Help a newbie mod creator understand something.

Started by Chillyconmor, May 07, 2019, 09:39:16 PM

Previous topic - Next topic

Chillyconmor

I am horribly bad at creating mods in this game, but everyone has to start somewhere, right?

For my first mod, i'm trying to let you remove any limb from any human via the surgery tab without the conditions we have right now (such as infection) . As far as I know, I think I have to edit the Recipe_RemoveBodyPart thing. How can I come about this? If i'm wrong, please tell me. Thanks in advance.

LWM

Yeah, that sounds about right.

Another approach would be to modify the xml file (using the xpath patching) to point to a *new* workerClass and then write that new C# workerClass that is derived from Recipe_RemoveBodyPart.  Then you could change whatever you need by writing your own override methods.

But one way or another, C#.

--LWM

Chillyconmor

#2
Thanks for the quick reply, and sorry for the late response.

I'm still slightly confused on what you mean by "point to a *new* workerClass and then write that new C# workerClass that is derived from Recipe_RemoveBodyPart"

This is what I think I need to do:
>Create the mod folder under Rimworld/mods and title it something like "Remove Any Limb Unconditionally"
>Create an About and Defs folder under that
>Go into the Defs folder

And this is where i'm confused yet again, because I don't know if I have to copy and paste Recipes_Surgery_Misc from the Core folder, or create an entirely new xml file, and if I did have to create an entirely new xml file, I don't know what i'm supposed to name it. If I create a new xml file, will I have to use a code such as

<?xml version="1.0" encoding="utf-8" ?>
<Patch>
<Operation Class="PatchOperationReplace">
    <xpath>/ThingDefs/ThingDef[defName = "RemoveBodyPart"]/verbs/li/!-- whatever i need to put here --</xpath>
    <value>
                <!-- whatever i need to put here -->
    </value>
</Operation>
</Patch>


or, if I have to copy and paste Recipes_Surgery_Misc, if I just add it somewhere under <RecipeDef ParentName="Surgery_Flesh">

Please include the part where you said I had to point to a new workerClass into my code and that would be great, and please correct me if anything is wrong and how I should do this, be it copy and paste or a new xml file.

LWM

Heh, because it's super fresh on my mind (just posted it):  https://github.com/lilwhitemouse/RimWorld-PrayerSpot

You can see what I did there:
In Patches I change one of the base Defs to point to my driver, I made my driver a derived class from the original driver, and I wrote my own override of the base function to do what I wanted.

Don't have much more time at the moment to explain, but I hope that can give you an idea of how such a thing can be done.  Got to run,

--LWM

Chillyconmor

Please, respond when you can, but I think I might have most of the idea now.

At the moment, my code looks like

<?xml version="1.0" encoding="utf-8" ?>
<patch>

<Operation Class="PatchOperationReplace">
<xpath>/Defs/RecipeDefs/Recipes_Surgery_Misc[defName="RemoveBodyPart"]/giverClass</xpath>

<value>
       <!-- confused on what to put here atm-->
</value>

</Operation>

</patch>


I assume i'm gonna have to go into the C# code and find Recipes_Surgery_Misc and look for RemoveBodyPart, modify its current code, and then copy and paste it under my mod folder with a new name such as URRemoveBodyPart, and change RemoveBodyPart to URRemoveBodyPart? I still don't know what to put in between the two value tags.

LWM

Mostly right.  If you look in the XML Defs for Core RimWorld, you'll find RecipeDefs/Recipes_Surgery_Misc.xml, which has the recipe.  It uses a *workerClass*, so you'd replace the workerClass, not the giverClass (giverClass was for replacing the "job giver" - which is distinct from a "job driver" or a ....)  The important part is to get exactly the correct type :p

<value>
  <workerClass>URRemoveBodyPart</workerClass>
</value>


Then you'd write a C# driver to do what you want.  You'd probably look in the code for whatever workerClass the recipe uses and then derive your class from it.  (How much object oriented c# do you know?)

Hope that helps,  --LWM

Chillyconmor

To be honest, I had no experience in C# before now, but I don't know exactly what to change. The code area I think I need to modify is,

IEnumerable<BodyPartRecord> parts = pawn.health.hediffSet.GetNotMissingParts(BodyPartHeight.Undefined, BodyPartDepth.Undefined, null, null);
using (IEnumerator<BodyPartRecord> enumerator = parts.GetEnumerator())
{
while (enumerator.MoveNext())
{
BodyPartRecord part = enumerator.Current;
if (pawn.health.hediffSet.HasDirectlyAddedPartFor(part))
{
yield return part;
}
else if (MedicalRecipesUtility.IsCleanAndDroppable(pawn, part))
{
yield return part;
}
else if (part != pawn.RaceProps.body.corePart && part.def.canSuggestAmputation && pawn.health.hediffSet.hediffs.Any((Hediff d) => !(d is Hediff_Injury) && d.def.isBad && d.Visible && d.Part == part))
{
yield return part;
}
}
}

The specific part I noticed was this block,

else if (part != pawn.RaceProps.body.corePart && part.def.canSuggestAmputation && pawn.health.hediffSet.hediffs.Any((Hediff d) => !(d is Hediff_Injury) && d.def.isBad && d.Visible && d.Part == part))
{
yield return part;
}

Since I can see a lot of hediffs in here and a part.def.canSuggestAmputation, I can assume this is what I need to remove. Is this correct?

Oh, and by the way, thanks a ton LWM; You're really helpful and I'm glad you kept up with my lack of knowledge on how modding works in this game.