[TUTORIAL] XML Patch Guide

The place to discuss scripting and game modifications for X Rebirth.

Moderators: Scripting / Modding Moderators, Moderators for English X Forum

UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader » Thu, 28. Apr 16, 17:25

1. you can change the load order with an
<dependency id="***ID of other mod" optional="true" />
to make sure your mod is loaded after another mod if present (if you leave out the optional the other mod is a requirement and it wont work without)

2. then just do your changes as if the other patch file already did its work. if some f the operations might not be possible because of missing Extensions (or Extensions breaking them) mark them with an optional="true" to suppress related errors (or was it silent="true" ? :gruebel: )
like this:
<add sel="///////////" optional="true"><Your_additional_stuff/></add>
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)

pref
Posts: 5579
Joined: Sat, 10. Nov 12, 17:55
x4

Post by pref » Thu, 28. Apr 16, 19:20

You have to set a dependency on the DLCs.

If you want to affect only the load order, but not depend on other extensions, then you can add a line like this in content.xml (note the optional attribute):

Code: Select all

<content ... >
  <dependency id="ws_xxxxxxxx" optional="true" name="ModName"></dependency> 
</content>
However it only works for workshop mods - iirc not even DLCs, so it might be that you have to set a dependency then. If this is the case, you might have to release a compatibility mod for the DLC(s) separately which depends on the DLC(s) and your original mod.

User avatar
Simoom
Posts: 1110
Joined: Sat, 30. Oct 10, 14:14
x4

Post by Simoom » Fri, 29. Apr 16, 00:29

Okay, thank you! :)

I am trying to find a way to customize the attributes of spawned weaponmods for my cheat script (and since there's no way to specify the attributes of spawned inventory ware directly through script at the moment... had to resort to patching).

So I wrote this as a test (for libraries/weaponmods.xml)
Replacing this:

Code: Select all

    <weapon macro="weapon_player_impulse_mk1_macro" weight="10"><!--0.135-->
      <damage min="1.05" max="1.1" weight="18"/>
      <cooling min="0.92" max="1.77" weight="2"/>
      <reload min="0.6" max="1.04" weight="13"/>
      <speed min="0.4" max="1.1" weight="3"/>
      <lifetime min="1.05" max="2.0" weight="14"/>
    </weapon>
With:

Code: Select all

  <replace sel="/weaponmods/weapons/weapon[@macro='weapon_player_impulse_mk1_macro']/damage">
    <damage exact="1.5" weight="18"/>
  </replace>
  <replace sel="/weaponmods/weapons/weapon[@macro='weapon_player_impulse_mk1_macro']/cooling">
    <cooling exact="3" weight="2"/>
  </replace>
  <replace sel="/weaponmods/weapons/weapon[@macro='weapon_player_impulse_mk1_macro']/reload">
    <reload exact="1.5" weight="13"/>
  </replace>
  <replace sel="/weaponmods/weapons/weapon[@macro='weapon_player_impulse_mk1_macro']/speed">
    <speed exact="1.5" weight="3"/>
  </replace>
  <replace sel="/weaponmods/weapons/weapon[@macro='weapon_player_impulse_mk1_macro']/lifetime">
    <lifetime exact="2.0" weight="14"/>
  </replace>
The weaponmods now spawn with no attributes at all... but I am not sure what's wrong with it. :( Is the game expecting ONLY min-max values or something?

UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader » Fri, 29. Apr 16, 00:36

Simoom wrote:The weaponmods now spawn with no attributes at all... but I am not sure what's wrong with it. :( Is the game expecting ONLY min-max values or something?
according to xsd file yes.
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)

User avatar
Simoom
Posts: 1110
Joined: Sat, 30. Oct 10, 14:14
x4

Post by Simoom » Wed, 4. May 16, 02:22

Hey everyone, sorry for so many questions... :oops:
  1. I am trying to patch some more files right now, and am wondering if there's an easier way to patch an entire block of text, or if I have to do it line by line? I see that <remove> has a ws attribute that allows me to remove a whole node block... but can I do something similar with <replace>?
  2. Does the line I replace always have to be closed? I need to replace this (from Upkeep.xml) with some values of my own:

    Code: Select all

    <do_if value="not $Ship.buildmodule and $Ship.primarypurpose != objectpurpose.mine">
    But as you can see this tag is not closed, and Visual Studio flags it.

UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader » Wed, 4. May 16, 06:23

