• 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'm back again :D with a new question :) can you explain me the issue here?

<set xpath="/blocks/block[@name=terrDesertGround]/drop[@name=resourceClayLump]/@count">3,5</set>

Looks like the code dosen't accept digits with a comma between, but i though count="3,5" means i get a amount between 3 and 5
DesertGround doesn't have resourceClayLump yet. It has resourceCrushedSand.

This should add the new line:

Code:
<append xpath="/blocks/block[@name='terrDesertGround']">
    	<drop event="Fall" name="resourceClayLump" count="3,5" prob="0.5" stick_chance="0"/>

</append>
 
I've tried every combination with the <remove xpath> that I can think of but still can't get it to work. Any help would be greatly appreciated. I would like to remove the highlighted section of the code below. Thanks in advance. :upset:

<block name="cntBusSchool">

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

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

<property name="Class" value="CarExplodeLoot"/>

<property name="LootList" value="19"/>

<property name="Shape" value="ModelEntity"/>

<property name="Path" value="solid"/>

<property name="Model" value="Entities/Vehicles/busPrefab"/>

<property name="Place" value="TowardsPlacer"/>

<property name="MultiBlockDim" value="3,4,12"/>

<property name="ActivationDistance" value="15"/>

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

<property name="BigDecorationRadius" value="5"/>

<property name="CanDecorateOnSlopes" value="false"/>

<property name="ShowModelOnFall" value="false"/>

<property name="RandomTintColor1" value="188,148,20" param1="bus"/>

<property name="Collide" value="sight,movement,melee,bullet,arrow,rocket"/>

<property class="Explosion">


<property name="ParticleIndex" value="4"/> <!-- which prefab/particle is used -->



<property name="RadiusBlocks" value="5"/> <!-- damage radius for blocks -->



<property name="BlockDamage" value="5000"/> <!-- damage for blocks in the center of the explosion -->



<property name="RadiusEntities" value="5"/> <!-- damage radius for entities -->



<property name="EntityDamage" value="70"/> <!-- damage for entities in the center of the explosion -->



</property>


<drop event="Harvest" name="resourceLeather" count="2,7" prob="0.5" tag="allHarvest"/>

<drop event="Harvest" name="resourceScrapIron" count="10,20" tag="allHarvest"/>

<drop event="Harvest" name="terrStone" count="0" tool_category="Disassemble"/>

<drop event="Harvest" name="resourceHeadlight" count="1" prob="0.2" tag="salvageHarvest"/>

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

<drop event="Harvest" name="resourceMechanicalParts" count="0,3" prob="0.1" tag="salvageHarvest"/>

<drop event="Harvest" name="resourceElectricParts" count="0,2" prob="0.1" tag="salvageHarvest"/>

<drop event="Harvest" name="resourceElectricParts" count="0,2" prob="0.1" tag="salvageHarvest"/>

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

<property name="FilterTags" value="floot"/>

</block>

 
Does this work for you?

Code:
<remove xpath="/blocks/block[@name='cntBusSchool']/property[@class='Explosion']" />
 
I'm trying to add skill point rewards to more quests. I tried using this in xpath

<insertAfter xpath="/quests/quest[@id=challenge_silenceofthelambs]" >

<reward type="SkillPoints" value="1" />

</insertAfter>

It throws an error when i load up a game though

ERR CML loader: Loading and parsing 'quests.xml' failed

Exception: Unrecognized xml element reward

 
I'm trying to add a weapon in the game

ModLet and the correct one so

Is this sure icon like that?

Code:
Machete Of God\Config\items.xml
-------------------------------------------------------------------------------------------
<configs>
<!-- [color="#00FF00"]Machete Of God[/color] -->
<append xpath="/items">	

<item name="MacheteOfGod">	
<property name="Tags" value="knife,melee,light,weapon,meleeWeapon,perkDeepCuts,perkTheHuntsman"/>
<property name="DisplayType" value="melee"/>
<property name="CustomIcon" value="MacheteOfGod"/>
<property name="HoldType" value="47"/>
<property name="Meshfile" value="Items/Weapons/Melee/Knives/machetePrefab"/>
<property name="Material" value="Mmetal"/>
<property name="RepairTools" value="resourceForgedSteel"/>
<property name="DegradationBreaksAfter" value="false"/>
<property name="EconomicValue" value="600"/>
<property name="SoundJammed" value="ItemNeedsRepair"/>
<property name="SoundDestroy" value="wooddestroy1"/>
<property name="Weight" value="200"/>
<property name="Group" value="Ammo/Weapons"/>
<property name="ActionSkillGroup" value="Blade Weapons"/>
<property name="CraftingSkillGroup" value="craftSkillWeapons"/>
<property name="RepairExpMultiplier" value="5.5"/>

