Custom Xenotypes should work now with Hivelogic

This commit is contained in:
Vegapnk 2023-07-26 17:06:17 +02:00
parent 57bb1950e4
commit 0aefb45d9b
7 changed files with 171 additions and 42 deletions

View file

@ -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.

28
Source/Common/Either.cs Normal file
View file

@ -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<TL, TR>
{
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;
}
}
}

View file

@ -30,9 +30,9 @@ namespace RJW_Genes
/// </summary>
/// <param name="pawn">The pawn born, that maybe becomes a hive-xenotype.</param>
/// <param name="hasDroneParent">whether there was a drone parent involved</param>
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<XenotypeDef, CustomXenotype> fallbackQueenDef = null, Either<XenotypeDef, CustomXenotype> fallbackDroneDef = null)
{
XenotypeDef queenDef = TryFindParentQueenXenotype(pawn);
Either<XenotypeDef,CustomXenotype> 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<XenotypeDef,CustomXenotype> 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<XenotypeDef, CustomXenotype> 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}");
}
}
/// <summary>
/// Turns a given pawn into a worker, by looking up the relevant genes as per queen.
@ -79,14 +123,19 @@ namespace RJW_Genes
/// </summary>
/// <param name="pawnTobeWorker">The pawn for which the genes are added.</param>
/// <param name="queenDef">The xenotype of the queen, used for lookup.</param>
private static void MakeWorker(Pawn pawnTobeWorker, XenotypeDef queenDef)
private static void MakeWorker(Pawn pawnTobeWorker, Either<XenotypeDef, CustomXenotype> 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
/// </summary>
/// <param name="pawn">The pawn for whichs parent the xenotypes is looked up.</param>
/// <returns>The Drone-Xenotype of a parent or null. If both are drones, mothers are preferred.</returns>
public static XenotypeDef TryFindParentDroneXenotype(Pawn pawn)
public static Either<XenotypeDef,CustomXenotype> TryFindParentDroneXenotype(Pawn pawn)
{
if (pawn == null)
return null;
@ -109,7 +158,7 @@ namespace RJW_Genes
List<DirectPawnRelation> 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
/// </summary>
/// <param name="pawn">The pawn for whichs parent the xenotypes is looked up.</param>
/// <returns>The Queen-Xenotype of a parent or null. If both are queens, mothers are preferred.</returns>
public static XenotypeDef TryFindParentQueenXenotype(Pawn pawn)
public static Either<XenotypeDef,CustomXenotype> TryFindParentQueenXenotype(Pawn pawn)
{
if (pawn == null)
return null;
@ -142,7 +190,7 @@ namespace RJW_Genes
List<DirectPawnRelation> 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;
}

View file

@ -74,7 +74,7 @@ namespace RJW_Genes
/// </summary>
/// <param name="pawn"></param>
/// <returns>A xenotype with a queen gene, or null.</returns>
public static XenotypeDef TryGetQueenXenotype(Pawn pawn)
public static Either<XenotypeDef,CustomXenotype> 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<XenotypeDef,CustomXenotype>(potentialXenotype);
}
var potentialCustomXenotype = pawn.genes.CustomXenotype;
if (potentialCustomXenotype != null && potentialCustomXenotype.genes.Contains(GeneDefOf.rjw_genes_queen))
{
return new Either<XenotypeDef, CustomXenotype>(potentialCustomXenotype);
}
}
return null;
@ -98,7 +105,7 @@ namespace RJW_Genes
/// </summary>
/// <param name="pawn"></param>
/// <returns>A xenotype with a drone gene, or null.</returns>
public static XenotypeDef TryGetDroneXenotype(Pawn pawn)
public static Either<XenotypeDef,CustomXenotype> 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<XenotypeDef,CustomXenotype>(potentialXenotype);
}
var potentialCustomXenotype = pawn.genes.CustomXenotype;
if (potentialCustomXenotype != null && potentialCustomXenotype.genes.Contains(GeneDefOf.rjw_genes_drone))
{
return new Either<XenotypeDef, CustomXenotype>(potentialCustomXenotype);
}
}
@ -122,23 +135,35 @@ namespace RJW_Genes
/// Prints a bigger piece of information when debug printing is enabled.
/// </summary>
/// <returns>A mapping which Queen-Xenotypes should produce which worker genes.</returns>
public static Dictionary<XenotypeDef,List<GeneDef>> GetQueenWorkerMappings()
public static Dictionary<String,List<GeneDef>> GetQueenWorkerMappings()
{
Dictionary<XenotypeDef,List<GeneDef>> dict = new Dictionary<XenotypeDef, List<GeneDef>>();
IEnumerable<QueenWorkerMappingDef> mappingDefs = DefDatabase<QueenWorkerMappingDef>.AllDefs;
Dictionary<string, List<GeneDef>> results = new Dictionary<string, List<GeneDef>>();
// 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<XenotypeDef>.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<GeneDef> workerGenes = new List<GeneDef>();
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;
}
/// <summary>
@ -203,6 +230,16 @@ namespace RJW_Genes
}
public static String GetXenotypeDefName(Either<XenotypeDef, CustomXenotype> def)
{
if (def == null)
return null;
else if (def.isLeft)
return def.left.defName;
else
return def.right.name;
}
public static HiveOffspringChanceDef LookupDefaultHiveInheritanceChances()
{
IEnumerable<HiveOffspringChanceDef> offspringChanceDefs = DefDatabase<HiveOffspringChanceDef>.AllDefs;
@ -217,11 +254,16 @@ namespace RJW_Genes
return defaultChance;
}
public static HiveOffspringChanceDef LookupHiveInheritanceChances(XenotypeDef queenDef)
public static HiveOffspringChanceDef LookupHiveInheritanceChances(Either<XenotypeDef, CustomXenotype> queenDef)
{
if (queenDef == null)
return LookupDefaultHiveInheritanceChances();
String queenDefName = queenDef.isLeft ? queenDef.left.defName : queenDef.right.name;
IEnumerable<HiveOffspringChanceDef> offspringChanceDefs = DefDatabase<HiveOffspringChanceDef>.AllDefs;
return offspringChanceDefs.FirstOrFallback(t => t.queenXenotype == queenDef.defName, LookupDefaultHiveInheritanceChances());
return offspringChanceDefs.FirstOrFallback(t => t.queenXenotype == queenDefName, LookupDefaultHiveInheritanceChances());
}

