Rimworld Mod制作教程3 使用Xpath制作patch(补丁)

废话

rimworld在A17版本后提供了一个新的编写mod的特性,叫做XML PatchOperations。直译就是补丁手术。
正如字面意思,它使用xpath的语法让modder可以以补丁的方式修改原版以及其他mod中变量的值。
本篇做一个简单的入门介绍,因为原文写的已经非常详细了。
原文链接

核心内容

1 使用Xpath制作patch(补丁)

1.1 基本格式

大部分格式都是 手术类型–变量位置–值,一些高级语法稍微复杂一些,可以做到if()else{}一样的逻辑判断

<?xml version="1.0" encoding="utf-8" ?>
<Patch>
  <!-- 要动用的手术类型 -->
  <Operation Class="PatchOperationReplace">
    <!-- 要修改的变量是某个标签为<TerrainDef>中defName为WaterDeep的物品,修改这个物品的纹理值texturePath -->
    <xpath>/Defs/TerrainDef[defName="WaterDeep"]/texturePath</xpath>
    <value>
      <!-- 值改为你新创造的纹理目录 -->
      <texturePath>Your/Texture/Path/Here</texturePath>
    </value>
  </Operation>
</Patch>

关于Xpath的路径需要注意的是,它代表xml文件中的节点路径,而不是你的xml文件在硬盘中的路径,虽然文件夹可能也叫一样的名字
举例分析:
Human这个种族的def文件中,xpath的路径应该为/Defs/ThingDef,如果修改label则应该写为/Defs/ThingDef[defName=“Human”]/label,如果要添加comps节点,则要在value中填写comps,不可以在路径中填写comps,因为源文件里没有这个属性。反之如果源文件里有comps则要追踪到comps路径下。