<property class="Action0">
	<property name="Class" value="DynamicMelee"/>
	<property name="Damage_type" value="Slashing"/>
	<property name="Sphere" value="0.15"/>   
	<property name="Sound_start" value="swoosh"/>
	<property name="ToolCategory.Butcher" value="0" param1="4"/>
	<property name="ToolCategory.harvestingTools" value="40.0" param1="2"/>
	<property name="Sound_harvesting" value="open_animal" param1="organic"/>
</property>
<property class="Action1">
	<property name="Class" value="DynamicMelee"/>
	<property name="Damage_type" value="Slashing"/>
	<property name="Sphere" value="0.15"/>
	<property name="Sound_start" value="swoosh"/>
	<property name="ToolCategory.Butcher" value="0" param1="4"/>
	<property name="ToolCategory.harvestingTools" value="40.0" param1="2"/>		
	<property name="Sound_harvesting" value="open_animal" param1="organic"/>
	<property name="UsePowerAttackAnimation" value="true"/>
</property>

<effect_group name="Base Effects">
	<passive_effect name="MaxRange" operation="base_set" value="50.0"/>
	<passive_effect name="BlockRange" operation="base_set" value="50"/>
	<passive_effect name="EntityDamage" operation="base_set" value="2000"/> [color="#00FF00"]<!-- meleeToolMachete -->[/color]
	<passive_effect name="BlockDamage" operation="base_set" value="20000"/>
	<passive_effect name="AttacksPerMinute" operation="base_set" value="100"/> [color="#00FF00"]<!-- 100 2 por segundo ok -->[/color]
	<passive_effect name="HarvestCount" operation="base_set" value="10" tags="butcherHarvest"/>	[color="#00FF00"]<!-- 10=2000 2=500 de CARNE COURO -->[/color]	
	<passive_effect name="HarvestCount" operation="base_set" value="2" tags="oreWoodHarvest"/>	[color="#00FF00"]<!-- 10=2000 2=500 de cada minerio -->[/color]	
	<passive_effect name="StaminaLoss" operation="base_set" value="0" tags="primary"/>
	<passive_effect name="DegradationMax" operation="base_set" value="300,800" tier="1,6"/>
	<passive_effect name="DegradationPerUse" operation="base_set" value="0"/>	[color="#00FF00"]<!-- DegradationPerUse  e ZERO 0 -->[/color]		
	<passive_effect name="ModSlots" operation="base_set" value="0,5" tier="1,6"/>
	<passive_effect name="ModPowerBonus" operation="perc_add" value=".15" tags="EntityDamage,BlockDamage"/>
	<passive_effect name="ModPowerBonus" operation="base_add" value="200" tags="EconomicValue"/>
</effect_group>
<effect_group name="Power Attack">
	<passive_effect name="EntityDamage" operation="perc_add" value="100" tags="secondary"/>
	<passive_effect name="BlockDamage" operation="perc_add" value="1" tags="secondary"/>
	<passive_effect name="AttacksPerMinute" operation="perc_subtract" value="0" tags="secondary"/>
	<passive_effect name="StaminaLoss" operation="base_add" value="21" tags="secondary"/>

	<triggered_effect trigger="onSelfSecondaryActionStart" action="PlaySound" target="self" sound="player1painlg">
		<requirement name="RandomRoll" seed_type="Random" target="self" min_max="0,100" operation="LTE" value="70"/>
		<requirement name="IsMale" target="self"/>
	</triggered_effect>
	<triggered_effect trigger="onSelfSecondaryActionStart" action="PlaySound" target="self" sound="player2painlg">
		<requirement name="RandomRoll" seed_type="Random" target="self" min_max="0,100" operation="LTE" value="70"/>
		<requirement name="IsMale" target="self" invert="true"/>
	</triggered_effect>
</effect_group>
</item>

</append>
</configs>

-----------------------------------------------------------------------------------------------------

Machete Of God\Config\recipes.xml

<configs>
<append xpath="/recipes">

	<recipe name="MacheteOfGod" count="1">
	     <ingredient name="resourceForgedIron" count="1"/>
             <ingredient name="resourceWood" count="1"/>
             <ingredient name="resourceLeather" count="1"/>
	</recipe>

	<recipe name="gunPistolAdmin" count="1">
		<ingredient name="resourceForgedIron" count="1"/>
                <ingredient name="resourceWood" count="1"/>
                <ingredient name="resourceLeather" count="1"/>
	</recipe>

</append>
</configs>
----------------------------------------------------------------------------------------------
Someone to help me?

 
Last edited by a moderator:
I'm trying to add skill point rewards to more quests. I tried using this in xpath
<insertAfter xpath="/quests/quest[@id=challenge_silenceofthelambs]" >

<reward type="SkillPoints" value="1" />

</insertAfter>

It throws an error when i load up a game though

ERR CML loader: Loading and parsing 'quests.xml' failed

Exception: Unrecognized xml element reward
insertAfter with that xpath is adding it before the node:

Code:
<!-- CHALLENGES -->
<reward type="SkillPoints" value="1" />

<quest id="challenge_silenceofthelambs">
	<property name="name_key" value="challenge_silenceofthelambs" />
	<property name="subtitle_key" value="challenge_silenceofthelambs_subtitle" />
what you probably want to do is append it. So try updating your insertAfter's with append

 
I'm trying to add a weapon in the gameModLet and the correct one so

Is this Serto icon like that?

-- snip --

----------------------------------------------------------------------------------------------
This looks okay at a glance. Are you having an issue with it?

 
Does this work for you?

Code:
<remove xpath="/blocks/block[@name='cntBusSchool']/property[@class='Explosion']" />
I tried that one first cause it made sense to me too and it didn't but I will try again right now to see if I messed it up somehow

***EDIT:

So I just tried it again this way with no luck it still blows up. I even tried it this way too.

<remove xpath="/blocks/block[@name=cntBusSchool]" />

<property class="Explosion">

<property name="ParticleIndex" value="4"/> <!-- which prefab/particle is used -->

<property name="RadiusBlocks" value="5"/> <!-- damage radius for blocks -->

<property name="BlockDamage" value="500"/> <!-- damage for blocks in the center of the explosion -->

<property name="RadiusEntities" value="5"/> <!-- damage radius for entities -->

<property name="EntityDamage" value="70"/> <!-- damage for entities in the center of the explosion -->

</property>

</remove>

 
Last edited by a moderator:
I tried that one first cause it made sense to me too and it didn't but I will try again right now to see if I messed it up somehow
***EDIT:

So I just tried it again this way with no luck it still blows up. I even tried it this way too.

<remove xpath="/blocks/block[@name=cntBusSchool]" />

<property class="Explosion">

<property name="ParticleIndex" value="4"/> <!-- which prefab/particle is used -->

<property name="RadiusBlocks" value="5"/> <!-- damage radius for blocks -->

<property name="BlockDamage" value="500"/> <!-- damage for blocks in the center of the explosion -->

<property name="RadiusEntities" value="5"/> <!-- damage radius for entities -->

<property name="EntityDamage" value="70"/> <!-- damage for entities in the center of the explosion -->

</property>

</remove>
I copy and pasted the line I wrote, and it works as expected. Can you post your output_log.txt? Maybe there's another issue we aren't seeing.

 
You know what I had a complete brain fart dude...Lol. I tested the code using the 'cntBusSchool' block but when I got in game I tested it with the full car...Haven't been getting much sleep lately and it is showing. Thank you for your help...Lol. If I would have paid attention to what I was doing I would have had it on my very first try...duh

 
You know what I had a complete brain fart dude...Lol. I tested the code using the 'cntBusSchool' block but when I got in game I tested it with the full car...Haven't been getting much sleep lately and it is showing. Thank you for your help...Lol. If I would have paid attention to what I was doing I would have had it on my very first try...duh
No worries; I'm just glad you got it sorted.

 
insertAfter with that xpath is adding it before the node:

Code:
<!-- CHALLENGES -->
<reward type="SkillPoints" value="1" />

<quest id="challenge_silenceofthelambs">
	<property name="name_key" value="challenge_silenceofthelambs" />
	<property name="subtitle_key" value="challenge_silenceofthelambs_subtitle" />
what you probably want to do is append it. So try updating your insertAfter's with append
Ok, i actually just got it to work by adding /objective to the insert after. However now it is rewarding to many skill points, it gives 4. Even the starter quest is rewarding 4 even with a value of 10. I changed the value to .25 but it throws an error and you lose the quest. Is this reward a fixed value that I can't adjust?

 
Last edited by a moderator:
Ok, i actually just got it to work by adding /objective to the insert after. However now it is rewarding to many skill points, it gives 4. Even the starter quest is rewarding 4 even with a value of 10. I changed the value to .25 but it throws an error and you lose the quest. Is this reward a fixed value that I can't adjust?
in Game, can you type in exportcurrentconfigs and look at the quests.xml in your save game folder. Then you can see if it did what you expected.

 
Hmmm. First time modding and this doesn't work.

Code:
<set xpath="/items/item[@name='meleeToolChainsaw' and @name='meleeToolAuger']/property[@name='MagazineSize']/@value">5000</set>
this is what it shows on my F1 console. The guy in page 4 with the jar works fine. :/

22.jpg

 
Your path is wrong and as far as I know your use of "and" is incorrect. "and" would need to include both chainsaw and auger, "or" might work but I have never tried anything with it though I am just learning myself.

In any case this works on b238

Code:
<set xpath="/items/item[@name='meleeToolChainsaw']/effect_group/passive_effect[@name='MagazineSize']/@value">5000</set>
<set xpath="/items/item[@name='meleeToolAuger']/effect_group/passive_effect[@name='MagazineSize']/@value">5000</set>
 
Back
Top