• If you have a mod, tool or prefab, please use the Resources section. Click Mods at the top of the forums.

XPath Modding Explanation Thread

This is a large amount of information in these posts. I'll be working on a full, properly formed tutorial as we get access to A17 and we can really make the xpath system shine. I've listed some examples here, and we'll be posting a ton more xpath samples over the coming weeks, as we port the SDX modlets over to use the native hooks.

By all means, begin posting your comments, questions, or requests for clarity.

Since we now know that xpath support will be built-into the vanilla base game, and discussions earlier were getting a bit confusing, I've decided to make a new thread to try to demystify xpath and what it'll mean for mods and modders going forward in A17. The information in this thread has been pieced together from forum and discord discussions. They may not be 100% accurate, but I will update this thread when we know the full implementation.

XPath is a way of adding, changing, or removing XML lines and nodes, without directly editing the XML files. It allows you to apply patches to the XML files without manually editing the vanilla XML files.

SDX has had partial support for this since its initial release, and a lot of the SDX Modlets are already written this way. We will be using some of the SDX's xpath as examples in this thread, but SDX is not required to do this in A17 and onwards.

I believe in using examples to explain concept, so in the next few posts, you'll see a mixture of explanation, along with sample xpath code.

The following Mod structure is expected for A17 and beyond:

Code:
Mods/
   <ModName>/
       Config/
       UIAtlases/ItemIconAtlas/
       ModInfo.xml

   <ModName2>/
       Config/
       ModInfo.xml
You will be able to have multiple mods loaded, and loading will occur as long as the ModInfo.xml exists. This is unchanged from what we've been doing doing with other alphas, with the exception of the Config folder.

This Config folder will support loading XML files, written using xpath, in the following folder structure:

Code:
Config/entityclasses.xml
Config/gamestages.xml
Config/items.xml
The files in the Config folder will not be a full copy of the vanilla file with your changes. Rather, it'll contain the changes you want done to the vanilla files. The files under the Config must match the vanilla file name. You cannot create an entityclasses2.xml file, and expect it to work. Any changes in the entityclasses.xml will have to be done in the same file. However, each mod can have its own entityclasses.xml.

During the game's initialization, it will perform the xpath merge in-memory only; no files will be actually be modified. This would allow us to remove mods we no longer want, without re-validating against steam, or previous copies of the xml. That's a big one. No more half merging of a mod, and not having it work, then trying to pull it back out.

What this means for us is that we'll be able to make a variety of smaller mods, which I've been calling modlets, which can add, remove and change smaller pieces of the game. They can be used together, or they could be added to an overhaul mod, in order to style your game play easier.

These modlets would also exists outside of the Data/Config folder, so if you have made direct XML changes in your Alpha 17.1 Data/Config files, and Steam updated the game to 17.2, you would have lost your changes, or would have to re-merge them in. We've all been there before. But if they existed as modlets, under the Mods folder, they would be safe. And as long as your xpath is still valid to the new XML, it should load up with no additional work on your part.

If we could use xyth's JunkItems modlet, which adds random, scrappable junk items to loot containers, and add them to Valmod Overhaul. Likewise, if Valmod Overhaul did not have the No Ammo modlet (which gives you the ability to unload a gun and get its bullets back without disassembling it), you could drop the NoAmmo modlet into your Mods folder. Headshots only? Want to increase stack sizes? Same deal.

With a properly constructed modlet, we'll be able to piece together new play styles for people to enjoy and share. A modder working on a large overhaul won't have to duplicate work. If they wanted to include the No Ammo mod, they wouldn't have to code it themselves, letting them focus on the bits that make their mod really unique.

Let's get started on your journey...

 
Last edited by a moderator:
I understand how to change the size of a loot container's loot box. What I don't understand is how to make a mod that edits the amount of each item in the loot container.

For example, I know

<set xpath="/lootcontainers/lootcontainer[@id=25]/@size">7,6</set>

