Difference between revisions of "Modding Tutorials/MayRequire"

From RimWorld Wiki
Jump to navigation Jump to search
Line 6: Line 6:
 
== Details ==
 
== Details ==
  
<code>MayRequire</code> is inserted as an XML attribute in a supported XML node with a value being one or more <code>packageId</code> values separated by commas.
+
<code>MayRequire</code> is inserted as an XML attribute in a supported XML node with a value being one or more <code>packageId</code> values separated by commas. Currently, <code>MayRequire</code> only works on list entries, stat entries, and Def root nodes.
  
 
The <code>packageId</code> for official DLCs are:
 
The <code>packageId</code> for official DLCs are:

Revision as of 20:39, 4 June 2023

?
Under Review
This tutorial or guide is currently undergoing review and should not be considered ready to use.

MayRequire is an XML attribute introduced alongside the Royalty DLC that allows for easy conditional loading of XML content. MayRequire makes it easier to load content that is optionally dependent on DLCs or other mods.

Details

MayRequire is inserted as an XML attribute in a supported XML node with a value being one or more packageId values separated by commas. Currently, MayRequire only works on list entries, stat entries, and Def root nodes.

The packageId for official DLCs are:

  • Royalty: Ludeon.RimWorld.Royalty
  • Ideology: Ludeon.RimWorld.Ideology
  • Biotech: Ludeon.RimWorld.Biotech

The packageId for mods can be found in their About.xml file.

MayRequireAnyOf

By default, MayRequire will only allow the use of that node if all of the DLCs or mods it designates are loaded. If you instead want to load the specified node if any of the specified DLCs or mods are loaded, you can use MayRequireAnyOf instead.

List Entries

MayRequire can be on any li node to only load that entry if the specified DLC or mod is loaded:

XML Example Description
<ThingDef ParentName="BasePawn">
  <defName>Human</defName>
  <label>human</label>
  
  <!-- irrelevant nodes omitted -->
  
  <recipes>
    <li>ExciseCarcinoma</li>
    <li>AdministerMechSerumHealer</li>
    <li>RemoveBodyPart</li>
    <li>Euthanize</li>
    <li>Anesthetize</li>
    <li>CureScaria</li>
    <li MayRequire="Ludeon.RimWorld.Biotech">Vasectomy</li>
    <li MayRequire="Ludeon.RimWorld.Biotech">ReverseVasectomy</li>
    <li MayRequire="Ludeon.RimWorld.Biotech">TubalLigation</li>
    <li MayRequire="Ludeon.RimWorld.Biotech">ExtractOvum</li>
    <li MayRequire="Ludeon.RimWorld.Royalty">CureBloodRot</li>
    <li MayRequire="Ludeon.RimWorld.Royalty">CureAbasia</li>
    <li MayRequire="Ludeon.RimWorld.Biotech">ExtractHemogenPack</li>
    <li MayRequire="Ludeon.RimWorld.Biotech">BloodTransfusion</li>
    <li MayRequire="Ludeon.RimWorld.Biotech">ImplantXenogerm</li>
    <li MayRequire="Ludeon.RimWorld.Biotech">ImplantIUD</li>
    <li MayRequire="Ludeon.RimWorld.Biotech">RemoveIUD</li>
    <li MayRequire="Ludeon.RimWorld.Biotech">TerminatePregnancy</li>
  </recipes>
  
  <!-- irrelevant nodes omitted -->
  
</ThingDef>

MayRequire is used in the Human ThingDef to set surgery recipes that are only relevant to specific DLCs. Without MayRequire, these would cause errors as the specified Defs only exist in their respective DLCs.

<SurgeryOutcomeEffectDef Name="SurgeryOutcomeBase">
  <defName>SurgeryOutcomeBase</defName>
  <outcomes>
    <li Class="SurgeryOutcomeSuccess" />
    
    <!-- irrelevant nodes omitted -->
    
    <li Class="SurgeryOutcome_FailureWithHediff"  MayRequire="Ludeon.RimWorld.Biotech">
      <chance>0.03</chance>
      <failedHediff>Sterilized</failedHediff>
      <applyToRecipes>
        <li MayRequire="Ludeon.RimWorld.Biotech">ImplantIUD</li>
        <li MayRequire="Ludeon.RimWorld.Biotech">RemoveIUD</li>
      </applyToRecipes>
      <failure>true</failure>
      <totalDamage>10</totalDamage>
      <applyEffectsToPart>true</applyEffectsToPart>
      <letterLabel>Surgery failed on {PATIENT_labelShort}: Sterilized</letterLabel>
      <letterText>{SURGEON_labelShort} has failed while operating on {PATIENT_labelShort} ({RECIPE_label}), leaving {PATIENT_objective} sterile.</letterText>
    </li>
    
    <!-- irrelevant nodes omitted -->
    
  </outcomes>
  
  <!-- irrelevant nodes omitted -->
  
</SurgeryOutcomeEffectDef>