View file

@ -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<XenotypeDef,CustomXenotype> queenDef = HiveBirthLogic.TryFindParentQueenXenotype(pawn) ?? TryFindParentQueenXenotypeFromEgg(__instance);
Either<XenotypeDef, CustomXenotype> 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
/// </summary>
/// <param name="egg">An Egg for which queens are looked up for</param>
/// <returns>The relevant xenotypedef of a queen, or null.</returns>
public static XenotypeDef TryFindParentQueenXenotypeFromEgg(Hediff_InsectEgg egg)
public static Either<XenotypeDef, CustomXenotype> TryFindParentQueenXenotypeFromEgg(Hediff_InsectEgg egg)
{
XenotypeDef queenDef = null;
Either<XenotypeDef, CustomXenotype> queenDef = null;
if (egg == null)
return null;
@ -85,9 +94,9 @@ namespace RJW_Genes
/// </summary>
/// <param name="egg">An Egg for which drones are looked up for</param>
/// <returns>The relevant xenotypedef of a drone, or null.</returns>
public static XenotypeDef TryFindParentDroneXenotypeFromEgg(Hediff_InsectEgg egg)
public static Either<XenotypeDef, CustomXenotype> TryFindParentDroneXenotypeFromEgg(Hediff_InsectEgg egg)
{
XenotypeDef droneDef = null;
Either<XenotypeDef, CustomXenotype> droneDef = null;
if (egg == null)
return null;

View file

@ -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<HiveOffspringChanceDef> offspringChanceDefs = DefDatabase<HiveOffspringChanceDef>.AllDefs;
IEnumerable<HiveOffspringChanceDef> 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))})");

View file

@ -41,6 +41,7 @@
<Compile Include="Animal_Inheritance\Defs\BestialityGeneInheritanceDef.cs" />
<Compile Include="Common\Defs\DistanceExtension.cs" />
<Compile Include="Common\Defs\ModExtensionHelper.cs" />
<Compile Include="Common\Either.cs" />
<Compile Include="Common\ModLog.cs" />
<Compile Include="Common\Defs\TickIntervalExtension.cs" />
<Compile Include="GeneDefOf.cs" />