Editing Modding Tutorials/Compatibility with defs

Jump to navigation Jump to search

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
{{BackToTutorials}}<br/>
+
{{BackToTutorials}}
 +
{{Credit|[[User:Alistaire|Alistaire]]}}<br/>
  
 
In this tutorial you will learn different ways to make XML mods compatible and how to link existing and modded recipes, facilities and buildings with eachother.
 
In this tutorial you will learn different ways to make XML mods compatible and how to link existing and modded recipes, facilities and buildings with eachother.
Line 5: Line 6:
 
=What you'll learn=
 
=What you'll learn=
  
You'll learn:
+
You'll learn how to implement your mods into existing defs, how to fix compatibility between XML mods and how to make modded recipes, facilities and buildings interact with eachother without overwriting the base game.<br/><br/>
# How to implement your changes into existing Defs
 
# How to fix compatibility between XML mods
 
# How to make modded recipes and buildings interact with eachother without overwriting the base game
 
# How to link facilities to buildings
 
# How to add Biomes to animals for the sake of spawning them<br/><br/>
 
  
 
=Overwriting defs=
 
=Overwriting defs=
 
===Core defs===
 
===Core defs===
'''Don't.'''
 
  
Use [[Modding Tutorials/PatchOperations| xpath]] instead.  
+
The least elegant way to go about compatibility is to have a modified copy of a core def in your mod file. You have to rely on load order to make the mod work, let's say you want to change the damage of a pistol:<br/>
 +
 
 +
  Core/
 +
    Defs/
 +
      ThingDefs/
 +
        Weapons_Guns.xml
 +
  YourModName/
 +
    Defs/
 +
      ThingDefs/
 +
        YourFileName.xml
 +
 
 +
.. and contents:
 +
 
 +
<source lang="xml"><?xml version="1.0" encoding="utf-8"?>
 +
<Defs>
 +
<!-- base parent <Def>'s -->
 +
 +
<ThingDef ParentName="BaseBullet">
 +
<defName>Bullet_Pistol</defName>
 +
<projectile>
 +
<DamageAmountBase>9</DamageAmountBase>
 +
</projectile>
 +
<!-- more tags -->
 +
</ThingDef>
 +
 
 +
<!-- more <Def>'s -->
 +
</Defs></source><br/>
 +
 
 +
The above code adds something that already exists on the /Core/ mod - to make it overwrite the core mod, this mod has to be loaded after it. Practically every mod is loaded after the core mod, so this shouldn't be a problem.<br/>
 +
 
 +
The problem arises when multiple mods edit ''Bullet_Pistol'', and as a rule of thumb the last loaded version of a defName is kept.<br/><br/>
 +
 
 
===Mod defs===
 