will change the bird nest's loot box size to 7x6.

However, how do I change the amount of eggs and feathers gained from each bird's nest? I don't understand how to point to "resourceFeather" to change the count. I know I can easily change the XML itself. What I'm asking is how do I make a modlet to edit this?

<lootcontainer id="25" count="1,2" size="6,2" sound_open="UseActions/open_garbage" sound_close="UseActions/close_garbage" loot_quality_template="qualBaseTemplate">

<item name="foodEgg" prob="0.25"/>

<item name="resourceFeather" count="1,5" prob="0.75"/>

</lootcontainer>

I've tried

Code:
<config> <set xpath="/loot/lootcontainer[@id='25']/@name='resourceFeather'/@count">5,10</set> </config>
and many other things but nothing works. Can't find any other mods to reverse engineer to make this work, either.

 
Last edited by a moderator:
I understand how to change the size of a loot container's loot box. What I don't understand is how to make a mod that edits the amount of each item in the loot container.
For example, I know

<set xpath="/lootcontainers/lootcontainer[@id=25]/@size">7,6</set>

will change the bird nest's loot box size to 7x6.

However, how do I change the amount of eggs and feathers gained from each bird's nest? I don't understand how to point to "resourceFeather" to change the count. I know I can easily change the XML itself. What I'm asking is how do I make a modlet to edit this?

<lootcontainer id="25" count="1,2" size="6,2" sound_open="UseActions/open_garbage" sound_close="UseActions/close_garbage" loot_quality_template="qualBaseTemplate">

<item name="foodEgg" prob="0.25"/>

<item name="resourceFeather" count="1,5" prob="0.75"/>

</lootcontainer>

I've tried

Code:
<config> <set xpath="/loot/lootcontainer[@id='25']/@name='resourceFeather'/@count">5,10</set> </config>
and many other things but nothing works. Can't find any other mods to reverse engineer to make this work, either.
Your XPath starts with /loot/, which isn't a valid node. Shouldn't it be xpath="/lootcontainers/ ?

 
Your XPath starts with /loot/, which isn't a valid node. Shouldn't it be xpath="/lootcontainers/ ?
Is everything else right? I still get an error "XpathException: Expression must evaluate to a node-set" after changing it to

<config>

<set xpath="/lootcontainers[@id=25]/@name='resourceFeather'/@count">5,10</set>

</config>

I've tried <set xpath="/lootcontainers/lootcontainer[@id=25]/@name='resourceFeather'/@count">5,10</set> too and get the same error.

I'm just not clear on how to target the things beyond "[@id=25]" and its attributes.

 
Last edited by a moderator:
Is everything else right? I still get an error "XpathException: Expression must evaluate to a node-set" after changing it to
<config>

<set xpath="/lootcontainers[@id=25]/@name='resourceFeather'/@count">5,10</set>

</config>

I've tried <set xpath="/lootcontainers/lootcontainer[@id=25]/@name='resourceFeather'/@count">5,10</set> too and get the same error.

I'm just not clear on how to target the things beyond "[@id=25]" and its attributes.
Oh, sorry, I did misunderstand

The words in between the / / are nodes in the XML.

Code:
<lootcontainer id="25" count="1,2" size="6,2" sound_open="UseActions/open_garbage" sound_close="UseActions/close_garbage" loot_quality_template="qualBaseTemplate">
	<item name="foodEgg" prob="0.25"/>
	<item name="resourceFeather" count="1,5" prob="0.75"/>
</lootcontainer>
To reference the count, you want to do this:

xpath="/lootcontainers/lootcontainer[@id=25']/item[@name=resourceFeather]/@count"

The item itself is a node, that has a name, much like the lootcontainer has an id.

 
<config>

<set xpath="/lootcontainers/lootcontainer[@id=25']/item[@name=resourceFeather]/@count">5,10</set>

</config>

gives me an error upon loading "XmlException: name cannot begin with the "]" character, hexadecimal value 0x5D. Line 2, position 53" which I believe is referring to the "]" after @id='25'"]?

Edit: Figured it out, it was the " after '25'. Thanks for the help!

 
<config><set xpath="/lootcontainers/lootcontainer[@id=25']/item[@name=resourceFeather]/@count">5,10</set>

</config>

gives me an error upon loading "XmlException: name cannot begin with the "]" character, hexadecimal value 0x5D. Line 2, position 53" which I believe is referring to the "]" after @id='25'"]?

Edit: Figured it out, it was the " after '25'. Thanks for the help!
Sorry for the typo.

 
Hey guys,

I had a mod that added a skill book which was rewarded when completing quests. I tweaked it for A18 and it loads without any error, but the item is not listed in the creative menu and I can't figure out why.

Here's the mod code.

Code:
	<append xpath="/items">
	<item name="skillbook">
		<property name="CreativeMode" value="None"/>
		<property name="HoldType" value="21"/>
		<property name="Meshfile" value="Items/Misc/bookPrefab"/>
		<property name="DropMeshfile" value="Items/Misc/sack_droppedPrefab"/>
		<property name="Material" value="Mpaper"/>
		<property name="EconomicValue" value="1600"/>
		<property name="SellableToTrader" value="false"/>
		<property class="Action0">
			<property name="Class" value="Quest"/>
			<property name="Delay" value="0"/>
			<property name="QuestGiven" value="quest_SkillPointReward"/>
		</property>
		<property name="FuelValue" value="2"/>
		<property name="Weight" value="2"/>
		<property name="Group" value="Special Items"/>
		<property name="CreativeMode" value="None"/>
		<property name="name_key" value="Skill Point Book" />
		<property name="desc_key" value="Awards 2 Skill Points for that quest you just completed. Good job!\n\n*Pats you on the head*" />
		<property name="CustomIcon" value="challengeQuestMaster"/>
		<property name="CustomIconTint" value="9f9fff"/>
		<property name="Stacknumber" value="200"/>
	</item>
</append>
EDIT: Fixed, I realised it was set to not show in creative mode.

 
Last edited by a moderator:
Hey guys,
I had a mod that added a skill book which was rewarded when completing quests. I tweaked it for A18 and it loads without any error, but the item is not listed in the creative menu and I can't figure out why.

Here's the mod code.

Code:
	<append xpath="/items">
	<item name="skillbook">
		<property name="CreativeMode" value="None"/>
		<property name="HoldType" value="21"/>
		<property name="Meshfile" value="Items/Misc/bookPrefab"/>
		<property name="DropMeshfile" value="Items/Misc/sack_droppedPrefab"/>
		<property name="Material" value="Mpaper"/>
		<property name="EconomicValue" value="1600"/>
		<property name="SellableToTrader" value="false"/>
		<property class="Action0">
			<property name="Class" value="Quest"/>
			<property name="Delay" value="0"/>
			<property name="QuestGiven" value="quest_SkillPointReward"/>
		</property>
		<property name="FuelValue" value="2"/>
		<property name="Weight" value="2"/>
		<property name="Group" value="Special Items"/>
		<property name="CreativeMode" value="None"/>
		<property name="name_key" value="Skill Point Book" />
		<property name="desc_key" value="Awards 2 Skill Points for that quest you just completed. Good job!\n\n*Pats you on the head*" />
		<property name="CustomIcon" value="challengeQuestMaster"/>
		<property name="CustomIconTint" value="9f9fff"/>
		<property name="Stacknumber" value="200"/>
	</item>
</append>
EDIT: Fixed, I realised it was set to not show in creative mode.
Glad you got it resolved :)

 
Hey everyone, had a quick question.

Ive been making some modded configs (modlets) for my server, i've adjusted some Z using "set xpath" i've added some recipes and changed a few other bits. All works fine, the only thing i cant figure out is how to disable the food poisoning roll for some (specific) food items.

