• 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:
Oops, missed the <append xpath="/items"> in the second block of code.  Point is, that code was working before I started messing with it again. lol

 
Ok guys, please disregard my previous posts.  With some trial and error, and some help from KhaineGB, I figured out how to make it work.  The main goal of my mod was simply to stop the shotguns from demolishing wooden buildings while raiding them.  That meant I needed a way to drastically lower the damage to wood.  Here is the code I came up with to make it work.

<!-- Line 1 changes the block damage of the shotgun ammo -->
<set xpath="/items/item[@name='ammoShotgunShell']/effect_group[@name='ammoShotgunShell']/passive_effect[@name='BlockDamage'][@value='5.4']/@value">1.5</set>
<!-- Line 2 removes the 3rd line of PASSIVE_EFFECT from the shotgun ammo. Since the third line is the one that directly effects damage to wood -->
<remove xpath="/items/item[@name='ammoShotgunShell']/effect_group[@name='ammoShotgunShell']/passive_effect[3]"/>


I figured there is no need to change the value of the second line of block damage, since it only added more block damage if hitting a wood block, and I needed to reduce the damage to wood blocks, removing that line completely works even better.

Took me way too long to figure this one out, but I am happy that I stuck with it.

 
Novice Question

Not sure if this is the right place for this....

How can I make this work? 

<triggered_effect trigger="onSelfHarvestBlock" action="ModifyCVar" cvar="X" operation="add" value="1"/>                 

<triggered_effect trigger="onSelfHarvestBlock" action="SetProgressionLevel" progression_name="perkDancing" level="@X"/>

I get an error: "ERR XML loader: Loading and parsing 'progression.xml' failed
FormatException: Input string was not in the correct format: nDigits == 0."

 
Got what SHOULD be a quick and easy one for you guys.  Looking to have traders restock daily, since they say they get new stuff every day I figure its high time they actually do.  While I'm at it, since it's the Zombie Apocalypse, I figure the traders should have extended hours and be open 24 hours.  That said, does the following code look right to you guys?  I'm not at home and cannot test it right now.  Thanks.

<!-- Changing the reset interval for traders using OR. Trader IDs are 1 = Joel, 2 = Jen, 3 = Player Owned Vending Machine,
4 = World Spawn Vending Machine, 5 = Rented Vending Machine, 6 = Bob, 7 = Hugh, 8 = rekt. -->
<set xpath="traders/trader_info[@id='1' or @id='2' or @id='6' or @id='7' or @1d='8']/@reset_interval">1</set>

<!-- Remove Trader open and close times to make the trader stay open 24 hours. -->
<remove xpath="traders/trader_info[@id='1' or @id='2' or @id='6' or @id='7' or @id='8']/@close_time"/>
<remove xpath="traders/trader_info[@id='1' or @id='2' or @id='6' or @id='7' or @id='8']/@open_time"/>




P.S.

I already have these changes modded using individual lines for each trader, but I wanted to see if I could get it to work with the use of OR.  Thanks again!

 
I'm not sure where to begin for the next thing I want to tweak.  If you guys might be able to point me in the right direction, I would appreciate it.  First, some quick backstory.

While raiding POIs I'll go from room to room doing my best to clear each room with stealth attacks.  With alpha 19 and 19.1 though, there are times when the zombies do not spawn until you are inside the room.  Its as though there spawn isn't being triggered when it should be.  This issue is especially prevalent when dropping into a room from the floor above.  For instance, I will use arrows to open the zombie cabinets and the cabinet will be empty.  The room containing the cabinet will not have any zombies in it either.  As soon as I land in the room, the zombies spawn.   Where would I start looking to modify this so that I can make sure the zombies spawn into a POI before I walk in?  Basically, I want the whole POI to spawn its zombie inhabitants all at once instead of room by room.  Or at the very least increase the distance that the spawn spot triggers at and spawns in the zombie.

 
<gamestage stage="64"> <spawn group="feralHordeStageGS54" num="21" maxAlive="8" duration="2" interval="38" /> <spawn group="feralHordeStageGS59" num="21" maxAlive="8" duration="2" /> <spawn group="feralHordeStageGS64" num="21" maxAlive="8" duration="2" /> <spawn group="ZombiesNight" num="65" maxAlive="1" /> </gamestage>
No longer the vanilla entry!

 
Ok, need some help ironing out a couple of issues with a mod I created.  Basically, I made an item called SuperShades that combines all of the eyewear except the Night Vision Goggles into one set of glasses.  They work, I can get a pair through the creative menu, but nothing shows up on the display to tell you what stats they effect or by how much.  Also, the name that pops up in game when hovering over these shades is apparelsupershades instead of Super Shades.  Here is the code for it.  Would greatly appreciate any assistance with this.

<SuperShades>