===Mod defs===
{{Main|Modding Tutorials/PatchOperations#PatchOperationFindMod}}
 
'''Don't.'''
 
  
Use [[Modding Tutorials/PatchOperations| xpath]] instead. You can use [[Modding Tutorials/PatchOperations#PatchOperationFindMod|PatchOperationFindMod]] or [[Modding Tutorials/PatchOperations#PatchOperationConditional|PatchOperationConditional]] to cleverly add your Defs and Patches.
+
{|
 +
!colspan=3| I modify.. !! What do?
 +
|-
 +
|rowspan=2| ..Core.. ||colspan=2| ..Def values || Add the defs you want to overwrite to your mod and load the mod after Core
 +
|-
 +
|colspan=2| ..Class references || Add the defs you want to overwrite to your mod and load the mod after Core, use C# to [[Modding Tutorials/Modifying defs|modify def classes]].
 +
|-
 +
|rowspan=8| ..a mod's.. ||rowspan=3| ..Def changes.. || ..directly || Make a choice which value to keep (merge them if possible) - if it's the only difference in the core def overwrites between the mods, simply loading one after the other will fix the compatibility, if that's not possible make a merged patch
 +
|-
 +
| ..collaterally || The easiest way to fix this is by making a patch, including the same def with both modifications applied to them - this def can then be loaded after both of the mods<sup>2</sup>
 +
|-
 +
| (both of the above) || Make a compatibility patch: take the def from both mods and try to merge as many values as you can, compare it to the core def, see if you can figure it out through XML only
 +
|-
 +
|rowspan=2| ..Class reference changes.. || ..directly || E.g <thingClass> added twice: [[Modding Tutorials/Compatibility with DLLs|create a DLL patch]]<sup>3</sup>
 +
|-
 +
| ..not directly || E.g Mod A <ThingDef> and Mod B <projectile> Class changes: this will work fine with an XML patch<sup>3</sup>
 +
|-
 +
|rowspan=2| ..Def values.. || ..intentionally || Add the defs you want to overwrite to your mod and load it after their mod<sup>1</sup>
 +
|-
 +
| ..unintentionally || Rename your defs, try to figure the compatibility out through contacting the author, make a compatibility patch
 +
|-
 +
|colspan=2| ..Class references || E.g <ThingDef Class="namespace.class"> added twice: [[Modding Tutorials/Compatibility with DLLs|create a DLL patch]]<sup>3</sup>
 +
|}<br/>
  
====Example====
+
# If your mod requires another mod to function and you want to change something about their mod, let's say CustomShotgun should do 20 damage instead of 25, your mod has to include CustomShotgun's def and be loaded after their mod.
<source lang="XML"><?xml version="1.0" encoding="utf-8"?>
+
# Mod A changes CoreDef's label to "hunting shotgun", mod B changes CoreDef's soundInteract to "InteractPistol", patch AB does both to fix their compatibility issues.
<Patch>
+
# When mod A adds Class="ModANamespace.ModAClass" to a defName's ThingDef and mod B adds Class="ModBNamespace.ModBClass" this is a non XML-patchable incompatibility. This means that if A adds a Class to the <projectile> tag and B adds a Class to the <thingDef> tag you're perfectly fine. This tutorial won't cover creating DLL patches because it's more in-depth, but [[Modding Tutorials/Compatibility with DLLs|create a DLL patch]] and [[Modding Tutorials/Injection|C# injection]] will.<br/><br/>
    <Operation Class="PatchOperationFindMod">
 
        <mods>
 
            <li>SomeOtherMod</li>
 
        </mods>
 
        <match Class="PatchOperationReplace">
 
            <xpath>/Defs/ThingDef[defName="ExampleDefFromSomeOtherMod"]/isTechHediff</xpath>
 
            <value>
 
                <isTechHediff>true</isTechHediff>
 
            </value>
 
        </match>
 
    </Operation>
 
</Patch>
 
</source>
 
  
 
=Referencing defs=
 
=Referencing defs=
 
===RecipeDef===
 
===RecipeDef===
  
In case your mod adds a new recipe for the [[Electric stove]], you might think it's necessary to patch or overwrite part of its ThingDef. This is however completely unnecessary - the C# code base contains a tag which allows you to make your ''recipe'' choose which ''building'' to attach to (instead of the other way round):<br/>
+
In case your mod adds a new recipe for the [[Cook stove]], you might think it's necessary to overwrite part of its thingDef. This is however completely unnecessary - the C# code base contains a tag which allows you to make your ''recipe'' choose which ''building'' to attach to (instead of the other way round):<br/>
  
 
<source lang="xml"><?xml version="1.0" encoding="utf-8"?>
 
<source lang="xml"><?xml version="1.0" encoding="utf-8"?>
Line 49: Line 82:
 
<RecipeDef>
 
<RecipeDef>
 
<defName>BakeBread</defName>
 
<defName>BakeBread</defName>
 +
<recipeMaker>
 
<recipeUsers>
 
<recipeUsers>
<li>ElectricStove</li>
+
<li>CookStove</li>
 
</recipeUsers>
 
</recipeUsers>
 
<!-- more tags -->
 
<!-- more tags -->
 +
</recipeMaker>
 
<!-- more tags -->
 
<!-- more tags -->
 
</RecipeDef>
 
</RecipeDef>
Line 70: Line 105:
 
</Defs></source><br/>
 
</Defs></source><br/>
  
The BakeBread recipe will now show up in both the BakeryOven and Electric Stove, without the mod having to modify Electric Stove's <recipes> list.<br/><br/>
+
The BakeBread recipe will now show up in both the BakeryOven and CookStove, without the mod having to modify CookStove's <recipes> list.<br/><br/>
 
 
There's also the option to define the recipeUsers in the Bread ThingDef:
 
 
 
<source lang="xml"><?xml version="1.0" encoding="utf-8"?>
 
<Defs>
 
<ThingDef>
 
<defName>DeliciousBread</defName>
 
<recipeMaker>
 
<recipeUsers>
 
<li>BakeryOven</li>
 
<li>ElectricStove</li>
 
</recipeUsers>
 
</recipeMaker>
 
<!-- more tags -->
 
</ThingDef>
 
</Defs></source><br/>
 
 
 
And if all else fails, there's still xpath:
 
 
 
<source lang="xml"><?xml version="1.0" encoding="utf-8"?>
 
<Patch>
 
<Operation Class="PatchOperationAdd">
 
<xpath>Defs/ThingDef[defName="BakeryOven"]/recipes</xpath>
 
<value>
 
<li>BakeBread</li>
 
</value>
 
</Operation>
 
</Patch>
 
</source>
 
  
 
===Facilities===
 
===Facilities===
Line 143: Line 149:
  
 
BadIdeaShredder can now be attached to the vanilla ResearchBench, and the vanilla ToolCabinet can now be attached to MyFirstWorkshop.<br/><br/>
 
BadIdeaShredder can now be attached to the vanilla ResearchBench, and the vanilla ToolCabinet can now be attached to MyFirstWorkshop.<br/><br/>
 
===Animals===
 
If you want your animal to show up in certain biomes, you don't need patch those biomes. You can add the biomes by defName and the game will resolve the cross reference.
 
 
<source lang ="XML">
 
<Defs>
 
<ThingDef>
 
<defName>MyExampleAnimal</defName>
 
<race>
 
<wildBiomes>
 
<TropicalRainforest>0.08</TropicalRainforest>
 
<TemperateForest>0.09</TemperateForest>
 
<BorealForest>0.09</BorealForest>
 
</wildBiomes>
 
</race>
 
<!-- more tags -->
 
</ThingDef>
 
</Defs>
 
</source>
 
 
== Conditional on DLC or other mods ==
 
Sometimes you only need something to be there when a specific mod or DLC is present. For that we use MayRequire and MayRequireAnyOf.
 
 
'''Note:''' the following examples use the DLC for the required content, but it could just as easily require "sarg.alphagenes" as "Ludeon.RimWorld.Biotech".
 
 
MayRequire requires the presence of all listed content. For example a list of pawns may include:
 
<pre>
 
<Tribal_Child MayRequire="Ludeon.RimWorld.Biotech">10</Tribal_Child>
 
</pre>
 
This requires that the [[Biotech DLC]] be enabled for this entry in the list to be used.
 
 
Multiple mods/DLC may be listed to required all of them at once for example:
 
<pre>
 
<li MayRequire="Ludeon.RimWorld.Royalty,Ludeon.RimWorld.Ideology">DarklightBrazier</li>
 
</pre>
 
Which requires both the [[Royalty DLC]] and the [[Ideology DLC]] to be enabled at the same time - if only one is enabled, it won't be included.
 
 
Finally there is MayRequireAnyOf which enables content when any of the list is present. For example:
 
<pre>
 
<li MayRequireAnyOf="Ludeon.RimWorld.Royalty,Ludeon.RimWorld.Biotech">
 
</pre>
 
Would enable the content when Royalty and/or Biotech are enabled.
 
  
 
=Next up=
 
=Next up=
  
* [[Modding_Tutorials/Modifying defs|Def Class Compatibility]] explains compatibility from the Def Class side of things.
 
 
* [[Modding Tutorials/Compatibility with DLLs|Create a DLL patch]] continues explanations on compatibility patching and referencing existing items.
 
* [[Modding Tutorials/Compatibility with DLLs|Create a DLL patch]] continues explanations on compatibility patching and referencing existing items.
 +
* [[Modding Tutorials/Injection|C# injection]] is an in-depth guide on using C# injection to resolve compatibility issues.<br/>
  
 
[[Category:Modding tutorials]]
 
[[Category:Modding tutorials]]

Please note that all contributions to RimWorld Wiki are considered to be released under the CC BY-SA 3.0 (see RimWorld Wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

Cancel Editing help (opens in new window)

This page is a member of 1 hidden category: