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);
        }
Exemplo n.º 2
0
        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);
        }