<?xml version="1.0" encoding="utf-8" ?>
<Defs>
  <ThingDef ParentName="BasePawn">
    <defName>Human</defName>
    <label>human</label>
    <description>A baseline human, mostly unmodified by gene engineering and mostly unchanged by evolutionary pressures on non-Earth planets.</description>
    <statBases>
      <MarketValue>1750</MarketValue>
      <MoveSpeed>4.6</MoveSpeed>
      <Flammability>1.0</Flammability>
      <ComfyTemperatureMin>16</ComfyTemperatureMin>
      <ComfyTemperatureMax>26</ComfyTemperatureMax>
      <LeatherAmount>50</LeatherAmount>
      <RoyalFavorValue>3</RoyalFavorValue>
    </statBases>
    <tools>
      <li>
        <label>left fist</label>
        <capacities>
          <li>Blunt</li>
        </capacities>
        <power>8.2</power>
        <cooldownTime>2</cooldownTime>
        <linkedBodyPartsGroup>LeftHand</linkedBodyPartsGroup>
        <surpriseAttack>
          <extraMeleeDamages>
            <li>
              <def>Stun</def>
              <amount>14</amount>
            </li>
          </extraMeleeDamages>
        </surpriseAttack>
      </li>
      <li>
        <label>right fist</label>
        <capacities>
          <li>Blunt</li>
        </capacities>
        <power>8.2</power>
        <cooldownTime>2</cooldownTime>
        <linkedBodyPartsGroup>RightHand</linkedBodyPartsGroup>
        <surpriseAttack>
          <extraMeleeDamages>
            <li>
              <def>Stun</def>
              <amount>14</amount>
            </li>
          </extraMeleeDamages>
        </surpriseAttack>
      </li>
      <li>
        <label>teeth</label>
        <capacities>
          <li>Bite</li>
        </capacities>
        <power>8.2</power>
        <cooldownTime>2</cooldownTime>
        <linkedBodyPartsGroup>Teeth</linkedBodyPartsGroup>
        <chanceFactor>0.07</chanceFactor>
      </li>
      <li>
        <label>head</label>
        <capacities>
          <li>Blunt</li>
        </capacities>
        <power>5</power>
        <cooldownTime>2</cooldownTime>
        <linkedBodyPartsGroup>HeadAttackTool</linkedBodyPartsGroup>
        <ensureLinkedBodyPartsGroupAlwaysUsable>true</ensureLinkedBodyPartsGroupAlwaysUsable>
        <chanceFactor>0.2</chanceFactor>
      </li>
    </tools>
    <race>
      <thinkTreeMain>Humanlike</thinkTreeMain>
      <thinkTreeConstant>HumanlikeConstant</thinkTreeConstant>
      <intelligence>Humanlike</intelligence>
      <makesFootprints>true</makesFootprints>
      <lifeExpectancy>80</lifeExpectancy>
      <leatherDef>Leather_Human</leatherDef>
      <nameCategory>HumanStandard</nameCategory>
      <body>Human</body>
      <baseBodySize>1</baseBodySize>
      <baseHealthScale>1</baseHealthScale>
      <foodType>OmnivoreHuman</foodType>
      <gestationPeriodDays>45</gestationPeriodDays>
      <meatMarketValue>0.8</meatMarketValue>
      <manhunterOnDamageChance>0.20</manhunterOnDamageChance>
      <manhunterOnTameFailChance>0.02</manhunterOnTameFailChance>
      <litterSizeCurve>
        <points>
          <li>(0.5, 0)</li>
          <li>(1, 1)</li>
          <li>(1.01, 0.02)</li>
          <li>(3.5, 0)</li>
        </points>
      </litterSizeCurve>
      <lifeStageAges>
        <li>
          <def>HumanlikeBaby</def>
          <minAge>0</minAge>
        </li>
        <li>
          <def>HumanlikeToddler</def>
          <minAge>1.2</minAge>
        </li>
        <li>
          <def>HumanlikeChild</def>
          <minAge>4</minAge>
        </li>
        <li>
          <def>HumanlikeTeenager</def>
          <minAge>13</minAge>
        </li>
        <li>
          <def>HumanlikeAdult</def>
          <minAge>18</minAge>
        </li>
      </lifeStageAges>
      <soundMeleeHitPawn>Pawn_Melee_Punch_HitPawn</soundMeleeHitPawn>
      <soundMeleeHitBuilding>Pawn_Melee_Punch_HitBuilding</soundMeleeHitBuilding>
      <soundMeleeMiss>Pawn_Melee_Punch_Miss</soundMeleeMiss>
      <specialShadowData>
        <volume>(0.3, 0.8, 0.4)</volume>
        <offset>(0,0,-0.3)</offset>
      </specialShadowData>
      <ageGenerationCurve>
        <points>
          <li>(14,0)</li>
          <li>(16,100)</li>
          <li>(50,100)</li>
          <li>(60,30)</li>
          <li>(70,18)</li>
          <li>(80,10)</li>
          <li>(90,3)</li>
          <li>(100,0)</li>
        </points>
      </ageGenerationCurve>
      <hediffGiverSets>
        <li>OrganicStandard</li>
        <li>Human</li>
      </hediffGiverSets>
    </race>
    <recipes>
      <li>ExciseCarcinoma</li>
      <li>AdministerMechSerumHealer</li>
      <li>RemoveBodyPart</li>
      <li>Euthanize</li>
      <li>Anesthetize</li>
    </recipes>
  </ThingDef>
</Defs>

1.2 手术类型

支持的手术类型如下