<!-- Create NEW Super Shades! In-Game icon will be the same as "Shades". To be put in items.xml -->
<append xpath="items">
<item name="SuperShades">
<property name="Extends" value="apparelShades"/>
<property name="DisplayType" value="apparelSuperShades"/>
<property name="CustomIcon" value="apparelShades"/>
<property name="EconomicValue" value="1500"/>
<property name="CustomIconTint" value="30,30,30"/>
<property name="Tags" value="head,clothing,canHaveCosmetic,noMods"/>
<property class="UMA">
<property name="Overlay0Tint" value="30,30,30"/>
</property>
<effect_group tiered="false">
<passive_effect name="ModSlots" operation="base_set" value="0"/>
<passive_effect name="AttributeLevel" operation="base_add" value="1" tags="attIntellect"/>
<display_value name="dIntellect" value="+1"/>
<passive_effect name="AttributeLevel" tags="attFortitude" operation="base_add" value="1"/>
<display_value name="dFortitude" value="+1"/>
<passive_effect name="AttributeLevel" tags="attPerception" operation="base_add" value="1"/>
<display_value name="dPerception" value="+1"/>
<passive_effect name="AttributeLevel" tags="attAgility" operation="base_add" value="1"/>
<display_value name="dAgility" value="+1"/>
<passive_effect name="AttributeLevel" tags="attStrength" operation="base_add" value="1"/>
<display_value name="dStrength" value="+1"/>
<passive_effect name="CraftingTime" operation="perc_add" value="-.2"/>
<passive_effect name="PlayerExpGain" operation="perc_add" value=".15"/>
<display_value name="dCraftingTime" value="-.2"/>
<display_value name="dPlayerExpGain" value=".15"/>
<passive_effect name="LootGamestage" operation="base_add" value="3,5.2"/>
<passive_effect name="TreasureBlocksPerReduction" operation="base_add" value="-1"/>
<display_value name="dTreasureBlocksPerReduction" value="-1"/>
<passive_effect name="BarteringBuying" operation="base_add" value=".2"/>
<passive_effect name="BarteringSelling" operation="base_add" value=".2"/>
</effect_group>
</item>
</append>

</SuperShades>


Second half of my issue is the loot.xml file I created to, in theory, allow the new shades to drop in game like the rest of the eyewear.  For that, I get an error code with the following xml file: 

<SuperShades>

<!-- Append loot.xml file to get new Super Shades to drop. Added New Super Shades to all loot groups where other eyewear is located. Presuming that by dong this, the new Super Shades will have the same chance to drop as all other eyewear? -->

<append xpath="/loot">
<lootgroup name="groupApparelFaceCover">
<item name="apparelSuperShades" mods="dye" mod_chance="0"/> <!-- Add Super Shades to groupApparelFaceCover lootgroup -->
</append>

<append xpath="/loot">
<lootgroup name="sportingGoods">
<item name="apparelSuperShades" prob=".7"/> <!-- Add Super Shades to sportingGoods lootgroup -->
</append>

<append xpath="/loot">
<lootgroup name="cothingTestLoot">
<item name="apparelSuperShades" mods="dye" mod_chance="0"/> <!-- Add Super Shades to clothingTestLoot lootgroup -->
</append>

</SuperShades>


The error states that the lootgroup on line 3 does not match the closing /append.  I tried changing line 3 to be <lootgroup name="groupApparelFaceCover"/> fixes the error, but I get three WRN messages, each one stating that the <append xpath="/loot"> was not applied.  I'm guessing I get 3 warning since I actually changed lines 3, 8, and 13 since I figured all 3 would error out.

Any help would be greatly appreciated.

 
Don't know about your first issue, but your second one is about closing elements correctly, as the original error stated.  You need this kind of structure:

<append>

   <lootgroup>

      <item />  <--  this is a self-closing element.

   </lootgroup>  <-- this closes the lootgroup element, which you're missing

</append>

 
Don't know about your first issue, but your second one is about closing elements correctly, as the original error stated.  You need this kind of structure:

<append>

   <lootgroup>

      <item />  <--  this is a self-closing element.

   </lootgroup>  <-- this closes the lootgroup element, which you're missing

</append>
Thanks Ricowan, I noticed that shortly after I made this post.  I fixed the code to be:
 

<SuperShades>
<!-- Append loot.xml file to get new Super Shades to drop. Added New Super Shades to all loot groups where other eyewear is located. Presuming that by dong this, the new Super Shades will have the same chance to drop as all other eyewear? -->

<append xpath="/loot">
<lootgroup name="groupApparelFaceCover">
<item name="apparelSuperShades" mods="dye" mod_chance="0"/> <!-- Add Super Shades to groupApparelFaceCover lootgroup -->
</lootgroup>
</append>

