diff --git a/Common/Defs/GeneDefs/GeneDefs_Diseases.xml b/Common/Defs/GeneDefs/GeneDefs_Diseases.xml
index ecc3ee8..d5a8d3a 100644
--- a/Common/Defs/GeneDefs/GeneDefs_Diseases.xml
+++ b/Common/Defs/GeneDefs/GeneDefs_Diseases.xml
@@ -202,4 +202,21 @@
+
+ rjw_genes_stretcher
+
+ Pawns with this gene have a chance to make sexual partners prefer large genitalia as part of their genetics.
+ UI/Icons/ColonistBar/Idle
+ 1
+ 0
+ 12
+
+
+
+
rjw_genes_size_blinded
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Genes/Diseases/Defs/ImmunityAgainstGenesExtension.cs b/Source/Genes/Diseases/Defs/ImmunityAgainstGenesExtension.cs
new file mode 100644
index 0000000..18fe8e0
--- /dev/null
+++ b/Source/Genes/Diseases/Defs/ImmunityAgainstGenesExtension.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+
+namespace RJW_Genes
+{
+ public class ImmunityAgainstGenesExtension : DefModExtension
+ {
+ ///
+ /// A list of the exact defnames of disease-genes that this extension will make immune against.
+ /// Must perfectly match!
+ ///
+ public List givesImmunityAgainst;
+ }
+
+}
diff --git a/Source/Genes/Diseases/DiseaseHelper.cs b/Source/Genes/Diseases/DiseaseHelper.cs
new file mode 100644
index 0000000..1af745b
--- /dev/null
+++ b/Source/Genes/Diseases/DiseaseHelper.cs
@@ -0,0 +1,111 @@
+using rjw;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Verse;
+
+namespace RJW_Genes
+{
+ public static class DiseaseHelper
+ {
+
+ ///
+ /// Checks for a pawn if it is immune against a disease.
+ ///
+ /// The pawn for which immunity is checked
+ /// The genetic disease that is checked against
+ /// True if the pawn is immune, false if the pawn can be infected by it.
+ public static bool IsImmuneAgainstGeneticDisease(Pawn pawn, GeneDef disease)
+ {
+ // Case 1: Something is null / not working, return Immune (to have less follow up effects)
+ if (pawn == null || pawn.genes == null) return true;
+ if (disease == null) return true;
+ // Case 1.B: Dead people can spread, but not receive, diseases.
+ if (pawn.Dead) return true;
+
+ // Case 2: The pawn has general genetic immunity to diseases
+ if (GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_genetic_disease_immunity))
+ return true;
+
+ // Case 3: The pawn already has the genetic disease
+ if (GeneUtility.HasGeneNullCheck(pawn, disease))
+ return true;
+
+ // Case 4: Check all genes if one of them has the Immunity Extension that covers the GeneDef
+ List genes = pawn.genes.GenesListForReading;
+ genes = genes.Where(x => pawn.genes.HasActiveGene(x.def)).ToList();
+
+ foreach (Gene gene in genes)
+ {
+ ImmunityAgainstGenesExtension ext = gene.def.GetModExtension();
+ if (ext != null) {
+ foreach (string defname in ext.givesImmunityAgainst)
+ if (disease.defName == defname)
+ return true;
+ }
+ }
+
+ // Case 5: Nothing special happens, so return false (not immune)
+ return false;
+ }
+
+ ///
+ /// Returns all active Genes with the `GeneticDiseaseExtension`.
+ ///
+ ///
+ /// List of all active Genes with the `GeneticDiseaseExtension` in pawn
+ public static List GetGeneticDiseaseGenes(Pawn pawn)
+ {
+ if (pawn != null && pawn.genes != null)
+ {
+ return pawn.genes
+ .GenesListForReading
+ .ConvertAll(gene => gene.def)
+ .Where(genedef => pawn.genes.HasActiveGene(genedef))
+ .Where(IsGeneticDiseaseGene)
+ .ToList();
+ }
+
+ return new List() { };
+ }
+
+ ///
+ /// Checks if the performed sex was penetrative.
+ /// Condom check is not done here!
+ ///
+ /// The sexprops
+ ///
+ public static bool IsPenetrativeSex(SexProps props)
+ {
+ if (props == null) return false;
+
+ return props.sexType ==
+ xxx.rjwSextype.Vaginal
+ || props.sexType == xxx.rjwSextype.Anal
+ || props.sexType == xxx.rjwSextype.Oral
+ || props.sexType == xxx.rjwSextype.DoublePenetration
+ || props.sexType == xxx.rjwSextype.Fellatio
+ || props.sexType == xxx.rjwSextype.Sixtynine;
+ }
+
+ public static bool IsGeneticDiseaseGene(GeneDef geneDef)
+ {
+ if (geneDef == null) return false;
+ GeneticDiseaseExtension diseaseExt = geneDef.GetModExtension();
+ return diseaseExt != null;
+ }
+
+ public static float LookupDiseaseInfectionChance(GeneDef geneDef)
+ {
+ if (IsGeneticDiseaseGene(geneDef))
+ {
+ GeneticDiseaseExtension diseaseExt = geneDef.GetModExtension();
+ return diseaseExt != null ? diseaseExt.infectionChance : 0.0f;
+ }
+ else
+ return 0.0f;
+ }
+ }
+}
diff --git a/Source/Genes/Diseases/Patches/Patch_AftersexUtility_TransferGeneticDiseases.cs b/Source/Genes/Diseases/Patches/Patch_AftersexUtility_TransferGeneticDiseases.cs
index 6bf8e88..b068c38 100644
--- a/Source/Genes/Diseases/Patches/Patch_AftersexUtility_TransferGeneticDiseases.cs
+++ b/Source/Genes/Diseases/Patches/Patch_AftersexUtility_TransferGeneticDiseases.cs
@@ -29,7 +29,7 @@ namespace RJW_Genes.Genes.Diseases.Patches
if (props.usedCondom) return;
// Exit early if settings require penetrative sex, but this is not penetrative sex
- if (!IsPenetrativeSex(props) && RJW_Genes_Settings.rjw_genes_genetic_disease_spread_only_on_penetrative_sex) return;
+ if (!DiseaseHelper.IsPenetrativeSex(props) && RJW_Genes_Settings.rjw_genes_genetic_disease_spread_only_on_penetrative_sex) return;
ModLog.Debug($"Firing Patch_TransferGeneticDiseases for {pawn} and {partner}");
TryTransferGeneticDiseases(pawn, partner, props);
@@ -38,74 +38,19 @@ namespace RJW_Genes.Genes.Diseases.Patches
private static void TryTransferGeneticDiseases(Pawn infector, Pawn infected, SexProps props)
{
- if (infected.genes.HasActiveGene(GeneDefOf.rjw_genes_genetic_disease_immunity))
- {
- ModLog.Debug($"{infected} is immune to genetic diseases");
- return;
- }
- if (infected.Dead)
- {
- // Dead people can spread, but not receive, diseases.
- return;
- }
-
- foreach (GeneDef disease in GetGeneticDiseaseGenes(infector)) {
+
+ foreach (GeneDef disease in DiseaseHelper.GetGeneticDiseaseGenes(infector)) {
ModLog.Debug($"Found genetic disease {disease} in {infector}, trying to infect {infected}");
- if (infected.genes.HasActiveGene(disease))
+ if (DiseaseHelper.IsImmuneAgainstGeneticDisease(infected,disease))
continue;
- if ((new Random()).NextDouble() <= LookupDiseaseInfectionChance(disease))
+ if ((new Random()).NextDouble() <= DiseaseHelper.LookupDiseaseInfectionChance(disease))
{
infected.genes.AddGene(disease, !RJW_Genes_Settings.rjw_genes_genetic_disease_as_endogenes);
}
}
}
- private static List GetGeneticDiseaseGenes(Pawn pawn)
- {
- if (pawn != null && pawn.genes != null)
- {
- return pawn.genes
- .GenesListForReading
- .ConvertAll(gene => gene.def)
- .Where(genedef => pawn.genes.HasActiveGene(genedef))
- .Where(IsGeneticDiseaseGene)
- .ToList();
- }
-
- return new List() { };
- }
-
- private static bool IsPenetrativeSex(SexProps props)
- {
- if (props == null) return false;
-
- return props.sexType ==
- xxx.rjwSextype.Vaginal
- || props.sexType == xxx.rjwSextype.Anal
- || props.sexType == xxx.rjwSextype.Oral
- || props.sexType == xxx.rjwSextype.DoublePenetration
- || props.sexType == xxx.rjwSextype.Fellatio
- || props.sexType == xxx.rjwSextype.Sixtynine;
- }
-
- private static bool IsGeneticDiseaseGene(GeneDef geneDef)
- {
- if (geneDef == null) return false;
- GeneticDiseaseExtension diseaseExt = geneDef.GetModExtension();
- return diseaseExt != null;
- }
-
- private static float LookupDiseaseInfectionChance(GeneDef geneDef)
- {
- if (IsGeneticDiseaseGene(geneDef))
- {
- GeneticDiseaseExtension diseaseExt = geneDef.GetModExtension();
- return diseaseExt != null ? diseaseExt.infectionChance : 0.0f;
- }
- else
- return 0.0f;
- }
}
}
diff --git a/Source/Rjw-Genes.csproj b/Source/Rjw-Genes.csproj
index 51b80a1..bd03e87 100644
--- a/Source/Rjw-Genes.csproj
+++ b/Source/Rjw-Genes.csproj
@@ -76,6 +76,8 @@
+
+