四种基础手术
PatchOperationAdd 为所选的节点添加一个子节点,以及子节点的默认值,其实就是新增变量
PatchOperationInsert 为所选的节点添加一个同级别的节点和默认值
PatchOperationRemove 删除所选的节点
PatchOperationReplace 替换所选的节点(的值)
三个针对xml Attribute(特性)的手术
PatchOperationAttributeAdd 添加特性,只有在特性不存在的时候才会生效
PatchOperationAttributeSet 为已经存在的特性提供修改
PatchOperationAttributeRemove 撤销某个特性
三种更复杂的类型
PatchOperationAddModExtension 添加ModExtension.
ModExtension是一种以C#的方式给xml打补丁的方式,简单轻便,可以做更复杂的逻辑,但因为没有自己独立的def容易出一些问题。
ModExtension介绍
PatchOperationSetName 改变节点的命名
PatchOperationSequence 一个PatchOperration格式的序列,一组手术,有语法错误的时候会停下来
三种条件手术
PatchOperationTest 对节点进行测试,很适合用在手术序列上
PatchOperationConditional 条件判断的手术,有了它你甚至可以在xml里写逻辑代码0.0
PatchOperationFindMod 可以用来测试某个mod是否存在,然后配合Conditional类型的手术可以让你的mod针对其他mod做一些特别的修改,从而达到高兼容性

我就主要说一下条件判断手术,因为会比较常用

	
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
  <!-- 对上次做的手办(鸡)的描述/Defs/ThingDefs_Buildings[defName = "GarageKid_Chicken"]/description 做条件判断 -->
	<Operation Class = "PatchOperationConditional">
		<xpath>/Defs/ThingDefs_Buildings[defName = "GarageKid_Chicken"]/description</xpath>
    <!-- 存在这个变量名 做替换-->
		<match Class = "PatchOperationReplace">
			<xpath>/Defs/ThingDefs_Buildings[defName = "GarageKid_Chicken"]/description</xpath>
			<value>
				<description>修改后的描述</description>
			</value>
		</match>
    <!-- 不存在这个变量名 做添加操作 -->
		<nomatch Class = "PatchOperationAdd">
			<xpath>/Defs/ThingDefs_Buildings[defName = "GarageKid_Chicken"]/description</xpath>
			<value>
				<description>修改后的描述</description>
			</value>
		</nomatch>
	</Operation>
</Patch>

1.3 偷窥 参考他人代码

这周有一个流行度很高的mod刚好采用xpath实现功能,名字叫做Priority treatment,它的功能是修改小人的AI。原版的小人有时候特别智障,一群伤员躺在病房,结果医生去吃饭,去睡觉,甚至去看电视。。。这个mod改善了这种情况,让医生职业的角色优先从事医护工作。

修改AI这操作,萌新一定觉得非常高大上,然而这个mod一共只使用了4个非常简单的xpath手术操作。
原版小人路过燃烧的地方时,不论他在做什么工作,一定会优先灭火,这个行为是由于灭火工作里有一个<emergency>true</emergency>突发事件=true的变量。普通的工作是没有的。通过给原版其他工作添加这个变量,从而达到让医生救人如救火的效果,各种意义上。

<?xml version="1.0" encoding="utf-8" ?>
<Patch>
  <Operation Class="PatchOperationAdd">
    <xpath>*/WorkGiverDef[defName = "DoctorTendToHumanlikes"]</xpath>
    <value>
	  <emergency>true</emergency>
	</value>
  </Operation>
  <Operation Class="PatchOperationAdd">
    <xpath>*/WorkGiverDef[defName = "DoctorTendToSelf"]</xpath>
    <value>
	  <emergency>true</emergency>
	</value>
  </Operation>
  <Operation Class="PatchOperationAdd">
    <xpath>*/WorkGiverDef[defName = "DoctorTendToAnimals"]</xpath>
    <value>
	  <emergency>true</emergency>
	</value>
  </Operation>
  <Operation Class="PatchOperationAdd">
    <xpath>*/WorkGiverDef[defName = "DoctorRescue"]</xpath>
    <value>
	  <emergency>true</emergency>
	</value>
  </Operation>
</Patch>

*表示xpath语法中匹配任何元素节点,是从根目录匹配到/Defs存在WorkGiverDef这个目录的,感兴趣的话可以看一眼xpath的语法教程
xpath语法教程

如果这篇文章对你有帮助,点赞收藏支持一下呗!

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值