using RimWorld; using UnityEngine; using Verse; namespace RJW_Menstruation { public class CompProperties_InducedOvulator : CompProperties_Menstruation { public CompProperties_InducedOvulator() { compClass = typeof(HediffComp_InducedOvulator); } } public class HediffComp_InducedOvulator : HediffComp_Menstruation { protected bool hadOvulatoryStage = false; // Regardless of whether an egg was actually produced protected override void InitializeExtraValues() { base.InitializeExtraValues(); hadOvulatoryStage |= IsEggExist; } public override string GetCurStageDesc { get { switch (CurrentVisibleStage) { case Stage.Follicular: return Translations.Stage_Follicular_Induced_Desc + (EggHealth < 1f ? " " + Translations.Stage_Climacteric_Desc : ""); default: return base.GetCurStageDesc; } } } // In an induced ovulator, about 65% of eggs ovulated will become pregnancies, so the expected lifetime supply // is the number of pregnancies they could have, with some extra to be sure. // An IUD or a poor fertility mate could run this down quicker. Oh well. protected override float RaceCyclesPerYear() { // Don't bother with breeding season, since so much time is planned to be spent pregnant. float pregnanciesPerYear = GenDate.DaysPerYear / Mathf.Max(1, Pawn.RaceProps.gestationPeriodDays); return 2 * pregnanciesPerYear / Configurations.ImplantationChanceDefault; } // There's really no good way to estimate the number of times it's been induced, so this is all we can do protected override int PawnEggsUsed(float pawnCyclesElapsed, float avglittersize) { return Mathf.CeilToInt((Pawn.relations?.ChildrenCount ?? 0) / Configurations.ImplantationChanceDefault); } public override void CompExposeData() { base.CompExposeData(); Scribe_Values.Look(ref hadOvulatoryStage, "hadOvulatoryStage", false); } protected override void GoOvulatoryStage() { estrusflag = false; hadOvulatoryStage = false; GoNextStage(Stage.Luteal); } protected override void OvulatoryAction() { base.OvulatoryAction(); hadOvulatoryStage = true; } protected override void LutealAction() { base.LutealAction(); if (curStage != Stage.Luteal) hadOvulatoryStage = false; } protected override void AfterCumIn(Pawn cummer) { base.AfterCumIn(cummer); if (curStage == Stage.Follicular) GoNextStage(Stage.Ovulatory); } public override bool IsDangerDay { get { if (Pawn.HasIUD()) return false; switch (curStage) { case Stage.Follicular: case Stage.Ovulatory: return true; case Stage.Luteal: return hadOvulatoryStage && curStageTicks < EggLifespanTicks; default: return false; } } } protected override bool ShouldBeInEstrus() { if (curStage == Stage.Luteal && !hadOvulatoryStage) return false; else return base.ShouldBeInEstrus(); } protected override float RandomOvulationChance => 0; } }