public override float CalculateCapacityLevel(HediffSet diffSet, List <PawnCapacityUtility.CapacityImpactor> impactors = null) { Pawn pawn = diffSet.pawn; if (!Genital_Helper.has_penis(pawn) && !Genital_Helper.has_vagina(pawn)) { return(0); } if (Genital_Helper.has_ovipositorF(pawn) || Genital_Helper.has_ovipositorM(pawn)) { return(0); } //Log.Message("[RJW]PawnCapacityWorker_Fertility::CalculateCapacityLevel is called for: " + xxx.get_pawnname(pawn)); RaceProperties race = diffSet.pawn.RaceProps; if (!pawn.RaceHasFertility()) { //Log.Message(" Fertility_filter, no fertility for : " + pawn.kindDef.defName); return(0f); } //androids only fertile with archotech parts if (AndroidsCompatibility.IsAndroid(pawn) && !(AndroidsCompatibility.AndroidPenisFertility(pawn) || AndroidsCompatibility.AndroidVaginaFertility(pawn))) { //Log.Message(" Android has no archotech genitals set fertility to 0 for: " + pawn.kindDef.defName); return(0f); } //archotech always fertile mode if (pawn.health.hediffSet.HasHediff(HediffDef.Named("FertilityEnhancer"))) { //Log.Message(" has archotech FertilityEnhancer set fertility to 100%"); return(1f); } float startAge = 0f; //raise fertility float startMaxAge = 0f; //max fertility float endAge = race.lifeExpectancy * (RJWPregnancySettings.fertility_endage_male * 0.7f); // Age when males start to lose potency. float zeroFertility = race.lifeExpectancy * RJWPregnancySettings.fertility_endage_male; // Age when fertility hits 0%. if (xxx.is_female(pawn)) { if (xxx.is_animal(pawn)) { endAge = race.lifeExpectancy * (RJWPregnancySettings.fertility_endage_female_animal * 0.6f); zeroFertility = race.lifeExpectancy * RJWPregnancySettings.fertility_endage_female_animal; } else { endAge = race.lifeExpectancy * (RJWPregnancySettings.fertility_endage_female_humanlike * 0.6f); // Age when fertility begins to drop. zeroFertility = race.lifeExpectancy * RJWPregnancySettings.fertility_endage_female_humanlike; // Age when fertility hits 0%. } } foreach (LifeStageAge lifestage in race.lifeStageAges) { if (lifestage.def.reproductive) { //presumably teen stage if (startAge == 0f && startMaxAge == 0f) { startAge = lifestage.minAge; startMaxAge = (Mathf.Max(startAge + (startAge + endAge) * 0.08f, startAge)); } //presumably adult stage else { if (startMaxAge > lifestage.minAge) { startMaxAge = lifestage.minAge; } } } } //Log.Message(" Fertility ages for " + pawn.Name + " are: " + startAge + ", " + startMaxAge + ", " + endAge + ", " + endMaxAge); float result = PawnCapacityUtility.CalculateTagEfficiency(diffSet, BodyPartTagDefOf.RJW_FertilitySource, 1f, FloatRange.ZeroToOne, impactors); result *= GenMath.FlatHill(startAge, startMaxAge, endAge, zeroFertility, pawn.ageTracker.AgeBiologicalYearsFloat); //Log.Message("[RJW]PawnCapacityWorker_Fertility::CalculateCapacityLevel result is: " + result); return(result); }
public static void Doimpregnate(Pawn pawn, Pawn partner) { if (RJWSettings.DevMode) { Log.Message("[RJW] Doimpregnate " + xxx.get_pawnname(pawn) + " is a father, " + xxx.get_pawnname(partner) + " is a mother"); } if (AndroidsCompatibility.IsAndroid(pawn) && !AndroidsCompatibility.AndroidPenisFertility(pawn)) { if (RJWSettings.DevMode) { Log.Message(" Father is android with no arcotech penis, abort"); } return; } if (AndroidsCompatibility.IsAndroid(partner) && !AndroidsCompatibility.AndroidVaginaFertility(partner)) { if (RJWSettings.DevMode) { Log.Message(" Mother is android with no arcotech v****a, abort"); } return; } // fertility check float fertility = RJWPregnancySettings.humanlike_impregnation_chance / 100f; if (xxx.is_animal(partner)) { fertility = RJWPregnancySettings.animal_impregnation_chance / 100f; } // Interspecies modifier if (pawn.def.defName != partner.def.defName) { if (RJWPregnancySettings.complex_interspecies) { fertility *= SexUtility.BodySimilarity(pawn, partner); } else { fertility *= RJWPregnancySettings.interspecies_impregnation_modifier; } } //Rand.PopState(); //Rand.PushState(RJW_Multiplayer.PredictableSeed()); float ReproductionFactor = Math.Min(pawn.health.capacities.GetLevel(xxx.reproduction), partner.health.capacities.GetLevel(xxx.reproduction)); float pregnancy_threshold = fertility * ReproductionFactor; float non_pregnancy_chance = Rand.Value; BodyPartRecord torso = partner.RaceProps.body.AllParts.Find(x => x.def == BodyPartDefOf.Torso); if (non_pregnancy_chance > pregnancy_threshold || pregnancy_threshold == 0) { if (RJWSettings.DevMode) { Log.Message(" Impregnation failed. Chance: " + pregnancy_threshold.ToStringPercent() + " roll: " + non_pregnancy_chance.ToStringPercent()); } return; } if (RJWSettings.DevMode) { Log.Message(" Impregnation succeeded. Chance: " + pregnancy_threshold.ToStringPercent() + " roll: " + non_pregnancy_chance.ToStringPercent()); } PregnancyDecider(partner, pawn); }