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 2A: The pawn has general genetic immunity to diseases if (GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_genetic_disease_immunity)) return true; // Case 2B: The pawn has the carrier gene if (GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_disease_carrier)) 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`. /// Update v2.3.0: Returns also possible options if the Pawn is a Genetic Disease Carrier. /// /// /// List of all active Genes with the `GeneticDiseaseExtension` in pawn public static List GetGeneticDiseaseGenes(Pawn pawn) { var diseases = new List() { }; if (pawn != null && pawn.genes != null) { diseases = pawn.genes .GenesListForReading .ConvertAll(gene => gene.def) .Where(genedef => pawn.genes.HasActiveGene(genedef)) .Where(IsGeneticDiseaseGene) .ToList(); } List carrierResults = GetGeneticDiseasesGenesFromDiseaseCarrier(pawn); diseases.AddRange(carrierResults); return diseases; } public static List GetGeneticDiseasesGenesFromDiseaseCarrier(Pawn pawn) { if (pawn == null) return new List() { }; Hediff storage = null; pawn.health.hediffSet.TryGetHediff(HediffDefOf.rjw_genes_disease_carrier_storage, out storage); if (storage == null) return new List() { }; var comp = storage.TryGetComp(); if (comp == null) return new List() { }; return comp.GetStoredDiseases(); } public static List GetGeneticInfectorGenes(Pawn pawn) { if (pawn != null && pawn.genes != null) { return pawn.genes .GenesListForReading .ConvertAll(gene => gene.def) .Where(genedef => pawn.genes.HasActiveGene(genedef)) .Where(IsGeneticInfectorGene) .ToList(); } return new List() { }; } public static List LookupInfectionGeneDefs(GeneticInfectorExtension infectorExt) { if (infectorExt == null) new List(); return RimWorld.GeneUtility .GenesInOrder .Where(genedef => infectorExt.infectionGenes.Contains(genedef.defName)) .ToList(); } /// /// 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 bool IsGeneticInfectorGene(GeneDef geneDef) { if (geneDef == null) return false; GeneticInfectorExtension infectorExt = geneDef.GetModExtension(); return infectorExt != null; } /// /// Manages storing a genetic disease in a pawn. /// If the pawn is not a carrier, nothing will happen. /// /// Disease to store /// Pawn that might be a carrier. /// True if all goes well and disease is stored - false on unapplicable and errors. public static bool TryStoreGeneticDiseaseInCarrier(GeneDef disease, Pawn pawn) { if (disease == null || pawn == null) return false; if (!GeneUtility.HasGeneNullCheck(pawn, GeneDefOf.rjw_genes_disease_carrier)) return false; var store = GetOrCreateDiseaseStorageHediff(pawn).TryGetComp(); if (store == null) return false; store.StoreDisease(disease); ModLog.Debug($"DiseaseCarrier: Stored {disease} in {pawn}"); return true; } /// /// Gets (or creates) a Disease Storage Hediff for the `carrier`-pawn, /// /// /// A Cumflation Hediff of the inflated pawn. public static Hediff GetOrCreateDiseaseStorageHediff(Pawn carrier) { Hediff diseaseCarrierHediff = carrier.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.rjw_genes_disease_carrier_storage); if (diseaseCarrierHediff == null) { diseaseCarrierHediff = HediffMaker.MakeHediff(HediffDefOf.rjw_genes_disease_carrier_storage, carrier); carrier.health.AddHediff(diseaseCarrierHediff); } diseaseCarrierHediff.Severity = 1; return diseaseCarrierHediff; } public static float LookupDiseaseInfectionChance(GeneDef geneDef) { if (IsGeneticDiseaseGene(geneDef)) { GeneticDiseaseExtension diseaseExt = geneDef.GetModExtension(); return diseaseExt != null ? diseaseExt.infectionChance : 0.0f; } else return 0.0f; } } }