Jump to content

Modifying a buff via modlet - think I have the path wrong


BFT2020

Recommended Posts

So been working on some modding (just simple xml changes) that I can upload to new versions and not have to modify the individual xml config files every time the game is updated

 

So far, I got a customize traders file done and a progression file that are working as intended.

 

However, once I started working on a buffs file, I ran into the issue below that I can't figure out what I am doing wrong (though I believe it is a pathing issue on my part)

 

First, here is the error I get in the console

 

Quote

2021-09-07T20:48:20 748.531 WRN XML patch for "buffs.xml" from mod "Z-JeremyMod" did not apply: <set xpath="/buffs/buff[@name='buffDrugPainkillers']/effect_group/requirement/triggered_effect[@stat='Health']/@value" 

 

The previous times I got this error, it was a path issue (99.9% of the time, I either forgot something, inserted a space it didn't like, or mistyped the node path).

 

Here is the code

 

Quote

<set xpath="/buffs/buff[@name='buffDrugPainkillers']/effect_group/requirement[@cvar='$buffDrugPainkillersHealed']/triggered_effect[@stat='Health']/@value">0</set>

 

I am trying to change the painkiller health buff from 40 to 0.  I know this is the right location as making the change in the actual config file works.

 

Here is the specific part of the buffs file I am trying to modify

 

Quote

 

<buffs>

    <----SNIP----->

    <buff name="buffDrugPainkillers" name_key="buffDrugPainkillersName" description_key="buffDrugPainkillersDesc" icon="ui_game_symbol_pills">
         <----SNIP----->

        <effect_group>
            <requirement name="NotHasBuff" buff="buffInjuryConcussion"/>
            <requirement name="CVarCompare" cvar="$buffDrugPainkillersHealed" operation="Equals" value="0"/>
                <triggered_effect trigger="onSelfBuffUpdate" action="ModifyStats" stat="Health" operation="add" value="40"/>
                <triggered_effect trigger="onSelfBuffUpdate" action="ModifyCVar" cvar="$buffDrugPainkillersHealed" operation="set" value="1"/>
        </effect_group>

        <---SNOP----->
    </buff>

 


If someone could point out my mistake, that would be greatly appreciated.

 

Link to comment
Share on other sites

<set xpath="/buffs/buff[@name='buffDrugPainkillers']/effect_group[3]/triggered_effect[@stat='Health']/@value">0</set>

That should work. You don't need to mention the requirement property since that's not a node that actually contains the triggered effects. I added the [3] cuz in your example it's just going to any effect group i think.  Either that or it's going to the first effect group and stopping there. It's been so long so I don't remember... Unfortunately most of vanilla's effect groups aren't labeled, so using the number works, but should they change anything about them or the order, you'll have to recheck the code.

Not able to test, but lemme know if this works for ya!

Also.. As I say for everyone using xpath, I highly recommend using notepad++, then pressing ALT 0. This will collapse each node. Write them down as you open it, and there's your xpath ... path.

Edited by Telric (see edit history)
Link to comment
Share on other sites

14 hours ago, Telric said:

<set xpath="/buffs/buff[@name='buffDrugPainkillers']/effect_group[3]/triggered_effect[@stat='Health']/@value">0</set>

That should work. You don't need to mention the requirement property since that's not a node that actually contains the triggered effects. I added the [3] cuz in your example it's just going to any effect group i think.  Either that or it's going to the first effect group and stopping there. It's been so long so I don't remember... Unfortunately most of vanilla's effect groups aren't labeled, so using the number works, but should they change anything about them or the order, you'll have to recheck the code.

Not able to test, but lemme know if this works for ya!

Also.. As I say for everyone using xpath, I highly recommend using notepad++, then pressing ALT 0. This will collapse each node. Write them down as you open it, and there's your xpath ... path.

Thanks I will give it a try tonight if I have the time.

 

Yeah, I went the requirement route as I was trying to make sure it went to the correct effect group.  I did not realize that you can simply do the [3] to get it to go to the correct node within that property. 

 

And thanks for the reminder to recheck as newer updates get released.  That is something I already put in the back of my mind to do, but with TFP wanting to go Gold soon and release a final product, it shouldn't be too many times I would have to do that (plus, doing this coding myself means I am learning it and will be able to understand quickly if I need to make changes to my files after each update).  I read your thread in the Tutorials & Guide section, along with watching Max Fox's videos on xpath coding and downloading mods like Darkness Falls to see how others have done it; though nothing replaces just diving in and trying to write the code (and seeing how many red errors you get and yellow warning messages)  😁

 

I just started using notepad++ (it is what i am using to write these files as it allows me to quickly check to see if I mistyped something as I learn to use this program).  However, for some reason, I opened the original file in notepad and had to do the manual snips.  Now I am curious about the original file and will open it tonight using Notepad++.  I bet if I did it in the first place, that might have been easier to see the code structure than using regular old notepad. 

Link to comment
Share on other sites

On 9/7/2021 at 9:19 PM, Telric said:

in your example it's just going to any effect group i think.  Either that or it's going to the first effect group and stopping there.

 

XPath selects a collection of XML elements. It doesn't stop when it finds a match. (It's why people use selectors in the first place.)

 

For example, you could do this:

<set xpath="//triggered_effect[@stat='Health']/@value">0</set>

 

That will select all triggered_effect nodes with the "stat" attribute value of "health", and set all their "value" attribute values to zero, for all XML nodes in the file.

 

