From 0aefb45d9bc581041e19378c02d15abcd654b8e8 Mon Sep 17 00:00:00 2001 From: Vegapnk Date: Wed, 26 Jul 2023 17:06:17 +0200 Subject: [PATCH] Custom Xenotypes should work now with Hivelogic --- CHANGELOG.md | 1 + Source/Common/Either.cs | 28 +++++++ Source/Genes/Hive/Helpers/HiveBirthLogic.cs | 82 +++++++++++++++---- Source/Genes/Hive/Helpers/HiveUtility.cs | 74 +++++++++++++---- ...Patch_InsectEggs_BirthBaby_SetHiveGenes.cs | 21 +++-- Source/RJW_Genes.cs | 6 +- Source/Rjw-Genes.csproj | 1 + 7 files changed, 171 insertions(+), 42 deletions(-) create mode 100644 Source/Common/Either.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b35dd8..7f581d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - New attempt at fixing condom consumption for Fertilin, adressing #41 & #48 provided by Infi - Copy of Infis patch for eating cum from sexperience, #41 and #48 - Updated some Icons to have better backgrounds (thanks @WasmachenDennSachenSo #53) +- Custom Queen- and Drone-Xenotypes should work now. *Notes*: The pawns that are gender fluid can get pregnant. diff --git a/Source/Common/Either.cs b/Source/Common/Either.cs new file mode 100644 index 0000000..dcd6dd8 --- /dev/null +++ b/Source/Common/Either.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RJW_Genes +{ + public class Either + { + public readonly TL left; + public readonly TR right; + public readonly bool isLeft; + + public Either(TL left) + { + this.left = left; + this.isLeft = true; + } + + public Either(TR right) + { + this.right = right; + this.isLeft = false; + } + } + +} diff --git a/Source/Genes/Hive/Helpers/HiveBirthLogic.cs b/Source/Genes/Hive/Helpers/HiveBirthLogic.cs index 8bb1600..9dabac2 100644 --- a/Source/Genes/Hive/Helpers/HiveBirthLogic.cs +++ b/Source/Genes/Hive/Helpers/HiveBirthLogic.cs @@ -30,9 +30,9 @@ namespace RJW_Genes /// /// 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 fallbackQueenDef = null, XenotypeDef fallbackDroneDef = null) + public static void ManageHiveBirth(Pawn pawn, bool hasDroneParent = false, Either fallbackQueenDef = null, Either fallbackDroneDef = null) { - XenotypeDef queenDef = TryFindParentQueenXenotype(pawn); + Either queenDef = TryFindParentQueenXenotype(pawn); if (queenDef == null) queenDef = fallbackQueenDef; HiveOffspringChanceDef hiveOffspringChanceDef = HiveUtility.LookupHiveInheritanceChances(queenDef); @@ -49,17 +49,15 @@ namespace RJW_Genes // 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})"); - MakeQueenBornLetter(pawn); + MakeQueen(pawn, queenDef); + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"Queen Chance: {hiveOffspringChanceDef.queenChance * 100}% chance,rolled { roll}"); } // Case 2.b: New Drone born else if (roll < hiveOffspringChanceDef.droneChance + hiveOffspringChanceDef.queenChance) { - XenotypeDef droneDef = TryFindParentDroneXenotype(pawn); - if (droneDef == null) droneDef = fallbackDroneDef; - 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}))"); + var droneDef = TryFindParentDroneXenotype(pawn); + MakeDrone(pawn,droneDef); + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"Drone Chance ({(hiveOffspringChanceDef.droneChance + hiveOffspringChanceDef.queenChance) * 100}% chance,rolled {roll}))"); } // Case 2.c: Worker else @@ -70,6 +68,52 @@ namespace RJW_Genes } } + private static void MakeQueen(Pawn pawnToBeQueen, Either queenDef) { + if (queenDef == null && pawnToBeQueen == null) + return; + if (queenDef.isLeft) { + var xenotype = queenDef.left; + pawnToBeQueen.genes.SetXenotype(xenotype); + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawnToBeQueen} born as a new queen with Xenotype {xenotype.defName}"); + } else { + var customXenotype = queenDef.right; + + foreach (var gene in customXenotype.genes) + pawnToBeQueen.genes.AddGene(gene, true); + + pawnToBeQueen.genes.xenotypeName = customXenotype.name; + pawnToBeQueen.genes.iconDef = customXenotype.iconDef; + + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawnToBeQueen} born as a new queen with custom Xenotype {customXenotype.name}"); + } + + MakeQueenBornLetter(pawnToBeQueen); + } + + + private static void MakeDrone(Pawn pawnToBeDrone, Either droneDef) + { + if (droneDef == null && pawnToBeDrone == null) + return; + if (droneDef.isLeft) + { + var xenotype = droneDef.left; + pawnToBeDrone.genes.SetXenotype(xenotype); + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawnToBeDrone} born as a new drone with Xenotype {xenotype.defName}"); + } + else + { + var customXenotype = droneDef.right; + + foreach (var gene in customXenotype.genes) + pawnToBeDrone.genes.AddGene(gene, true); + + pawnToBeDrone.genes.xenotypeName = customXenotype.name; + pawnToBeDrone.genes.iconDef = customXenotype.iconDef; + + if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"{pawnToBeDrone} born as a new drone with custom Xenotype {customXenotype.name}"); + } + } /// /// Turns a given pawn into a worker, by looking up the relevant genes as per queen. @@ -79,14 +123,19 @@ namespace RJW_Genes /// /// The pawn for which the genes are added. /// The xenotype of the queen, used for lookup. - private static void MakeWorker(Pawn pawnTobeWorker, XenotypeDef queenDef) + private static void MakeWorker(Pawn pawnTobeWorker, Either queenDef) { if (pawnTobeWorker == null) return; var mappings = HiveUtility.GetQueenWorkerMappings(); + String queenDefName = HiveUtility.GetXenotypeDefName(queenDef); + if (queenDef == null || mappings.NullOrEmpty()) + return; - var genes = mappings.TryGetValue(queenDef, HiveUtility.LookupDefaultWorkerGenes()); + var genes = mappings.TryGetValue(queenDefName, HiveUtility.LookupDefaultWorkerGenes()); + if (genes == null) + return; foreach (var gene in genes) pawnTobeWorker.genes.AddGene(gene, false); @@ -101,7 +150,7 @@ namespace RJW_Genes /// /// 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) + public static Either TryFindParentDroneXenotype(Pawn pawn) { if (pawn == null) return null; @@ -109,7 +158,7 @@ namespace RJW_Genes List parentRelations = pawn.relations.DirectRelations.FindAll(rel => rel.def.Equals(PawnRelationDefOf.Parent)); foreach (DirectPawnRelation parent in parentRelations) { - XenotypeDef xenotype = HiveUtility.TryGetDroneXenotype(parent.otherPawn); + var xenotype = HiveUtility.TryGetDroneXenotype(parent.otherPawn); if (xenotype != null) return xenotype; } @@ -121,9 +170,8 @@ namespace RJW_Genes if (bornQueen == null) return; var letter= LetterMaker.MakeLetter( - "New Queen", "A new Queen was born! Make sure to adress inheritance before the new queen reaches adolesence.", LetterDefOf.NeutralEvent, bornQueen + "New Queen", "A new Queen was born! Make sure to adress succession before the new queen reaches adolesence.", LetterDefOf.NeutralEvent, bornQueen ); - //letter.Start(); Find.LetterStack.ReceiveLetter(letter); } @@ -134,7 +182,7 @@ namespace RJW_Genes /// /// 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) + public static Either TryFindParentQueenXenotype(Pawn pawn) { if (pawn == null) return null; @@ -142,7 +190,7 @@ namespace RJW_Genes List parentRelations = pawn.relations.DirectRelations.FindAll(rel => rel.def.Equals(PawnRelationDefOf.Parent)); foreach (var parent in parentRelations) { - XenotypeDef xenotype = HiveUtility.TryGetQueenXenotype(parent.otherPawn); + var xenotype = HiveUtility.TryGetQueenXenotype(parent.otherPawn); if (xenotype != null) return xenotype; } diff --git a/Source/Genes/Hive/Helpers/HiveUtility.cs b/Source/Genes/Hive/Helpers/HiveUtility.cs index c7d262d..03bdf34 100644 --- a/Source/Genes/Hive/Helpers/HiveUtility.cs +++ b/Source/Genes/Hive/Helpers/HiveUtility.cs @@ -74,7 +74,7 @@ namespace RJW_Genes /// /// /// A xenotype with a queen gene, or null. - public static XenotypeDef TryGetQueenXenotype(Pawn pawn) + public static Either TryGetQueenXenotype(Pawn pawn) { if (pawn == null) return null; @@ -84,8 +84,15 @@ namespace RJW_Genes var potentialXenotype = pawn.genes.Xenotype; if (potentialXenotype != null && potentialXenotype.genes.Contains(GeneDefOf.rjw_genes_queen)) { - return potentialXenotype; + return new Either(potentialXenotype); } + + var potentialCustomXenotype = pawn.genes.CustomXenotype; + if (potentialCustomXenotype != null && potentialCustomXenotype.genes.Contains(GeneDefOf.rjw_genes_queen)) + { + return new Either(potentialCustomXenotype); + } + } return null; @@ -98,7 +105,7 @@ namespace RJW_Genes /// /// /// A xenotype with a drone gene, or null. - public static XenotypeDef TryGetDroneXenotype(Pawn pawn) + public static Either TryGetDroneXenotype(Pawn pawn) { if (pawn == null) return null; @@ -108,7 +115,13 @@ namespace RJW_Genes var potentialXenotype = pawn.genes.Xenotype; if (potentialXenotype != null && potentialXenotype.genes.Contains(GeneDefOf.rjw_genes_drone)) { - return potentialXenotype; + return new Either(potentialXenotype); + } + + var potentialCustomXenotype = pawn.genes.CustomXenotype; + if (potentialCustomXenotype != null && potentialCustomXenotype.genes.Contains(GeneDefOf.rjw_genes_drone)) + { + return new Either(potentialCustomXenotype); } } @@ -122,23 +135,35 @@ namespace RJW_Genes /// Prints a bigger piece of information when debug printing is enabled. /// /// A mapping which Queen-Xenotypes should produce which worker genes. - - public static Dictionary> GetQueenWorkerMappings() + public static Dictionary> GetQueenWorkerMappings() { - Dictionary> dict = new Dictionary>(); IEnumerable mappingDefs = DefDatabase.AllDefs; + Dictionary> results = new Dictionary>(); + // Dev-Note: I first a nice lambda here, but I used nesting in favour of logging. foreach (QueenWorkerMappingDef mappingDef in mappingDefs) { - + // Option A) This is the default worker genes, expected, just ignore. if (mappingDef.defName == "rjw_genes_default_worker_genes") { // Do nothing, there is no lookup but this entry is fine and should not log a warning. continue; } + // Option B) The Xenotype is a "static" Xenotype, from a mod or something. XenotypeDef queenDef = DefDatabase.GetNamed(mappingDef.queenXenotype); + string defName = null; if (queenDef != null) + { + defName = queenDef.defName; + } + else if (Current.Game != null && Current.Game.customXenotypeDatabase != null) + { + // Option C) The Xenotype is a Custom Xenotype, created by the player + CustomXenotype customQueenDef = Current.Game.customXenotypeDatabase.customXenotypes.Find(f => f.name == mappingDef.defName); + defName = customQueenDef?.name; + } + if (defName != null) { List workerGenes = new List(); foreach (string geneName in mappingDef.workerGenes) @@ -149,15 +174,17 @@ namespace RJW_Genes else if(RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Warning($"Could not look up Gene {geneName} for {mappingDef.queenXenotype}."); } - dict.Add(queenDef, workerGenes); - } - else { - if (RJW_Genes_Settings.rjw_genes_detailed_debug) - ModLog.Warning($"Did not find a matching xenotype for {mappingDef.queenXenotype}! Defaulting to rjw_genes_default_worker_genes."); + results.Add(defName, workerGenes); + continue; } + + // Option D) Fallback, unknown + if (RJW_Genes_Settings.rjw_genes_detailed_debug) + ModLog.Warning($"Did not find a matching xenotype for {mappingDef.queenXenotype}! Defaulting to rjw_genes_default_worker_genes."); + } - return dict; + return results; } /// @@ -203,6 +230,16 @@ namespace RJW_Genes } + public static String GetXenotypeDefName(Either def) + { + if (def == null) + return null; + else if (def.isLeft) + return def.left.defName; + else + return def.right.name; + } + public static HiveOffspringChanceDef LookupDefaultHiveInheritanceChances() { IEnumerable offspringChanceDefs = DefDatabase.AllDefs; @@ -217,11 +254,16 @@ namespace RJW_Genes return defaultChance; } - public static HiveOffspringChanceDef LookupHiveInheritanceChances(XenotypeDef queenDef) + public static HiveOffspringChanceDef LookupHiveInheritanceChances(Either queenDef) { + if (queenDef == null) + return LookupDefaultHiveInheritanceChances(); + + String queenDefName = queenDef.isLeft ? queenDef.left.defName : queenDef.right.name; + IEnumerable offspringChanceDefs = DefDatabase.AllDefs; - return offspringChanceDefs.FirstOrFallback(t => t.queenXenotype == queenDef.defName, LookupDefaultHiveInheritanceChances()); + return offspringChanceDefs.FirstOrFallback(t => t.queenXenotype == queenDefName, LookupDefaultHiveInheritanceChances()); } diff --git a/Source/Genes/Hive/Patches/Patch_InsectEggs_BirthBaby_SetHiveGenes.cs b/Source/Genes/Hive/Patches/Patch_InsectEggs_BirthBaby_SetHiveGenes.cs index fe9155e..5c5e98d 100644 --- a/Source/Genes/Hive/Patches/Patch_InsectEggs_BirthBaby_SetHiveGenes.cs +++ b/Source/Genes/Hive/Patches/Patch_InsectEggs_BirthBaby_SetHiveGenes.cs @@ -34,8 +34,8 @@ namespace RJW_Genes Pawn pawn = (Pawn)__result; - XenotypeDef queenDef = HiveBirthLogic.TryFindParentQueenXenotype(pawn) ?? TryFindParentQueenXenotypeFromEgg(__instance); - XenotypeDef droneDef = HiveBirthLogic.TryFindParentDroneXenotype(pawn) ?? TryFindParentDroneXenotypeFromEgg(__instance); + Either queenDef = HiveBirthLogic.TryFindParentQueenXenotype(pawn) ?? TryFindParentQueenXenotypeFromEgg(__instance); + Either droneDef = HiveBirthLogic.TryFindParentDroneXenotype(pawn) ?? TryFindParentDroneXenotypeFromEgg(__instance); bool hasQueenParent = queenDef != null; bool hasDroneParent = droneDef != null; @@ -47,6 +47,15 @@ namespace RJW_Genes } else { if (RJW_Genes_Settings.rjw_genes_detailed_debug) ModLog.Message($"Ignoring Postfix Hediff_InsectEgg::ProcessHumanLikeInsectEgg - No Queen Parent - No Action."); + + // Extra Debug for #56 + if (RJW_Genes_Settings.rjw_genes_detailed_debug) + { + ModLog.Message($"Implanter was: ({__instance.implanter.genes.xenotypeName}|{__instance.implanter.genes.Xenotype}), Fertilizer was: ({__instance.father.genes.xenotypeName}|{__instance.father.genes.Xenotype})"); + ModLog.Message($"Implanter Xenotype From helper: {HiveUtility.TryGetQueenXenotype(__instance.implanter)} and has Queen {__instance.implanter.genes.HasGene(GeneDefOf.rjw_genes_queen)}"); + ModLog.Message($"Father Xenotype From helper: {HiveUtility.TryGetDroneXenotype(__instance.implanter)} and has Drone {__instance.father.genes.HasGene(GeneDefOf.rjw_genes_drone)}"); + CustomXenotype custom = __instance.implanter.genes.CustomXenotype; + } } } @@ -59,9 +68,9 @@ namespace RJW_Genes /// /// An Egg for which queens are looked up for /// The relevant xenotypedef of a queen, or null. - public static XenotypeDef TryFindParentQueenXenotypeFromEgg(Hediff_InsectEgg egg) + public static Either TryFindParentQueenXenotypeFromEgg(Hediff_InsectEgg egg) { - XenotypeDef queenDef = null; + Either queenDef = null; if (egg == null) return null; @@ -85,9 +94,9 @@ namespace RJW_Genes /// /// An Egg for which drones are looked up for /// The relevant xenotypedef of a drone, or null. - public static XenotypeDef TryFindParentDroneXenotypeFromEgg(Hediff_InsectEgg egg) + public static Either TryFindParentDroneXenotypeFromEgg(Hediff_InsectEgg egg) { - XenotypeDef droneDef = null; + Either droneDef = null; if (egg == null) return null; diff --git a/Source/RJW_Genes.cs b/Source/RJW_Genes.cs index db4ffbf..44cf60d 100644 --- a/Source/RJW_Genes.cs +++ b/Source/RJW_Genes.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Verse; @@ -14,9 +15,8 @@ namespace RJW_Genes { ModLog.Message($"{HiveUtility.getQueenXenotypes().EnumerableCount()} Queen-Xenotypes ({string.Join(",", HiveUtility.getQueenXenotypes().Select(t => t.defName))})"); ModLog.Message($"{HiveUtility.getDroneXenotypes().EnumerableCount()} Drone-Xenotypes ({string.Join(",", HiveUtility.getDroneXenotypes().Select(t => t.defName))})"); - ModLog.Message($"Found {HiveUtility.GetQueenWorkerMappings().Count} Queen-Worker Mappings ({string.Join(",", HiveUtility.GetQueenWorkerMappings().Keys.Select(t => t.defName))} + Default) "); - + ModLog.Message($"Found {HiveUtility.GetQueenWorkerMappings().Count} Queen-Worker Mappings ({string.Join(",", HiveUtility.GetQueenWorkerMappings().Keys.Select(t => t))} + Default) "); IEnumerable offspringChanceDefs = DefDatabase.AllDefs; IEnumerable faultOffspringDefs = offspringChanceDefs.Where(t => t.queenChance + t.workerChance + t.workerChance > 1.02 || t.queenChance + t.workerChance + t.workerChance < 0.98 ); ModLog.Message($"Found {offspringChanceDefs.Count()} OffspringChanceDefs, of which {faultOffspringDefs.Count()} had faulty chances ({string.Join(",", faultOffspringDefs.Select(t => t.defName))})"); diff --git a/Source/Rjw-Genes.csproj b/Source/Rjw-Genes.csproj index e975194..ec83cd3 100644 --- a/Source/Rjw-Genes.csproj +++ b/Source/Rjw-Genes.csproj @@ -41,6 +41,7 @@ +