<append xpath="/loot">
<lootgroup name="sportingGoods">
<item name="apparelSuperShades" prob=".7"/> <!-- Add Super Shades to sportingGoods lootgroup -->
</lootgroup>
</append>

<append xpath="/loot">
<lootgroup name="cothingTestLoot">
<item name="apparelSuperShades" mods="dye" mod_chance="0"/> <!-- Add Super Shades to clothingTestLoot lootgroup -->
</lootgroup>
</append>
</SuperShades>


No more errors, but now I get WRN on all three <append xpath="/loot"> lines of code and they do not get applied.  So it's "fixed" yet still not working.  I'll have to dig deeper into the loot.xml file of the vanilla game to try and figure out what I am doing wrong.  I have looked at other mod's xml files for similar stuff, but that's how I got to where we are right now. lmao

Thanks again for any help you all can offer.

 
It looks like you're trying to add your new lootgroups to an element named "loot", but that doesn't exist in the loot.xml file.  The root node in that file is "lootcontainers".

What happens if you change <append xpath="/loot"> to <append xpath="/lootcontainers"> ?

 
It looks like you're trying to add your new lootgroups to an element named "loot", but that doesn't exist in the loot.xml file.  The root node in that file is "lootcontainers".

What happens if you change <append xpath="/loot"> to <append xpath="/lootcontainers"> ?
I'll give that a try when I get home.  Thanks for the idea.  Will let you know how it pans out.

 
Update, changing the root node did fix it, partially.  Now I get an error stating that there are multiple instances of groupApparelFaceCover.  Just to see if that was going to be the only issue, I commented that block of code out, and it gave the same error, except now it said sportingGoods.  I checked through the loot.xml file for the Vanilla game, and there are exactly two groupApparelFaceCover, one that defines <lootgroup name="groupApparelFaceCover"> and one that adds that loot group to <lootgroup name="groupApparelClothes">.  It is a similar situation with <lootgroup name="sportingGoods">, there is the block that defines the lootgroup, then there is another block where the lootgroup is added to a loot container.

Vanilla loot.xml references:

<lootgroup name="groupApparelFaceCover"> Defines the loot group on line 1307

<lootgroup name="groupApparelFaceCover"> Added to loot group on line 1337

<lootgroup name="sportingGoods">  Defines the loot group on line 2868

<lootgroup name="sportingGoods">  Added to loot container on line 3845

Again, I am trying to get my new item to drop in the same loot containers that would drop the other glasses in the game.  All of the other glasses are part of three loot groups.  <lootgroup name="groupApparelFaceCover">  ,   <lootgroup name="sportGoods">  and  <lootgroup name="clothingTestLoot">

I'm at a loss right now and I assume that without getting this code to work, the only way I will ever see my new shades in the game is by using Creative Mode to get them.  I'm sure I am missing something, but I have no idea what it could be.

 
OK, so if the lootgroup elements already exist, then you only need to append your new item to those existing elements:

<append xpath="/lootcontainers/lootgroup[@name='groupApparelFaceCover']">
    <item name="apparelSuperShades" mods="dye" mod_chance="0"/>        <!-- Add Super Shades to groupApparelFaceCover lootgroup -->
</append>
 

etc.

 
OK, so if the lootgroup elements already exist, then you only need to append your new item to those existing elements:

<append xpath="/lootcontainers/lootgroup[@name='groupApparelFaceCover']">
    <item name="apparelSuperShades" mods="dye" mod_chance="0"/>        <!-- Add Super Shades to groupApparelFaceCover lootgroup -->
</append>
 

etc.
That worked!  Thank you Ricowan for your help.  Now the new shades are in the game, they "should" drop in game, I still need to verify that but that could take a while.  Now it's just a matter of getting the stats to show up on the shades in game.  The stats are applied to the shades just fine, they just are not listed on the display when you look at the shades in game.

 
Just figured I would pop back into the thread to let you guys know, I got the display properties working for my new shades!  It doesn't list all the stats, but it shows me the important ones so I can tell which pair will be better.  The only thing left to confirm is that they are dropping in game.  Since I fixed the issues with that block of code I haven't really seen many glasses drop, maybe 2 or 3 total, so we're still testing that.

On a side note, anyone have any ideas how I can maybe use creative to spawn in a loot container that has a chance of dropping eyewear?  Or know a way that I can maybe force them to spawn so I can verify that they drop?

 
Can anyone point me to information about making changes to vanilla Localization in my mod? All I can find is info on adding new items. I made a mod to change crafting perks and I want to modify the Localization in my mod to reflect the changes, but what I have does not change anything.

 Example of the header and one line that I am currently hacking at trying.

