Help with body mod

Started by Mari, August 08, 2016, 12:01:26 AM

Previous topic - Next topic

Mari

Hello,

I didn't like my female colonists having the larger body types, so I tried to make a mod addressing this. I read on the forums that the body types are hardcoded based on the backstories, but I thought it might be possible. I (perhaps obviously) have very little experience with C# but my idea was basically to detour with CCL the method that loads in the backstories and then replace the body types before adding them to the dictionary, but for some reason it won't work the way I have it written. I suspect I am doing something obviously wrong, or it may just be impossible.

Here is my code:

using System;
using Verse;
using RimWorld;
using CommunityCoreLibrary;

namespace FemaleBodyTypes
{
[StaticConstructorOnStartup]
public class FemaleBodyTypes {

public FemaleBodyTypes() {
System.Reflection.MethodInfo method = typeof(BackstoryDatabase).GetMethod("ReloadAllBackstories", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
System.Reflection.MethodInfo method2 = typeof(FemaleBodyTypes).GetMethod("ReplaceBodyTypes", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
Detours.TryDetourFromTo(method, method2);
}

public static void ReplaceBodyTypes() {

foreach (Backstory current in XmlLoader.LoadXmlDataInResourcesFolder<Backstory>("Backstories/Shuffled"))
{
current.PostLoad();
current.ResolveReferences();

if (current.bodyTypeFemale == BodyType.Hulk) {
current.bodyTypeFemale = BodyType.Female;
}
if (current.bodyTypeFemale == BodyType.Fat) {
current.bodyTypeFemale = BodyType.Thin;
}
foreach (string current2 in current.ConfigErrors(false))
{
Log.Error(current.title + ": " + current2);
}
BackstoryDatabase.AddBackstory(current);
}
SolidBioDatabase.LoadAllBios();
}
}
}


My idea was to detour the method that builds the backstory dictionary in the constructor of my class to a method that is basically identical except having a couple extra if statements to replace the body types as they are read in. It seems like the constructor is never even being called though, so I am clearly in over my depth. Maybe there is something really obvious I am doing wrong, so I was hoping someone with more C# experience and knowledge of the game code could help me.

Thanks a lot!

robotguy4

#1
While I can't be much help, I suggest you ultimately make your mod have more options in terms of what body types to block.

A mod that just blocks just one type isn't going to be very useful to many people. One that can block specified ones would be useful to many people.

EDIT: The only help I can offer is to look at this. It might help: https://github.com/Skullywag/ReclaimFabric/blob/master/Source/ReclaimFabric/_Thing.cs

Someone else probably will be able to help you out more.

Mari

Quote from: robotguy4 on August 08, 2016, 03:39:38 AM
While I can't be much help, I suggest you ultimately make your mod have more options in terms of what body types to block.

A mod that just blocks just one type isn't going to be very useful to many people. One that can block specified ones would be useful to many people.

Thanks! I plan to make a more useful version once I get the basic thing working. I just wanted to try making it for my personal use as a challenge but assuming it actually is possible to do this at all, it'll be much easier to generalize that into something more useful once I understand how it actually works. I have definitely seen a few people asking for something like that so if I can figure it out I'd be happy to try to make a configurable version.

I will try looking at that code you linked, it might help if I mess around with it a bit. It looks like that modder overwrote the SpecialInjector class in CCL, I can try doing that instead for a start.

Mari

#3
Shockingly, I actually managed to make it work by using a special injector and then calling the method from the injector itself since it seems that method runs before CCL special injectors in the loading process? Thanks for posting that reference robotguy!

If anyone ever is searching for something similar and finds this thread, I used two classes. The first one uses SpecialInjector to override and call the backstory loading method on startup:

using CommunityCoreLibrary;
using System;
using RimWorld;

namespace FemaleBodyTypes
{
public class DetourInjector : SpecialInjector
{
public override bool Inject() {
System.Reflection.MethodInfo method = typeof(BackstoryDatabase).GetMethod("ReloadAllBackstories", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
System.Reflection.MethodInfo method2 = typeof(FemaleBodyTypes).GetMethod("ReplaceBodyTypes", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
Detours.TryDetourFromTo(method, method2);
BackstoryDatabase.Clear();
BackstoryDatabase.ReloadAllBackstories();
return true;
}
}
}


and the second one contains the code to rebuild the dictionary of backstories:

using System;
using Verse;
using RimWorld;
using CommunityCoreLibrary;

namespace FemaleBodyTypes
{
public static class FemaleBodyTypes {

public static void ReplaceBodyTypes() {

foreach (Backstory current in XmlLoader.LoadXmlDataInResourcesFolder<Backstory>("Backstories/Shuffled"))
{
current.PostLoad();
current.ResolveReferences();

if (current.bodyTypeFemale == BodyType.Hulk) {
current.bodyTypeFemale = BodyType.Male;
}
if (current.bodyTypeFemale == BodyType.Fat) {
current.bodyTypeFemale = BodyType.Thin;
}
foreach (string current2 in current.ConfigErrors(false))
{
Log.Error(current.title + ": " + current2);
}
BackstoryDatabase.AddBackstory(current);
}
SolidBioDatabase.LoadAllBios();
}
}
}


In principle it seems like that method could be used to mod other aspects of the hardcoded default backstories like their stats or which types of work are allowed, or remove some completely based on title or id if you wanted. In any case, I will get working on a more generalized configurable version now, maybe with CCL mod config menus, I'll post it here and on steam when it's finished.

Edit: finished the mod: https://ludeon.com/forums/index.php?topic=24173.0