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;
}
}
}