key,source,context,changes,english,
perkLightArmorRank1LongDesc,progression,perk Agi,"You have started on the path of the lightly armored warrior. Craft quality 3 fair light armor, reduce light armor movement penalty by 15% and stamina penalty by 10%. Improve durability by 50%.\nUnlocks leather armor crafting.",

 
Can anyone point me to information about making changes to vanilla Localization in my mod? All I can find is info on adding new items. I made a mod to change crafting perks and I want to modify the Localization in my mod to reflect the changes, but what I have does not change anything.

 Example of the header and one line that I am currently hacking at trying.

key,source,context,changes,english,
perkLightArmorRank1LongDesc,progression,perk Agi,"You have started on the path of the lightly armored warrior. Craft quality 3 fair light armor, reduce light armor movement penalty by 15% and stamina penalty by 10%. Improve durability by 50%.\nUnlocks leather armor crafting.",
You can just write
key,english

 
Last edited by a moderator:
Is it possible to change

<property name="RepairTools" value="resourceRepairKit"/>


with one line to 

<property name="RepairTools" value="gunMGT1AK47Parts"/>


if

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


?

Also, how to create multiple not(contains ) in one line?

Code:
<item name="gunMGT1AK47">
	<property name="Tags" value="weapon,ranged,holdBreathAiming,reloadPenalty,gun,barrelAttachments,sideAttachments,smallTopAttachments,mediumTopAttachments,stock,magazine,drumMagazine,firingMode,bottomAttachments,attFortitude,perkMachineGunner,perkBookAutoWeapons,canHaveCosmetic"/>
	<property name="DisplayType" value="rangedGun"/>
	<property name="HoldType" value="48"/>
	<property name="Meshfile" value="#Other/Items?Weapons/Ranged/ak47/ak47Prefab.prefab"/>
	<property name="Material" value="MMachineGunParts"/> <property name="Weight" value="4"/>

	<property name="CrosshairOnAim" value="true"/> <!-- aimTest -->
	<property name="CrosshairUpAfterShot" value="true"/> <!-- aimTest -->

	<property name="RepairTools" value="resourceRepairKit"/>
	<property name="DegradationBreaksAfter" value="false"/>

	<property name="SoundJammed" value="weapon_jam"/>
	<property name="Sound_Sight_In" value="rifle_sight_in"/>
	<property name="Sound_Sight_Out" value="rifle_sight_out"/>

	<property name="RepairExpMultiplier" value="10.8"/>
	<property name="EconomicValue" value="500"/>
	<property name="UnlockedBy" value="perkMachineGunner,gunMGT1AK47Schematic"/>
	<property name="ShowQuality" value="true"/>
	<property name="Group" value="Ammo/Weapons"/>

	<property class="Action0">
		<property name="Class" value="Ranged"/>
		<property name="Delay" value=".150"/> <!-- obsolete if rounds per minute exists -->
		<property name="Magazine_items" value="ammo762mmBulletBall,ammo762mmBulletHP,ammo762mmBulletAP"/>
		<property name="Sound_start" value="ak47_fire"/>
		<property name="Sound_loop" value="ak47_fire"/>
		<property name="Sound_empty" value="dryfire"/>
		<property name="Sound_reload" value="ak47_reload"/>
		<property name="Sound_end" value="ak47_fire_end"/>
		<property name="Particles_muzzle_fire" value="gunfire_AK47"/>
		<property name="Particles_muzzle_fire_fpv" value="gunfire_AK47_fpv"/>
		<requirement name="CVarCompare" cvar="_underwater" operation="LT" value=".98"/>
	</property>
	<property class="Action1">
		<property name="Class" value="Zoom"/>
		<property name="Zoom_max_out" value="55"/>
		<property name="Zoom_max_in" value="55"/>
		<property name="ScopeCameraOffset" value="-.00062,0,.055"/>
	</property>
  ......
 
Last edited by a moderator:
  • Previous Page
  • Next Page
  • Previous Page
  • Next Page

Is it possible to change

<property name="RepairTools" value="resourceRepairKit"/>


with one line to 

<property name="RepairTools" value="gunMGT1AK47Parts"/>


Short answer for this is yes.  The code should look something like:
 

<config>
<set xpath="/items/item[@name='gunMGT1AK47']/property[@name='RepairTools']/@value">gunMGT1AK47Parts</set>
</config>


if

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


I'm not sure what your goal is with this condition.  But since you provided the block of code that defines the item "gunMGT1AK47" the code I provided to change the item needed to repair it should work.

  • Previous Page
  • Next Page
  • Previous Page
  • Next Page

 
I meant to change at once every <item /> that contains such Material property inside itself.

So that when adding a mod for a gigantic number of weapons, this all overlaps when it goes next (and it wasn't necessary to add mini-fixes, due to which hundreds of "yellow errors" appear)

 
Last edited by a moderator:
Back
Top