Added animal inheritance to RJW-genes code

This commit is contained in:
Shabakur 2022-12-01 15:29:26 +01:00
parent b5033deef6
commit 33a37f26de
17 changed files with 821 additions and 9 deletions

View file

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using rjw;
using Verse;
using RimWorld;
namespace RJW_BGS
{
[StaticConstructorOnStartup]
internal static class First
{
static First()
{
RJWcopy.Racegroupdictbuilder();
//foreach (RaceGroupDef raceGroupDef2 in DefDatabase<RaceGroupDef>.AllDefs)
//{
//Log.Message("defName = " + raceGroupDef2.defName);
// if (raceGroupDef2.raceNames != null)
// {
// foreach (string race in raceGroupDef2.raceNames)
// {
//Log.Message(race);
// }
// }
//}
}
}
}

View file

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
using Verse;
namespace RJW_BGS
{
[StaticConstructorOnStartup]
internal static class HarmonyInit
{
// Token: 0x0600001F RID: 31 RVA: 0x000029A4 File Offset: 0x00000BA4
static HarmonyInit()
{
Harmony harmony = new Harmony("RJW_BGS");
harmony.PatchAll();
}
}
}

View file

@ -0,0 +1,134 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using RimWorld;
namespace RJW_BGS
{
public class InheritanceUtility
{
public static List<GeneDef> AnimalInheritedGenes(Pawn father, Pawn mother)
{
//One parent must be an animal and the other must be human, so only one needs to return
List<GeneDef> genelist = new List<GeneDef>();
if (father != null && !father.RaceProps.Humanlike)
{
return SelectGenes(father);
}
if (mother != null && !mother.RaceProps.Humanlike)
{
return SelectGenes(mother);
//PawnKindDef pawnKindDef = mother.kindDef;
//RaceGeneDef raceGeneDef = RJWcopy.GetRaceGenDefInternal(pawnKindDef);
//if (raceGeneDef != null)
//{
// GeneDef gene = null;
//In case you hit a modded gene not currently active try again.
// for (int i = 0; i < 50 || gene == null; i++)
// {
// if (raceGeneDef.genes.Any())
// {
// gene = DefDatabase<GeneDef>.GetNamed(raceGeneDef.genes.RandomElement());
// }
// }
// if (gene != null)
// {
// genelist.Add(gene);
//
// }
//
// }
}
return genelist;
}
public static List<GeneDef> SelectGenes(Pawn pawn)
{
List<GeneDef> genelist = new List<GeneDef>();
PawnKindDef pawnKindDef = pawn.kindDef;
RaceGeneDef raceGeneDef = RJWcopy.GetRaceGenDefInternal(pawnKindDef);
if (raceGeneDef != null)
{
int num1 = raceGeneDef.genes.Count;
int num2 = raceGeneDef.genechances.Count;
if (num1 != num2)
{
Log.Error("The amount of genes and genechanches are different in " + raceGeneDef.defName + ". Can't select genes to inherit");
return genelist;
}
for (int i = 0; i<num1; i++)
{
if (raceGeneDef.genechances[i] > Rand.Range(0.01f, 1f))
{
genelist.Add(DefDatabase<GeneDef>.GetNamed(raceGeneDef.genes[i]));
}
}
}
return genelist;
}
public static void AddGenes(Pawn pawn, List<GeneDef> genes)
{
foreach (GeneDef gene in genes)
{
pawn.genes.AddGene(gene, false);
}
}
public static void NewGenes(Pawn mother, Pawn dad, Pawn baby)
{
if (baby.RaceProps.Humanlike)
{
if (baby.genes == null)
{
baby.genes = new Pawn_GeneTracker(baby);
}
//Remove the hair and skin genes pawns always start with, should get correct ones from human parent anyway.
for (int i = baby.genes.Endogenes.Count - 1; i >= 0; i--)
{
baby.genes.RemoveGene(baby.genes.Endogenes[i]);
}
List<GeneDef> genes = PregnancyUtility.GetInheritedGenes(dad, mother);
List<GeneDef> beastgenes = InheritanceUtility.AnimalInheritedGenes(dad, mother);
InheritanceUtility.AddGenes(baby, beastgenes);
InheritanceUtility.AddGenes(baby, genes);
if(baby.genes.GetFirstEndogeneByCategory(EndogeneCategory.Melanin) == null)
{
AddSkinColor(mother, dad, baby);
}
}
}
public static void AddSkinColor(Pawn mother, Pawn father, Pawn baby)
{
if (mother != null && mother.genes != null)
{
GeneDef gene = mother.genes.GetFirstEndogeneByCategory(EndogeneCategory.Melanin);
if (gene != null)
{
baby.genes.AddGene(gene, false);
}
}
else if (father != null && father.genes != null)
{
GeneDef gene = father.genes.GetFirstEndogeneByCategory(EndogeneCategory.Melanin);
if (gene != null)
{
baby.genes.AddGene(gene, false);
}
}
else
{
Log.Message("Could not find skincolor of " + baby.Name + "'s parents, giving random skincolor.");
baby.genes.AddGene(PawnSkinColors.RandomSkinColorGene(baby), false);
}
}
}
}