xml patch wors by using the xml hierarchy, it does not work with lines. (although often they are the same for readability)
this is for example also a valid single node opening:

Code: Select all

<do_if
value="some really long expression you better
split into multiple lines to avoid annoying
horizontal scrolling"
chance="another really long expression you better
split into multiple lines to avoid annoying
horizontal scrolling which resolves to 0 or 100"
/>
that just as examle to show that a node isnt necesarily the same as a line.

1. the ws attribute is for removing whitespaces so you can keep the xml indents in the result document, i dont think it can be used to remove multiple nodes at once. same for replace - each adressed node must be unique.
there is an unofficial msel extension which allows the adressing of multiple nodes in one operation, but its afaik not supported by EGO yet.

2. yes, otherwise your xml is not valid. note that you would also replace the actions inside this <do_if/> since you adress the whole Node, not just the Line where it starts.
you can replace the attribute values themselves though:

Code: Select all

<replace sel="//*****/do_if[@value='not $Ship.buildmodule and $Ship.primarypurpose != objectpurpose.mine']/@value">( not $Ship.buildmodule and $Ship.primarypurpose != objectpurpose.mine ) or $someothercondition</replace>
(note the @value at the end of the sel path)

alternatively you could also add a chance attribute as further restriction if you just want the do_if to apply in less cases:

Code: Select all

<add sel="//*****/do_if[@value='not $Ship.buildmodule and $Ship.primarypurpose != objectpurpose.mine']" type="@chance">$someothercondition * 100</add>
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)

User avatar
Simoom
Posts: 1110
Joined: Sat, 30. Oct 10, 14:14
x4

Post by Simoom » Thu, 5. May 16, 05:38

Thanks UniTrader.

Hmm.... okay, so let me make sure I understand this:

Code: Select all

<?xml version="1.0" encoding="utf-8"?>
<mdscript name="Upkeep_Management" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="md.xsd">
  <cues>
    <library name="CheckObject">
      <actions>
        <do_if value="$Object.exists and @$Object.isplayerowned">
          <do_if value="$Object != player.primaryship">
            <do_if value="md.$AllowMultiMissions or not @$HasMission">
              <do_all exact="1">

                
                <do_elseif value="$Object.isclass.station"> <!-- <<< This is the line I want to change -->
                  <[... WHOLE LOT OF STUFF]/>
                </do_elseif>


              </do_all>
            </do_if>
          </do_if>
        </do_if>
      </actions>
    </library>

  </cues>
</mdscript>
If I only want to change that opening <do_elseif> line... but it's an open node that contains a WHOLE LOT of stuff in between... in my patch file I need to include that WHOLE LOT of stuff between the <do_elseif></do_elseif> ?

So like...

Code: Select all

  <replace sel="cues/library[@name='CheckObject']/actions/do_if/do_if/do_if/do_all/do_elseif[@value='$Object.isclass.station']">
    <do_elseif value="($Object.isclass.station) and not ($Object.macro.ismacro.[...])">
        <[... WHOLE LOT OF STUFF]/>
    </do_elseif>
  </replace>

UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader » Thu, 5. May 16, 14:39

if you want to replace the node as whole yes, but as i said in my previous post you can also replace the attribute Value only. like this:

Code: Select all

<replace sel="cues/library[@name='CheckObject']/actions/do_if/do_if/do_if/do_all/do_elseif[@value='$Object.isclass.station']/@value">($Object.isclass.station) and not ($Object.macro.ismacro.[...])</replace>
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)


User avatar
Simoom
Posts: 1110
Joined: Sat, 30. Oct 10, 14:14
x4

Post by Simoom » Fri, 6. May 16, 07:03

Sorry to be back here again with more questions...

How should I handle changing a specific node that has the same name as another one?

For example:

Code: Select all

    <actions>
      <do_if value="a">
      </do_if>
      <do_else>
      </do_else>

      <do_if value="b">
      </do_if>
      <do_else>
      </do_else>
    </actions>
If I want to change the <do_else> node under <do_if value="b">, how do I point to that? Or do I have to replace everything under <actions> entirely?

UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader » Fri, 6. May 16, 11:18

you could either use the positoon in the node as identifier (i dont recommend this method since its unreliable when using multiple mods):
sel="//do_if[**]/do_else[2]

or you could use the values of some child nodes that differ between them:
sel="//do_if[**]/do_else[some_node_which_is_only_in_the_second_do_else]
for better example the contents of both do_else would be helpful. also a Search for XPath with a short description of your problem might help ;)
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)

User avatar
Simoom
Posts: 1110
Joined: Sat, 30. Oct 10, 14:14
x4

Post by Simoom » Fri, 13. May 16, 05:00

Hey guys, sorry question again...

What do I do when the of a node contains ' '? It seems to mess up the pathfinding...

Code: Select all

<replace sel="//cue[@name='SectionHandler']/actions/do_elseif[@value='event.param == 'cStaff_move'']/@value">
The 'cStaff_move' is messing things up... how do I prevent that?

UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader » Fri, 13. May 16, 05:10

this stuff can get rally tricky..
first thing i do is swapping "" and ''

Code: Select all

<replace sel='//cue[@name="SectionHandler"]/actions/do_elseif[@value="event.param == 'cStaff_move'"]/@value'>
then you can use html entities instead of characters directly for the innermost "" and '':
" instead of "
&apos; instead of '

Code: Select all

<replace sel='//cue[@name="SectionHandler"]/actions/do_elseif[@value="event.param == &apos;cStaff_move&apos;"]/@value'>
there are also other tricks you could use - some like co use @value contains(***snippet inside value attribute***) or something, but not familiar with that possibility myself..
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)

User avatar
Simoom
Posts: 1110
Joined: Sat, 30. Oct 10, 14:14
x4

Post by Simoom » Fri, 13. May 16, 11:36

Thanks as always, UniTrader!

Backtracking a bit, regarding your answer to my previous question:
UniTrader wrote:you could either use the positoon in the node as identifier (i dont recommend this method since its unreliable when using multiple mods):
sel="//do_if[**]/do_else[2]

or you could use the values of some child nodes that differ between them:
sel="//do_if[**]/do_else[some_node_which_is_only_in_the_second_do_else]
for better example the contents of both do_else would be helpful. also a Search for XPath with a short description of your problem might help ;)
I am trying to remove these two nodes in Upkeep_Management.xml:

Code: Select all

  <do_if value="$Object.primarypurpose == objectpurpose.mine">
    <do_if value="$Object.cargo.tags.indexof.{tag.bulk}">
      <do_if value="$Object.units.{unitcategory.orecollector}.count lt 5">
        <signal_cue_instantly cue="md.Upkeep.Deliver_Unit_Start" param="[null, $Object, table[{unitcategory.orecollector} = 5]]"/>
        <include_actions ref="PostMissionAddedActions"/>
      </do_if>
    </do_if>
  </do_if>

  <do_if value="$Object.primarypurpose == objectpurpose.mine">
    <do_if value="$Object.cargo.tags.indexof.{tag.liquid}">
      <do_if value="$Object.units.{unitcategory.gascollector}.count lt 5">
        <signal_cue_instantly cue="md.Upkeep.Deliver_Unit_Start" param="[null, $Object, table[{unitcategory.gascollector} = 5]]"/>
        <include_actions ref="PostMissionAddedActions"/>
      </do_if>
    </do_if>
  </do_if>
Note that both are <do_if> with the exact same value (why would you write it like that Egosoft?? WHY???)

So... to remove them, what do I write? I could do:

Code: Select all

  <remove sel="//library[@name='CheckObject']/actions/do_if/do_if/do_if[@value='md.$AllowMultiMissions or not @$HasMission']/do_all/do_if[@value='$Object.isclass.ship_l or $Object.isclass.ship_xl']/do_if[6]"/>
  <remove sel="//library[@name='CheckObject']/actions/do_if/do_if/do_if[@value='md.$AllowMultiMissions or not @$HasMission']/do_all/do_if[@value='$Object.isclass.ship_l or $Object.isclass.ship_xl']/do_if[7]"/>
But you said that's unreliable. How do I format a child node to the do_if inside the bracket?

pref
Posts: 5579
Joined: Sat, 10. Nov 12, 17:55
x4

Post by pref » Fri, 13. May 16, 12:42

You can also use the contains function, and omit the quotes.

UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader » Fri, 13. May 16, 13:02

2 possibilities:

either use brackets as i initially said:

Code: Select all

  <remove sel="//library[@name='CheckObject']/actions/do_if/do_if/do_if[@value='md.$AllowMultiMissions or not @$HasMission']/do_all/do_if[@value='$Object.isclass.ship_l or $Object.isclass.ship_xl']/do_if[do_if/do_if/signal_cue_instantly[@cue='md.Upkeep.Deliver_Unit_Start']]"/>
  <remove sel="//library[@name='CheckObject']/actions/do_if/do_if/do_if[@value='md.$AllowMultiMissions or not @$HasMission']/do_all/do_if[@value='$Object.isclass.ship_l or $Object.isclass.ship_xl']/do_if[do_if/do_if/signal_cue_instantly[@cue='md.Upkeep.Deliver_Unit_Start']]"/>
or go down the Path a few more levels and then go back up:

Code: Select all

  <remove sel="//library[@name='CheckObject']/actions/do_if/do_if/do_if[@value='md.$AllowMultiMissions or not @$HasMission']/do_all/do_if[@value='$Object.isclass.ship_l or $Object.isclass.ship_xl']/do_if/do_if/do_if/signal_cue_instantly[@cue='md.Upkeep.Deliver_Unit_Start']/../../.."/>
  <remove sel="//library[@name='CheckObject']/actions/do_if/do_if/do_if[@value='md.$AllowMultiMissions or not @$HasMission']/do_all/do_if[@value='$Object.isclass.ship_l or $Object.isclass.ship_xl']/do_if/do_if/do_if/signal_cue_instantly[@cue='md.Upkeep.Deliver_Unit_Start']/../../.."/>
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)

User avatar
Simoom
Posts: 1110
Joined: Sat, 30. Oct 10, 14:14
x4

Post by Simoom » Fri, 13. May 16, 14:25

I see! Thank you again UniTrader! :)

ns88ns
Posts: 90
Joined: Sun, 11. Sep 11, 22:00
x4

Post by ns88ns » Mon, 19. Dec 16, 20:00

Hi, folks.

There is directive <patch/> in MD scripts. I checked XR Wiki and Google but I found almost nothing... So the questions are:

- What is it?
- What it does?
- How it works?

Perhaps I missed somethig so if you point me to the threads/resources where <patch/> is described - then it will be nice.

Thank you in advance.

UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader » Mon, 19. Dec 16, 20:10

patch nodes in md are basically actions performed when the version of the cue in the md script file has increased compared to the version stored in the savegame. you can also filtler if the respective patch node should be performed when the cue is complete, canceled, waiting etc.

see also the libraries/md.xsd:

Code: Select all

      <xs:element name="patch" minOccurs="0" maxOccurs="unbounded">
        <xs:annotation>
          <xs:documentation>
            Actions for patching a cue of an older version (will be performed when loading the MD script from a save).
            Patches are applied to waiting, active or complete cues (see state attribute).
            This includes library users and instances, except for completed instances that have already been deleted.
          </xs:documentation>
        </xs:annotation>
        <xs:complexType>
          <xs:group ref="actions" />
          <xs:attribute name="sinceversion" use="required" type="xs:positiveInteger">
            <xs:annotation>
              <xs:documentation>
                Cue version at which this patch element was added (it will only be applied when loading a cue of an older version)
              </xs:documentation>
            </xs:annotation>
          </xs:attribute>
          <xs:attribute name="state">
            <xs:annotation>
              <xs:documentation>
                Required state that this cue must be in for this patch to be applied (default is complete)
              </xs:documentation>
            </xs:annotation>
            <xs:simpleType>
              <xs:restriction base="xs:string">
                <xs:enumeration value="complete">
                  <xs:annotation>
                    <xs:documentation>
                      Apply patch only if this cue is complete (default)
                    </xs:documentation>
                  </xs:annotation>
                </xs:enumeration>
                <xs:enumeration value="waiting">
                  <xs:annotation>
                    <xs:documentation>
                      Apply patch only if this cue is waiting (conditions are being checked)
                    </xs:documentation>
                  </xs:annotation>
                </xs:enumeration>
                <xs:enumeration value="active">
                  <xs:annotation>
                    <xs:documentation>
                      Apply patch only if this cue is active (not complete yet because of a delay)
                    </xs:documentation>
                  </xs:annotation>
                </xs:enumeration>
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
          <xs:attribute name="comment" type="comment" />
        </xs:complexType>
      </xs:element>
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)

ns88ns
Posts: 90
Joined: Sun, 11. Sep 11, 22:00
x4

Post by ns88ns » Mon, 19. Dec 16, 20:50

Clear... Will read the XDS more attentively.
Thanks a lot.

Post Reply

Return to “X Rebirth - Scripts and Modding”