MayRequire is used in the list of possible surgery outcomes to add the possibility of accidentally sterilizing the patient as a result of a surgery failure.

Note that the use of MayRequire on the list nodes of the <applyToRecipes> is technically unnecessary as the entire outcome node would not have loaded without Biotech active.

<AlienRace.ThingDef_AlienRace Name="ARR_RaceBase" ParentName="HumanRace" Abstract="True">

  <!-- irrelevant nodes omitted -->

  <comps>
    <li Class="ARimReborn.CompProperties_ClassUser" MayRequire="Aelanna.ARimReborn.ClassesAndJobs" />
  </comps>

  <inspectorTabs>
    <li MayRequire="Aelanna.ARimReborn.ClassesAndJobs">ARimReborn.ITab_Pawn_Classes</li>
  </inspectorTabs>

</AlienRace.ThingDef_AlienRace>

MayRequire can be used to omit entire code components.

In this modded example, both a ThingComp and an inspector tab are only added if a specific sub-mod is loaded.

<Operation Class="PatchOperationSequence">
  <operations>
    <li Class="PatchOperationAdd" MayRequire="Ludeon.Rimworld.Biotech"> <!-- Only runs if Biotech is active -->
      <xpath>Defs/ThingDef[defName="MechGestator"]/recipes<xpath>
      <value>
        <li>MyCustomMech</li>
      </value>
    </li>
    <li Class="PatchOperationAdd" MayRequire="MyProject.OtherModPackageId"><!-- Only runs if the specific mod is active -->
      <xpath>Defs/ThingDef[defName="OtherModWorkbench"]/recipes</xpath>
      <value>
        <li>MyCustomResource</li>
      </value>
    </li>
  </operations>
</Operation>

MayRequire can be used in lieu of PatchOperationFindMod in a PatchOperationSequence.

Warning: PatchOperationSequence can obfuscate errors, so it is strongly recommended that you individually test patches first before you place them in a sequence. Please see PatchOperations for more information.

Stat Blocks

MayRequire can be used by any StatModifier list, which includes all statBases, statOffsets, statFactors, and equippedStatOffsets nodes:

XML Description
<ThingDef ParentName="ApparelMakeableBase">
  <defName>Apparel_Duster</defName>
  
  <!-- irrelevant tags omitted -->
  
  <equippedStatOffsets>
    <SlaveSuppressionOffset MayRequire="Ludeon.RimWorld.Ideology">-0.05</SlaveSuppressionOffset>
  </equippedStatOffsets>
  
  <!-- irrelevant tags omitted -->
</ThingDef>

MayRequire is used by several vanilla apparel ThingDefs to apply stats that are only relevant to DLCs, such as the SlaveSuppressionOffset stat from Ideology.

<ThingDef Name="TorchLamp" ParentName="BuildingBase">
  <defName>TorchLamp</defName>
  <label>torch lamp</label>
  
  <!-- irrelevant nodes omitted -->
  
  <statBases>
    <MaxHitPoints>75</MaxHitPoints>
    <WorkToBuild>100</WorkToBuild>
    <Flammability>0</Flammability>
    <MeditationFocusStrength>0.0</MeditationFocusStrength>
    <StyleDominance MayRequire="Ludeon.RimWorld.Ideology">5</StyleDominance>
  </statBases>
  
  <!-- irrelevant nodes omitted -->
  
</ThingDef>

MayRequire is used by several vanilla buildings such as the torch lamp to determine how much that particular building influences the overall style of the room it is in. This is also an Ideology feature.

Optional Defs

MayRequire can be used to conditionally load entire Defs. This is far easier to use than the prior option of using PatchOperations to inject new Defs.

XML Description
<ThingDef MayRequire="Ludeon.RimWorld.Ideology" ParentName="Brazier">
  <defName>DarklightBrazier</defName>
  <label>darklight brazier</label>
  <description>A specially treated brazier that illuminates its surroundings with darklight and creates heat. These satisfy royal brazier requirements.</description>
  
  <!-- irrelevant content omitted -->

</ThingDef>

MayRequire is used to activate Royalty's darklight brazier stat if Ideology is also loaded.

<StatDef ParentName="MeditationFocusBase" MayRequireAnyOf="Ludeon.RimWorld.Royalty,Ludeon.RimWorld.Biotech">
  <defName>MeditationFocusGain</defName>
  <label>meditation psyfocus gain</label>
  
  <!-- irrelevant content omitted -->
  
</StatDef>

MayRequireAnyOf is used to activate the MeditationFocusGain stat if either Royalty or Biotech is loaded.

<ThingDef ParentName="ApparelMakeableBase" MayRequireAnyOf="Ludeon.RimWorld.Royalty,Ludeon.RimWorld.Biotech">
  <defName>Apparel_Cape</defName>
  <label>cape</label>
  
  <!-- irrelevant content omitted -->
  
</ThingDef>

MayRequireAnyOf is used to activate the Cape apparel if either Royalty or Biotech is loaded.