View file

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
using RimWorld;
using Verse;
using rjw;
namespace RJW_BGS
{
[HarmonyPatch(typeof(Hediff_BasePregnancy), "Initialize")]
public static class PatchRJWBestialityPregnancyUtility
{
[HarmonyPostfix]
public static void AddGenes(Pawn mother, Pawn dad, ref Hediff_BasePregnancy __instance)
{
foreach (Pawn baby in __instance.babies)
{
if (baby.RaceProps.Humanlike)
{
if (baby.genes == null)
{
baby.genes = new Pawn_GeneTracker(baby);
}
//Remove the hair and skin genes pawns always start with, should get correct ones from human parent anyway.
for (int i = baby.genes.Endogenes.Count - 1; i >= 0; i--)
{
baby.genes.RemoveGene(baby.genes.Endogenes[i]);
}
List<GeneDef> genes = PregnancyUtility.GetInheritedGenes(dad, mother);
List<GeneDef> beastgenes = InheritanceUtility.AnimalInheritedGenes(dad, mother);
InheritanceUtility.AddGenes(baby, beastgenes);
InheritanceUtility.AddGenes(baby, genes);
//foreach (GeneDef gene in genes)
//{
// baby.genes.AddGene(gene, false);
//}
}
}
}
}
}

View file

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
using rjw;
using RimWorld;
using Verse;
namespace RJW_BGS
{
[HarmonyPatch(typeof(Hediff_InsectEgg), "GiveBirth")]
public static class PatchRJWHediffInsect_Egg
{
[HarmonyTranspiler]
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
MethodInfo newgenes = AccessTools.Method(typeof(InheritanceUtility), "NewGenes", null, null);
FieldInfo implanter = AccessTools.Field(typeof(Hediff_InsectEgg), "implanter");
FieldInfo father = AccessTools.Field(typeof(Hediff_InsectEgg), "father");
foreach (CodeInstruction instruction in instructions)
{
yield return instruction;
if (instruction.opcode == OpCodes.Call && instruction.operand.ToString() == "Void BabyPostBirth(Verse.Pawn, Verse.Pawn, Verse.Pawn)")
{
yield return new CodeInstruction(OpCodes.Ldloc_0, null);
yield return new CodeInstruction(OpCodes.Ldfld, implanter);
yield return new CodeInstruction(OpCodes.Ldarg_0, null);
yield return new CodeInstruction(OpCodes.Ldfld, father);
yield return new CodeInstruction(OpCodes.Ldloc_1, null);
yield return new CodeInstruction(OpCodes.Call, newgenes);
}
}
}
}
}

View file

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
using RimWorld;
using Verse;
using rjw;
namespace RJW_BGS
{
[HarmonyPatch(typeof(PregnancyUtility), "GetInheritedGeneSet", new Type[]
{
typeof(Pawn),
typeof(Pawn),
//typeof(bool)
}
)]
public static class PatchVanillaPregnancyUtility
{
[HarmonyPostfix]
public static void AnimalInheritedGenes(Pawn father, Pawn mother, ref GeneSet __result)
{
List<GeneDef> genes = InheritanceUtility.AnimalInheritedGenes(father, mother);
if (genes.Any())
{
foreach (GeneDef gene in genes)
{
__result.AddGene(gene);
}
}
}
}
}

View file

