diff --git a/Source/Genes/Hive/Helpers/HiveBirthLogic.cs b/Source/Genes/Hive/Helpers/HiveBirthLogic.cs deleted file mode 100644 index faf8534..0000000 --- a/Source/Genes/Hive/Helpers/HiveBirthLogic.cs +++ /dev/null @@ -1,141 +0,0 @@ -using RimWorld; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Reflection.Emit; -using System.Text; -using System.Threading.Tasks; -using Verse; - -namespace RJW_Genes -{ - /// - /// DevNote: Issue #37 came along because I checked for getMother() and getFather(), but it can happen that a pawn has two mothers. - /// They are called Mother if they have a ParentRelation and are female. - /// New behaviour iterates over all parents and returns the first queen/drone or null. - /// - public class HiveBirthLogic - { - /// - /// Central function for the Hive-Birth logic used in Patches. - /// *Only* run this, if the pawn has a queen parent (either as mother/father, or as implanter in case of egg-logic). - /// Covers the following behavior: - /// 1. look up the Defs for the mother and HiveOffspringChances (or defaults) - /// 2. If there is no drone involved, default to worker - /// 3. Roll a random dice - /// 3.1 Make a queen - /// 3.2 Make a drone - /// 3.3 Make a worker - /// - /// The pawn born, that maybe becomes a hive-xenotype. - /// whether there was a drone parent involved - public static void ManageHiveBirth(Pawn pawn, bool hasDroneParent = false) - { - XenotypeDef queenDef = TryFindParentQueenXenotype(pawn); - HiveOffspringChanceDef hiveOffspringChanceDef = HiveUtility.LookupHiveInheritanceChances(queenDef); - - // Case 1: Mother is Queen, Father is something else. Produce Worker. - if (!hasDroneParent) - { - if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawn} was born as a worker, as it did not have Drone Father ({100}% chance)"); - MakeWorker(pawn, queenDef); - } - // Case 2: Mother is Queen, Father is drone. Apply xenotype as per chance. - else - { - double roll = (new Random()).NextDouble(); - // Case 2.a: New Queen born - if (roll < hiveOffspringChanceDef.queenChance) - { - pawn.genes.SetXenotype(queenDef); - if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawn} born as a new queen with xenotype {queenDef.defName} ({hiveOffspringChanceDef.queenChance * 100}% chance,rolled {roll})"); - // TODO: Make a letter ? Letter doesn't show :( - Find.LetterStack.ReceiveLetter("New Queen", "A new Queen was born! Make sure to adress inheritance before the new queen reaches adolesence.", LetterDefOf.BabyBirth, (LookTargets)(Thing)pawn); - } - // Case 2.b: New Drone born - else if (roll < hiveOffspringChanceDef.droneChance + hiveOffspringChanceDef.queenChance) - { - XenotypeDef droneDef = TryFindParentDroneXenotype(pawn); - pawn.genes.SetXenotype(droneDef); - if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawn} born as a new drone with xenotype {droneDef.defName} ({(hiveOffspringChanceDef.droneChance + hiveOffspringChanceDef.queenChance) * 100}% chance,rolled {roll}))"); - } - // Case 2.c: Worker - else - { - if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawn} born as a worker ({(hiveOffspringChanceDef.workerChance) * 100}% chance,rolled {roll}))"); - MakeWorker(pawn, queenDef); - } - } - } - - - /// - /// Turns a given pawn into a worker, by looking up the relevant genes as per queen. - /// - /// If the queen xenotype has no mapping, the "rjw_genes_default_worker_xenotype" are used instead. - /// The genes are added as endogenes, so the worker can still become a xenotype. - /// - /// The pawn for which the genes are added. - /// The xenotype of the queen, used for lookup. - private static void MakeWorker(Pawn pawnTobeWorker, XenotypeDef queenDef) - { - if (pawnTobeWorker == null) - return; - - var mappings = HiveUtility.GetQueenWorkerMappings(); - - var genes = mappings.TryGetValue(queenDef, HiveUtility.LookupDefaultWorkerGenes()); - - foreach (var gene in genes) - pawnTobeWorker.genes.AddGene(gene, false); - - pawnTobeWorker.genes.xenotypeName = "Worker"; - } - - /// - /// Looks up if there is a Xenotype with Drone-Gene for the pawns parents. - /// This is to account that maybe father or mother are the drone (instead of hardcoding things for father). - /// If both are drones, the mothers is returned. - /// - /// The pawn for whichs parent the xenotypes is looked up. - /// The Drone-Xenotype of a parent or null. If both are drones, mothers are preferred. - public static XenotypeDef TryFindParentDroneXenotype(Pawn pawn) - { - if (pawn == null) - return null; - - List parentRelations = pawn.relations.DirectRelations.FindAll(rel => rel.def.Equals(PawnRelationDefOf.Parent)); - foreach (DirectPawnRelation parent in parentRelations) - { - XenotypeDef xenotype = HiveUtility.TryGetDroneXenotype(parent.otherPawn); - if (xenotype != null) return xenotype; - } - - return null; - } - - - /// - /// Looks up if there is a Xenotype with Queen-Gene for the pawns parents. - /// This is to account that maybe father or mother are the queen (instead of hardcoding things for father). - /// If both are queens, the first is returned. - /// - /// The pawn for whichs parent the xenotypes is looked up. - /// The Queen-Xenotype of a parent or null. If both are queens, mothers are preferred. - public static XenotypeDef TryFindParentQueenXenotype(Pawn pawn) - { - if (pawn == null) - return null; - - List parentRelations = pawn.relations.DirectRelations.FindAll(rel => rel.def.Equals(PawnRelationDefOf.Parent)); - foreach (var parent in parentRelations) - { - XenotypeDef xenotype = HiveUtility.TryGetQueenXenotype(parent.otherPawn); - if (xenotype != null) return xenotype; - } - - return null; - } - } -} diff --git a/Source/Genes/Hive/Helpers/HiveUtility.cs b/Source/Genes/Hive/Helpers/HiveUtility.cs index c7d262d..db65fb6 100644 --- a/Source/Genes/Hive/Helpers/HiveUtility.cs +++ b/Source/Genes/Hive/Helpers/HiveUtility.cs @@ -224,6 +224,5 @@ namespace RJW_Genes return offspringChanceDefs.FirstOrFallback(t => t.queenXenotype == queenDef.defName, LookupDefaultHiveInheritanceChances()); } - } } diff --git a/Source/Genes/Hive/Patches/Patch_BirthOutcome_SetHiveGenes.cs b/Source/Genes/Hive/Patches/Patch_BirthOutcome_SetHiveGenes.cs index 7bdf206..c075cc8 100644 --- a/Source/Genes/Hive/Patches/Patch_BirthOutcome_SetHiveGenes.cs +++ b/Source/Genes/Hive/Patches/Patch_BirthOutcome_SetHiveGenes.cs @@ -34,20 +34,116 @@ namespace RJW_Genes Pawn pawn = (Pawn)__result; // Important: Not all pawns have mother/father. Some Pawns are born in Growth-Vats or born from mod. - bool hasQueenParent = HiveBirthLogic.TryFindParentQueenXenotype(pawn) != null; - bool hasDroneParent = HiveBirthLogic.TryFindParentDroneXenotype(pawn) != null; + bool hasQueenParent = TryFindParentQueenXenotype(pawn) != null; + bool hasDroneParent = TryFindParentDroneXenotype(pawn) != null; if (hasQueenParent) { if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"PostFix PregnancyUtility::ApplyBirthOutcome - Checking Hive Inheritance because {pawn} has a queen parent."); - HiveBirthLogic.ManageHiveBirth(pawn, hasDroneParent); - } - else - { - if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"Ignoring Postfix PregnancyUtility::ApplyBirthOutcome - No Quene Parent - Doing Nothing"); + XenotypeDef queenDef = TryFindParentQueenXenotype(pawn); + HiveOffspringChanceDef hiveOffspringChanceDef = HiveUtility.LookupHiveInheritanceChances(queenDef); + + // Case 1: Mother is Queen, Father is something else. Produce Worker. + if (!hasDroneParent) + { + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawn} was born as a worker, as it did not have Drone Father ({100}% chance)"); + MakeWorker(pawn, queenDef); + } + // Case 2: Mother is Queen, Father is drone. Apply xenotype as per chance. + else + { + double roll = (new Random()).NextDouble(); + // Case 2.a: New Queen born + if (roll < hiveOffspringChanceDef.queenChance) + { + pawn.genes.SetXenotype(queenDef); + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawn} born as a new queen with xenotype {queenDef.defName} ({hiveOffspringChanceDef.queenChance * 100}% chance,rolled {roll})"); + // TODO: Make a letter ? + } + // Case 2.b: New Drone born + else if (roll < hiveOffspringChanceDef.droneChance + hiveOffspringChanceDef.queenChance) + { + XenotypeDef droneDef = TryFindParentDroneXenotype(pawn); + pawn.genes.SetXenotype(droneDef); + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawn} born as a new drone with xenotype {droneDef.defName} ({(hiveOffspringChanceDef.droneChance + hiveOffspringChanceDef.queenChance) * 100}% chance,rolled {roll}))"); + } + // Case 2.c: Worker + else { + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawn} born as a worker ({(hiveOffspringChanceDef.workerChance) * 100}% chance,rolled {roll}))"); + MakeWorker(pawn, queenDef); + } + } } } + /// + /// Turns a given pawn into a worker, by looking up the relevant genes as per queen. + /// + /// If the queen xenotype has no mapping, the "rjw_genes_default_worker_xenotype" are used instead. + /// The genes are added as endogenes, so the worker can still become a xenotype. + /// + /// The pawn for which the genes are added. + /// The xenotype of the queen, used for lookup. + private static void MakeWorker(Pawn pawnTobeWorker, XenotypeDef queenDef) + { + if (pawnTobeWorker == null) + return; + + var mappings = HiveUtility.GetQueenWorkerMappings(); + + var genes = mappings.TryGetValue(queenDef, HiveUtility.LookupDefaultWorkerGenes()); + + foreach (var gene in genes) + pawnTobeWorker.genes.AddGene(gene, false); + + } + + /// + /// Looks up if there is a Xenotype with Drone-Gene for the pawns parents. + /// This is to account that maybe father or mother are the drone (instead of hardcoding things for father). + /// If both are drones, the mothers is returned. + /// + /// The pawn for whichs parent the xenotypes is looked up. + /// The Drone-Xenotype of a parent or null. If both are drones, mothers are preferred. + private static XenotypeDef TryFindParentDroneXenotype(Pawn pawn) + { + if (pawn == null) + return null; + + var motherXenotype = HiveUtility.TryGetDroneXenotype(pawn.GetMother()); + var fatherXenotype = HiveUtility.TryGetDroneXenotype(pawn.GetFather()); + + if (motherXenotype != null) + return motherXenotype; + if (fatherXenotype != null) + return fatherXenotype; + + return null; + } + + + /// + /// Looks up if there is a Xenotype with Queen-Gene for the pawns parents. + /// This is to account that maybe father or mother are the queen (instead of hardcoding things for father). + /// If both are queens, the mothers is returned. + /// + /// The pawn for whichs parent the xenotypes is looked up. + /// The Queen-Xenotype of a parent or null. If both are queens, mothers are preferred. + private static XenotypeDef TryFindParentQueenXenotype(Pawn pawn) + { + if (pawn == null) + return null; + + var motherXenotype = HiveUtility.TryGetQueenXenotype(pawn.GetMother()); + var fatherXenotype = HiveUtility.TryGetQueenXenotype(pawn.GetFather()); + + if (motherXenotype != null) + return motherXenotype; + if (fatherXenotype != null) + return fatherXenotype; + + return null; + } } } diff --git a/Source/Genes/Hive/Patches/Patch_InsectEggs_BirthBaby_SetHiveGenes.cs b/Source/Genes/Hive/Patches/Patch_InsectEggs_BirthBaby_SetHiveGenes.cs index c864732..e65986e 100644 --- a/Source/Genes/Hive/Patches/Patch_InsectEggs_BirthBaby_SetHiveGenes.cs +++ b/Source/Genes/Hive/Patches/Patch_InsectEggs_BirthBaby_SetHiveGenes.cs @@ -14,7 +14,6 @@ namespace RJW_Genes /// Patches the method `ProcessHumanLikeInsectEgg` from `Hediff_InsectEgg`. /// /// The 'ProcessHumanLikeInsectEgg' returns the finished baby, for which we alter the pawn according to our xenotypes. - /// Note: This covers Insect-Egg Pregnancies only, and there is a (very similar) class `Patch_BirthOutCome_SetHiveGenes.cs` that handles normal pregnancies /// [HarmonyPatch(typeof(Hediff_InsectEgg), "ProcessHumanLikeInsectEgg")] @@ -25,29 +24,130 @@ namespace RJW_Genes [HarmonyPostfix] static void HandleHiveBasedInheritance(ref Thing __result) { - + // Check: Was the born thing a pawn? if (__result == null || !(__result is Pawn)) { - if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message("There was a birth of something non-human - not entering logic for queen-drone-xenotype inheritance."); + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message("There was a birth of something non-human - not entering logic for queen-drone-xenotype inheritance."); return; } Pawn pawn = (Pawn)__result; // Important: Not all pawns have mother/father. Some Pawns are born in Growth-Vats or born from mod. - bool hasQueenParent = HiveBirthLogic.TryFindParentQueenXenotype(pawn) != null; - bool hasDroneParent = HiveBirthLogic.TryFindParentDroneXenotype(pawn) != null; + bool hasQueenParent = TryFindParentQueenXenotype(pawn) != null; + bool hasDroneParent = TryFindParentDroneXenotype(pawn) != null; if (hasQueenParent) { - if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"PostFix Hediff_InsectEgg::ProcessHumanLikeInsectEgg - Checking Hive Inheritance because {pawn} has a queen parent."); - HiveBirthLogic.ManageHiveBirth(pawn, hasDroneParent); + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"PostFix PregnancyUtility::ApplyBirthOutcome - Checking Hive Inheritance because {pawn} has a queen parent."); + + XenotypeDef queenDef = TryFindParentQueenXenotype(pawn); + HiveOffspringChanceDef hiveOffspringChanceDef = HiveUtility.LookupHiveInheritanceChances(queenDef); + + // Case 1: Mother is Queen, Father is something else. Produce Worker. + if (!hasDroneParent) + { + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawn} was born as a worker, as it did not have Drone Father ({100}% chance)"); + MakeWorker(pawn, queenDef); + } + // Case 2: Mother is Queen, Father is drone. Apply xenotype as per chance. + else + { + double roll = (new Random()).NextDouble(); + // Case 2.a: New Queen born + if (roll < hiveOffspringChanceDef.queenChance) + { + pawn.genes.SetXenotype(queenDef); + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawn} born as a new queen with xenotype {queenDef.defName} ({hiveOffspringChanceDef.queenChance * 100}% chance,rolled {roll})"); + // TODO: Make a letter ? + } + // Case 2.b: New Drone born + else if (roll < hiveOffspringChanceDef.droneChance + hiveOffspringChanceDef.queenChance) + { + XenotypeDef droneDef = TryFindParentDroneXenotype(pawn); + pawn.genes.SetXenotype(droneDef); + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawn} born as a new drone with xenotype {droneDef.defName} ({(hiveOffspringChanceDef.droneChance + hiveOffspringChanceDef.queenChance) * 100}% chance,rolled {roll}))"); + } + // Case 2.c: Worker + else { + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawn} born as a worker ({(hiveOffspringChanceDef.workerChance) * 100}% chance,rolled {roll}))"); + MakeWorker(pawn, queenDef); + } + } } else { - if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"Ignoring Postfix Hediff_InsectEgg::ProcessHumanLikeInsectEgg - No Queen Parent - No Action."); + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message("There was an egg-birth without a (detected) queen-parent"); } } + /// + /// Turns a given pawn into a worker, by looking up the relevant genes as per queen. + /// + /// If the queen xenotype has no mapping, the "rjw_genes_default_worker_xenotype" are used instead. + /// The genes are added as endogenes, so the worker can still become a xenotype. + /// + /// The pawn for which the genes are added. + /// The xenotype of the queen, used for lookup. + private static void MakeWorker(Pawn pawnTobeWorker, XenotypeDef queenDef) + { + if (pawnTobeWorker == null) + return; + + var mappings = HiveUtility.GetQueenWorkerMappings(); + + var genes = mappings.TryGetValue(queenDef, HiveUtility.LookupDefaultWorkerGenes()); + + foreach (var gene in genes) + pawnTobeWorker.genes.AddGene(gene, false); + + } + + /// + /// Looks up if there is a Xenotype with Drone-Gene for the pawns parents. + /// This is to account that maybe father or mother are the drone (instead of hardcoding things for father). + /// If both are drones, the mothers is returned. + /// + /// The pawn for whichs parent the xenotypes is looked up. + /// The Drone-Xenotype of a parent or null. If both are drones, mothers are preferred. + private static XenotypeDef TryFindParentDroneXenotype(Pawn pawn) + { + if (pawn == null) + return null; + + var motherXenotype = HiveUtility.TryGetDroneXenotype(pawn.GetMother()); + var fatherXenotype = HiveUtility.TryGetDroneXenotype(pawn.GetFather()); + + if (motherXenotype != null) + return motherXenotype; + if (fatherXenotype != null) + return fatherXenotype; + + return null; + } + + + /// + /// Looks up if there is a Xenotype with Queen-Gene for the pawns parents. + /// This is to account that maybe father or mother are the queen (instead of hardcoding things for father). + /// If both are queens, the mothers is returned. + /// + /// The pawn for whichs parent the xenotypes is looked up. + /// The Queen-Xenotype of a parent or null. If both are queens, mothers are preferred. + private static XenotypeDef TryFindParentQueenXenotype(Pawn pawn) + { + if (pawn == null) + return null; + + var motherXenotype = HiveUtility.TryGetQueenXenotype(pawn.GetMother()); + var fatherXenotype = HiveUtility.TryGetQueenXenotype(pawn.GetFather()); + + if (motherXenotype != null) + return motherXenotype; + if (fatherXenotype != null) + return fatherXenotype; + + return null; + } } } diff --git a/Source/Rjw-Genes.csproj b/Source/Rjw-Genes.csproj index bbbe0c9..ff8360b 100644 --- a/Source/Rjw-Genes.csproj +++ b/Source/Rjw-Genes.csproj @@ -47,7 +47,6 @@ -