The double-slash means "any descendent of the currently selected element which matches, no matter how deep." (In this case it's the root node of the XML document.) It's useful for matching nodes that might or might not be a direct child of a node that you know how to target.

 

For example:

<set xpath="//buff[@name='buffDrugPainkillers']//triggered_effect[@stat='Health']/@value">0</set>

 

You might not know if the triggered effect is a descendent of a requirement node, or of an effect_group node, but it doesn't matter.

 

It's something to keep in mind for forwards compatibility. It obviously doesn't guarantee it will still work if TFP update the XML, but it helps.

Edited by khzmusik (see edit history)
Link to comment
Share on other sites

I will keep that in mind.  I have some changes I will be making in the loot file that a mass change would be easier to do than changing everything one by one.

 

I got the buff nerf to work and it tested out fine.  Nothing like lighting yourself on fire and not being able to instant recover by swallowing a white pill 😁

Link to comment
Share on other sites

So to expand on my modding skills, I am now modifying the loot xml file.  The first thing I am doing is changing the weapons and armor to basic resources (simulating that all you are finding are broken armor and weapons).  I think I am doing it right, but wanted to confirm.  I don't get any errors when I load up my test world, but not sure yet if the game is doing what I think it is doing:

 

First, what I think I am doing:

-At each loot group with cloth armor, I am replacing the armor with resourceCloth and setting up a count range of this resource.

 

Now my code.  Instead of individually changing each loot group with cloth armor in it, I just want to find each instance with the cloth armor and change it.

<config>
	<setattribute xpath="lootcontainers/lootgroup/item[@name='armorClothJacket']" name="count">3,6</setattribute>
	<setattribute xpath="lootcontainers/lootgroup/item[@name='armorClothPants']" name="count">3,6</setattribute>
	<setattribute xpath="lootcontainers/lootgroup/item[@name='armorClothBoots']" name="count">3,6</setattribute>
	<setattribute xpath="lootcontainers/lootgroup/item[@name='armorClothGloves']" name="count">3,6</setattribute>
	<setattribute xpath="lootcontainers/lootgroup/item[@name='armorClothHat']" name="count">3,6</setattribute>
	<set xpath="/lootcontainers/lootgroup/item[@name='armorClothJacket']/@name">resourceCloth</set>
	<set xpath="/lootcontainers/lootgroup/item[@name='armorClothPants']/@name">resourceCloth</set>
	<set xpath="/lootcontainers/lootgroup/item[@name='armorClothBoots']/@name">resourceCloth</set>
	<set xpath="/lootcontainers/lootgroup/item[@name='armorClothGloves']/@name">resourceCloth</set>
	<set xpath="/lootcontainers/lootgroup/item[@name='armorClothHat']/@name">resourceCloth</set>

</config>

In my mind, the game is updating all instances with Cloth Armor by:

-Attaching a new attribute count=3,6

-Replacing all instances with Cloth Armor with resourceCloth

Link to comment
Share on other sites

2 hours ago, BFT2020 said:

So to expand on my modding skills, I am now modifying the loot xml file.  The first thing I am doing is changing the weapons and armor to basic resources (simulating that all you are finding are broken armor and weapons).  I think I am doing it right, but wanted to confirm.  I don't get any errors when I load up my test world, but not sure yet if the game is doing what I think it is doing:

 

First, what I think I am doing:

-At each loot group with cloth armor, I am replacing the armor with resourceCloth and setting up a count range of this resource.

 

Now my code.  Instead of individually changing each loot group with cloth armor in it, I just want to find each instance with the cloth armor and change it.

<config>
	<setattribute xpath="lootcontainers/lootgroup/item[@name='armorClothJacket']" name="count">3,6</setattribute>
	<setattribute xpath="lootcontainers/lootgroup/item[@name='armorClothPants']" name="count">3,6</setattribute>
	<setattribute xpath="lootcontainers/lootgroup/item[@name='armorClothBoots']" name="count">3,6</setattribute>
	<setattribute xpath="lootcontainers/lootgroup/item[@name='armorClothGloves']" name="count">3,6</setattribute>
	<setattribute xpath="lootcontainers/lootgroup/item[@name='armorClothHat']" name="count">3,6</setattribute>
	<set xpath="/lootcontainers/lootgroup/item[@name='armorClothJacket']/@name">resourceCloth</set>
	<set xpath="/lootcontainers/lootgroup/item[@name='armorClothPants']/@name">resourceCloth</set>
	<set xpath="/lootcontainers/lootgroup/item[@name='armorClothBoots']/@name">resourceCloth</set>
	<set xpath="/lootcontainers/lootgroup/item[@name='armorClothGloves']/@name">resourceCloth</set>
	<set xpath="/lootcontainers/lootgroup/item[@name='armorClothHat']/@name">resourceCloth</set>

</config>

In my mind, the game is updating all instances with Cloth Armor by:

-Attaching a new attribute count=3,6

-Replacing all instances with Cloth Armor with resourceCloth

 

That looks correct, but there's an easier way to do it.

 

XPath comes with a "starts-with" function that you can use in your selectors. So that code could be rewritten like this:

 

<config>
	<setattribute xpath="lootcontainers/lootgroup/item[starts-with(@name, 'armorCloth')]" name="count">3,6</setattribute>
	<set xpath="/lootcontainers/lootgroup/item[starts-with(@name, 'armorCloth')]/@name">resourceCloth</set>
</config>

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...