@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using rjw;
using Verse;
using RimWorld;
namespace RJW_BGS
{
internal class RJWcopy
{
//Code copied from rjw, as their code was internal and I need the dictionary to know which genes to add to the pawn
public static void Racegroupdictbuilder()
{
foreach (PawnKindDef pawnKindDef2 in from pawnKindDef in DefDatabase<PawnKindDef>.AllDefs
where pawnKindDef.race.race != null
select pawnKindDef)
{
RaceGroupDef raceGroupDef = null;
bool temp = TryGetRaceGroupDef(pawnKindDef2, out raceGroupDef);
}
}
public static bool TryGetRaceGroupDef(PawnKindDef pawnKindDef, out RaceGroupDef raceGroupDef)
{
if (RaceGroupByPawnKind.TryGetValue(pawnKindDef, out raceGroupDef))
{
return raceGroupDef != null;
}
raceGroupDef = GetRaceGroupDefInternal(pawnKindDef);
RaceGroupByPawnKind.Add(pawnKindDef, raceGroupDef);
return raceGroupDef != null;
}
//slightly modified code so it also works racegroupdefs
public static RaceGroupDef GetRaceGroupDefInternal(PawnKindDef kindDef)
{
string raceName = kindDef.race.defName;
string pawnKindName = kindDef.defName;
IEnumerable<RaceGroupDef> allDefs = DefDatabase<RaceGroupDef>.AllDefs;
List<RaceGroupDef> list = allDefs.Where(delegate (RaceGroupDef group)
{
List<string> pawnKindNames = group.pawnKindNames;
return pawnKindNames != null && pawnKindNames.Contains(pawnKindName);
}).ToList<RaceGroupDef>();
List<RaceGroupDef> list2 = allDefs.Where(delegate (RaceGroupDef group)
{
List<string> raceNames = group.raceNames;
return raceNames != null && raceNames.Contains(raceName);
}).ToList<RaceGroupDef>();
int num = list.Count<RaceGroupDef>() + list2.Count<RaceGroupDef>();
if (num == 0)
{
return null;
}
if (num == 1)
{
return list.Concat(list2).Single<RaceGroupDef>();
}
RaceGroupDef result;
if ((result = list.FirstOrDefault((RaceGroupDef match) => !IsThisMod(match))) == null)
{
if ((result = list2.FirstOrDefault((RaceGroupDef match) => !IsThisMod(match))) == null)
{
result = (list.FirstOrDefault<RaceGroupDef>() ?? list2.FirstOrDefault<RaceGroupDef>());
}
}
return result;
}
public static RaceGeneDef GetRaceGenDefInternal(PawnKindDef kindDef)
{
if (kindDef == null)
{
return null;
}
string raceName = kindDef.race.defName;
string pawnKindName = kindDef.defName;
RaceGroupDef raceGroupDef = GetRaceGroupDef(kindDef);
//string raceGroupName = GetRaceGroupDef(kindDef).defName;
IEnumerable<RaceGeneDef> allDefs = DefDatabase<RaceGeneDef>.AllDefs;
Log.Message(allDefs.Count<RaceGeneDef>().ToString());
List<RaceGeneDef> list = allDefs.Where(delegate (RaceGeneDef group)
{
List<string> pawnKindNames = group.pawnKindNames;
return pawnKindNames != null && pawnKindNames.Contains(pawnKindName);
}).ToList<RaceGeneDef>();
List<RaceGeneDef> list2 = allDefs.Where(delegate (RaceGeneDef group)
{
List<string> raceNames = group.raceNames;
return raceNames != null && raceNames.Contains(raceName);
}).ToList<RaceGeneDef>();
List<RaceGeneDef> list3 = new List<RaceGeneDef>();
if (raceGroupDef != null)
{
Log.Message("found a raceGroupDef");
Log.Message(raceGroupDef.defName);
foreach (RaceGeneDef rgd in allDefs)
{
Log.Message(rgd.defName);
}
list3 = allDefs.Where(delegate (RaceGeneDef group)
{
String raceGroupDefName = group.raceGroup;
return raceGroupDefName != null && raceGroupDefName == raceGroupDef.defName;
}).ToList<RaceGeneDef>();
}
RaceGeneDef result = null;
//First check if there is a matching pawnkinddef then race, then racegroup
if (list.Any())
{
result = list.RandomElement();
}
else if (list2.Any() && result == null)
{
result = list2.RandomElement();
}
else if (list3.Any() && result == null)
{
result = list3.RandomElement();
}
else
{
result = null;
}
return result;
}
private static RaceGroupDef GetRaceGroupDef(PawnKindDef kindDef)
{
RaceGroupDef raceGroupDef = null;
bool temp = TryGetRaceGroupDef(kindDef, out raceGroupDef);
return raceGroupDef;
}
private static bool IsThisMod(Def def)
{
return LoadedModManager.RunningMods.Single((ModContentPack pack) => pack.Name == "RimJobWorld").AllDefs.Contains(def);
}
private static readonly IDictionary<PawnKindDef, RaceGroupDef> RaceGroupByPawnKind = new Dictionary<PawnKindDef, RaceGroupDef>();
}
}

View file

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using rjw;
namespace RJW_BGS
{
public class RaceGeneDef : Def
{
public String raceGroup;
public List<string> raceNames;
public List<string> pawnKindNames;
public List<string> genes;
public List<float> genechances;
public String hybridName;
}
}