For instance "grilled meat"

https://pastebin.com/embed_js/phQEFZzt

This

https://pastebin.com/embed_js/hAhz8F0G

To This

i was trying to use the "set xpath" function, but its being a bit of a dog.

*edit* apparently i forgot how to insert things properly too :(

 
Hey everyone, had a quick question.Ive been making some modded configs (modlets) for my server, i've adjusted some Z using "set xpath" i've added some recipes and changed a few other bits. All works fine, the only thing i cant figure out is how to disable the food poisoning roll for some (specific) food items.

For instance "grilled meat"

https://pastebin.com/embed_js/phQEFZzt

This

https://pastebin.com/embed_js/hAhz8F0G

To This

i was trying to use the "set xpath" function, but its being a bit of a dog.

*edit* apparently i forgot how to insert things properly too :(
Did you want to remove the risk completely?

Here's a few examples that will get you close. You can add more to the xpath for more accuracy.

Code:
<set xpath="//triggered_effect[@cvar='.DiseaseRoll']/@value>0</>

<remove xpath="//triggered_effect[@cvar='.DiseaseRoll']" />

<remove xpath="//triggered_effect[@cvar='.DiseaseRoll' and @operation='set']" />
 
Did you want to remove the risk completely?
Here's a few examples that will get you close. You can add more to the xpath for more accuracy.

Code:
<set xpath="//triggered_effect[@cvar='.DiseaseRoll']/@value>0</>

<remove xpath="//triggered_effect[@cvar='.DiseaseRoll']" />

<remove xpath="//triggered_effect[@cvar='.DiseaseRoll' and @operation='set']" />
Thanks! will give that a try!

And yeah, was trying to remove it entirely for some food, and change some others. The Everything gives you food poisoning was a bit much for the people i usually play with, just a casual evening kind of crew lol :)

Thanks again!

 
Wouldnt ask if I havent tried & im proper stuck haha... Not even sure how to write this down so its understood but here goes....

The original Blocks.xml has the line <block name="steelMaster"> which has all the code needed to upgrade the Rconcrete block to steel... I need that block to be upgradable... so I tried using the following code...

<block name="steelMaster">

<property name="Group" value="Building,advBuilding"/>

<property name="DescriptionKey" value="steelBlockGroupDesc"/>

<property name="Material" value="Msteel"/>

<property name="DisplayType" value="blockHardened"/>

<property name="PassThroughDamage" value="true"/>

<property name="Texture" value="355,355,356,356,356,356"/>

<property name="CreativeMode" value="None"/>

<property class="RepairItems">

<property name="resourceForgedSteel" value="10"/>

</property>

<property class="UpgradeBlock">

<property name="ToBlock" value="Titanium Block"/>

<property name="Item" value="Forged Titanium"/>

<property name="ItemCount" value="10"/>

<property name="UpgradeHitCount" value="1"/>

</property>

<property name="CustomUpgradeSound" value="place_block_metal"/>

<drop event="Harvest" name="resourceRockSmall" count="25" tag="allHarvest"/>

<drop event="Destroy" count="0"/>

<drop event="Fall" name="terrDestroyedStone" count="1" prob="0.75" stick_chance="1"/>

<property name="EconomicValue" value="7"/>

<property name="FilterTags" value="fbuilding,fconcrete"/>

<property name="SortOrder1" value="40l0"/>

<property name="SortOrder2" value="0002"/>

</block>

Problem is when it loads its says 2 blocks with the same ID falling back to original block which obviously means my code is ignored & I get a red error... I know there must be a few ways of doing this but ive no idea how ,

What im trying to do is allow the Rconcrete blocks to be upgradable to a new Material (Titanium) which I already have working as a seperate block as that has a different name.. :(

any help would be greatfull...

 
Wouldnt ask if I havent tried & im proper stuck haha... Not even sure how to write this down so its understood but here goes....
The original Blocks.xml has the line <block name="steelMaster"> which has all the code needed to upgrade the Rconcrete block to steel... I need that block to be upgradable... so I tried using the following code...

<block name="steelMaster">

<property name="Group" value="Building,advBuilding"/>

<property name="DescriptionKey" value="steelBlockGroupDesc"/>

<property name="Material" value="Msteel"/>

<property name="DisplayType" value="blockHardened"/>

<property name="PassThroughDamage" value="true"/>

<property name="Texture" value="355,355,356,356,356,356"/>

<property name="CreativeMode" value="None"/>

<property class="RepairItems">

<property name="resourceForgedSteel" value="10"/>

</property>

<property class="UpgradeBlock">

<property name="ToBlock" value="Titanium Block"/>

<property name="Item" value="Forged Titanium"/>

<property name="ItemCount" value="10"/>

<property name="UpgradeHitCount" value="1"/>

</property>

<property name="CustomUpgradeSound" value="place_block_metal"/>

<drop event="Harvest" name="resourceRockSmall" count="25" tag="allHarvest"/>

<drop event="Destroy" count="0"/>

<drop event="Fall" name="terrDestroyedStone" count="1" prob="0.75" stick_chance="1"/>

<property name="EconomicValue" value="7"/>

<property name="FilterTags" value="fbuilding,fconcrete"/>

<property name="SortOrder1" value="40l0"/>

<property name="SortOrder2" value="0002"/>

</block>

Problem is when it loads its says 2 blocks with the same ID falling back to original block which obviously means my code is ignored & I get a red error... I know there must be a few ways of doing this but ive no idea how ,

What im trying to do is allow the Rconcrete blocks to be upgradable to a new Material (Titanium) which I already have working as a seperate block as that has a different name.. :(

any help would be greatfull...
What about something like..

Code:
<append xpath="/blocks/block[@name='steelMaster']" > 
   <property class="UpgradeBlock">
        <property name="ToBlock" value="Titanium Block"/>
        <property name="Item" value="Forged Titanium"/>
        <property name="ItemCount" value="10"/>
        <property name="UpgradeHitCount" value="1"/>
    </property>
</append>
 
Genius lol... I had ideas in my head but had NO idea how to actually code it... Thank You kind Sir :)

Must be doing something wrong cos when I go to upgrade the block (steelmaster) my Titanium icon shows up but nothing happens, like its asking me for the resource which I have but its not using it..

 
Last edited by a moderator:
Couldnt get it to work with that Code so something else must be wrong ?

This is the original code for the steelblock...

<block name="steelMaster">

<property name="Group" value="Building,advBuilding"/>

<property name="DescriptionKey" value="steelBlockGroupDesc"/>

<property name="Material" value="Msteel"/>

<!-- <property name="FallDamage" value="1.2"/> Nah, that would be evil, right? -->

<property name="DisplayType" value="blockHardened"/>

<property name="PassThroughDamage" value="true"/>

<property name="Texture" value="355,355,356,356,356,356"/>

<!-- <property name="ImposterExchange" value="imposterBlock" param1="112"/> -->

<property name="CreativeMode" value="None"/>

<property class="RepairItems"> <property name="resourceForgedSteel" value="8"/> </property>

<property name="CustomUpgradeSound" value="place_block_metal"/>

<drop event="Harvest" name="resourceScrapIron" count="15" prob="1" tag="allHarvest"/>

<drop event="Destroy" count="0"/>

<drop event="Fall" name="scrapMetalPile" count="1" prob="0.75" stick_chance="1"/>

<property name="EconomicValue" value="160"/>

<property name="DescriptionKey" value="steelBlockGroupDesc"/>

<property name="FilterTags" value="fbuilding,fsteel"/>

<property name="SortOrder1" value="40p0"/>

<property name="SortOrder2" value="0002"/>

</block>

 
Last edited by a moderator:
Couldnt get it to work with that Code so something else must be wrong ?
This is the original code for the steelblock...

<block name="steelMaster">

<property name="Group" value="Building,advBuilding"/>

<property name="DescriptionKey" value="steelBlockGroupDesc"/>

<property name="Material" value="Msteel"/>

<!-- <property name="FallDamage" value="1.2"/> Nah, that would be evil, right? -->

<property name="DisplayType" value="blockHardened"/>

<property name="PassThroughDamage" value="true"/>

<property name="Texture" value="355,355,356,356,356,356"/>

<!-- <property name="ImposterExchange" value="imposterBlock" param1="112"/> -->

<property name="CreativeMode" value="None"/>

<property class="RepairItems"> <property name="resourceForgedSteel" value="8"/> </property>

<property name="CustomUpgradeSound" value="place_block_metal"/>

<drop event="Harvest" name="resourceScrapIron" count="15" prob="1" tag="allHarvest"/>

<drop event="Destroy" count="0"/>

<drop event="Fall" name="scrapMetalPile" count="1" prob="0.75" stick_chance="1"/>

<property name="EconomicValue" value="160"/>

<property name="DescriptionKey" value="steelBlockGroupDesc"/>

<property name="FilterTags" value="fbuilding,fsteel"/>

<property name="SortOrder1" value="40p0"/>

<property name="SortOrder2" value="0002"/>

</block>
Sorry for the delay. The snippet works, in that its inserted in the right spot.

Does the ToBlock value point to an actual block? Does the Item point to an item that you use to upgrade it with?

 
Passing a variable to Animator error

Edit: I just checked the game code and saw that "AnimatotSet" functions don't accept CVars. :upset:

Hi

I am trying to pass an Int variable to the AnimationController but for some reason I get an error.

If I do:

Code:
   <triggered_effect trigger="onSelfPrimaryActionStart" action="ModifyCVar" target="self" cvar="TestCVar" operation="set" value="1"/>
   <triggered_effect trigger="onSelfPrimaryActionStart" action="AnimatorSetInt" target="self" property="TempProp" value="@TestCVar"/>
I get:

Code:
ERR XML loader: Loading and parsing 'items.xml' failed
FormatException: Input string was not in the correct format.
and if I do:

Code:
   <triggered_effect trigger="onSelfPrimaryActionStart" action="ModifyCVar" target="self" cvar="TestCVar" operation="set" value="1"/>
   <triggered_effect trigger="onSelfPrimaryActionStart" action="AnimatorSetFloat" target="self" property="TempProp" value="@TestCVar"/>
I get:

Code:
ERR XML loader: Loading and parsing 'items.xml' failed
FormatException: Unknown char: @ (input: '@TempCVar')
Basically these are the 2 lines that are causing it (actually the last line is causing it). For sake of testing I just created a new CVar and tried to pass it to the AnimationController.

If I pass a value like "3" it works fine. In this post from last year is noted that you can use a CVar for value with '@' in front of the name of the CVar and you can use it with Animator actions.

What am I doing wrong?

 
Last edited by a moderator:
<config><set xpath="/lootcontainers/lootcontainer[@id=25']/item[@name=resourceFeather]/@count">5,10</set>

</config>.

id=numbers or not in use anymore, or are they?

cant see them anywhere

if yes, where do i find the ids?

if no, the id is now the item/block name?

 
id=numbers or not in use anymore, or are they?
cant see them anywhere

if yes, where do i find the ids?

if no, the id is now the item/block name?
What do you mean by ids are not used anymore?

Loot containers have ids. Not everything is using ids. id is just a property as name is just a property. Some things in the XMLs have ids and some have names.

Here is example loot container from loot.xml:

Code:
<lootcontainer id="9" count="0,2" size="6,2" sound_open="UseActions/open_backpack" sound_close="UseActions/close_backpack" open_time="1.5" loot_quality_template="qualBaseTemplate">
<item group="backpacks"/>
</lootcontainer>
(this is from A18 BTW.)

 
Last edited by a moderator:
Back
Top