mirror of
				https://gitgud.io/lutepickle/rjw_menstruation.git
				synced 2024-08-14 22:46:52 +00:00 
			
		
		
		
	Initial implementation of variable update rate
This commit is contained in:
		
							parent
							
								
									2696c2b1f0
								
							
						
					
					
						commit
						e37940abcf
					
				
					 13 changed files with 267 additions and 163 deletions
				
			
		
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -56,6 +56,12 @@
 | 
				
			||||||
  <Option6_Desc>Cum will lose fertility by this amount every hour
This value affects fertilization chance indirectly.</Option6_Desc>
 | 
					  <Option6_Desc>Cum will lose fertility by this amount every hour
This value affects fertilization chance indirectly.</Option6_Desc>
 | 
				
			||||||
  <Option7_Label>Cycle acceleration</Option7_Label>
 | 
					  <Option7_Label>Cycle acceleration</Option7_Label>
 | 
				
			||||||
  <Option7_Desc>Accelerate menstruation cycle
This can cause early menopause and infertility.
Setting this lower than x12 is recommended.
Rimworld's timescale: x6(default)</Option7_Desc>
 | 
					  <Option7_Desc>Accelerate menstruation cycle
This can cause early menopause and infertility.
Setting this lower than x12 is recommended.
Rimworld's timescale: x6(default)</Option7_Desc>
 | 
				
			||||||
 | 
					  <Option_ColonistUpdateInterval_Label>Colonist update interval</Option_ColonistUpdateInterval_Label>
 | 
				
			||||||
 | 
					  <Option_ColonistUpdateInterval_Desc>How often the womb of each of your colonists, prisoners, and slaves update.
Lowering this will improve accuracy, increasing this can improve performance.</Option_ColonistUpdateInterval_Desc>
 | 
				
			||||||
 | 
					  <Option_NonColonistUpdateInterval_Label>Non-colonist update interval</Option_NonColonistUpdateInterval_Label>
 | 
				
			||||||
 | 
					  <Option_NonColonistUpdateInterval_Desc>How often the womb of humans you don't control update.
Lowering this will improve accuracy, increasing this can improve performance.</Option_NonColonistUpdateInterval_Desc>
 | 
				
			||||||
 | 
					  <Option_AnimalUpdateInterval_Label>Animal update interval</Option_AnimalUpdateInterval_Label>
 | 
				
			||||||
 | 
					  <Option_AnimalUpdateInterval_Desc>How often the womb of animals update.
Lowering this will improve accuracy, increasing this can improve performance.</Option_AnimalUpdateInterval_Desc>
 | 
				
			||||||
  <Option8_Label>Debug</Option8_Label>
 | 
					  <Option8_Label>Debug</Option8_Label>
 | 
				
			||||||
  <Option8_Desc>Show debug information.</Option8_Desc>
 | 
					  <Option8_Desc>Show debug information.</Option8_Desc>
 | 
				
			||||||
  <Option9_Label>Womb status</Option9_Label>
 | 
					  <Option9_Label>Womb status</Option9_Label>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
using rjw;
 | 
					using RimWorld;
 | 
				
			||||||
 | 
					using rjw;
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using UnityEngine;
 | 
					using UnityEngine;
 | 
				
			||||||
| 
						 | 
					@ -17,6 +18,9 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public const float CumFertilityDecayRatioDefault = 0.05f;
 | 
					        public const float CumFertilityDecayRatioDefault = 0.05f;
 | 
				
			||||||
        public const int CumFertilityDecayRatioAdjustDefault = 50;
 | 
					        public const int CumFertilityDecayRatioAdjustDefault = 50;
 | 
				
			||||||
        public const int CycleAccelerationDefault = 6;
 | 
					        public const int CycleAccelerationDefault = 6;
 | 
				
			||||||
 | 
					        public const int ColonistTickIntervalDefault = 2500; // 1 hour
 | 
				
			||||||
 | 
					        public const int NonColonistTickIntervalDefault = 2500;
 | 
				
			||||||
 | 
					        public const int AnimalTickIntervalDefault = 2500;
 | 
				
			||||||
        public const float EnzygoticTwinsChanceDefault = 0.002f;
 | 
					        public const float EnzygoticTwinsChanceDefault = 0.002f;
 | 
				
			||||||
        public const int EnzygoticTwinsChanceAdjustDefault = 2;
 | 
					        public const int EnzygoticTwinsChanceAdjustDefault = 2;
 | 
				
			||||||
        public const int MaxEnzygoticTwinsDefault = 9;
 | 
					        public const int MaxEnzygoticTwinsDefault = 9;
 | 
				
			||||||
| 
						 | 
					@ -41,6 +45,9 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public static float CumFertilityDecayRatio = CumFertilityDecayRatioDefault;
 | 
					        public static float CumFertilityDecayRatio = CumFertilityDecayRatioDefault;
 | 
				
			||||||
        public static int CumFertilityDecayRatioAdjust = CumFertilityDecayRatioAdjustDefault;
 | 
					        public static int CumFertilityDecayRatioAdjust = CumFertilityDecayRatioAdjustDefault;
 | 
				
			||||||
        public static int CycleAcceleration = CycleAccelerationDefault;
 | 
					        public static int CycleAcceleration = CycleAccelerationDefault;
 | 
				
			||||||
 | 
					        public static int ColonistTickInterval = ColonistTickIntervalDefault;
 | 
				
			||||||
 | 
					        public static int NonColonistTickInterval = NonColonistTickIntervalDefault;
 | 
				
			||||||
 | 
					        public static int AnimalTickInterval = AnimalTickIntervalDefault;
 | 
				
			||||||
        public static bool EnableWombIcon = true;
 | 
					        public static bool EnableWombIcon = true;
 | 
				
			||||||
        public static bool EnableDraftedIcon = true;
 | 
					        public static bool EnableDraftedIcon = true;
 | 
				
			||||||
        public static bool EnableAnimalCycle = false;
 | 
					        public static bool EnableAnimalCycle = false;
 | 
				
			||||||
| 
						 | 
					@ -85,6 +92,9 @@ namespace RJW_Menstruation
 | 
				
			||||||
            EnableGatherCumGizmo = true;
 | 
					            EnableGatherCumGizmo = true;
 | 
				
			||||||
            EnableAnimalCycle = false;
 | 
					            EnableAnimalCycle = false;
 | 
				
			||||||
            CycleAcceleration = CycleAccelerationDefault;
 | 
					            CycleAcceleration = CycleAccelerationDefault;
 | 
				
			||||||
 | 
					            ColonistTickInterval = ColonistTickIntervalDefault;
 | 
				
			||||||
 | 
					            NonColonistTickInterval = NonColonistTickIntervalDefault;
 | 
				
			||||||
 | 
					            AnimalTickInterval = AnimalTickIntervalDefault;
 | 
				
			||||||
            EstrusOverridesHookupSettings = false;
 | 
					            EstrusOverridesHookupSettings = false;
 | 
				
			||||||
            EstrusFuckabilityToHookup = RJWHookupSettings.MinimumFuckabilityToHookup;
 | 
					            EstrusFuckabilityToHookup = RJWHookupSettings.MinimumFuckabilityToHookup;
 | 
				
			||||||
            EstrusAttractivenessToHookup = RJWHookupSettings.MinimumAttractivenessToHookup;
 | 
					            EstrusAttractivenessToHookup = RJWHookupSettings.MinimumAttractivenessToHookup;
 | 
				
			||||||
| 
						 | 
					@ -188,6 +198,9 @@ namespace RJW_Menstruation
 | 
				
			||||||
            Scribe_Values.Look(ref CumFertilityDecayRatioAdjust, "CumFertilityDecayRatioAdjust", CumFertilityDecayRatioAdjust, true);
 | 
					            Scribe_Values.Look(ref CumFertilityDecayRatioAdjust, "CumFertilityDecayRatioAdjust", CumFertilityDecayRatioAdjust, true);
 | 
				
			||||||
            Scribe_Values.Look(ref CumFertilityDecayRatio, "CumFertilityDecayRatio", CumFertilityDecayRatio, true);
 | 
					            Scribe_Values.Look(ref CumFertilityDecayRatio, "CumFertilityDecayRatio", CumFertilityDecayRatio, true);
 | 
				
			||||||
            Scribe_Values.Look(ref CycleAcceleration, "CycleAcceleration", CycleAcceleration, true);
 | 
					            Scribe_Values.Look(ref CycleAcceleration, "CycleAcceleration", CycleAcceleration, true);
 | 
				
			||||||
 | 
					            Scribe_Values.Look(ref ColonistTickInterval, "ColonistTickInterval", ColonistTickInterval, true);
 | 
				
			||||||
 | 
					            Scribe_Values.Look(ref NonColonistTickInterval, "NonColonistTickInterval", NonColonistTickInterval, true);
 | 
				
			||||||
 | 
					            Scribe_Values.Look(ref AnimalTickInterval, "AnimalTickInterval", AnimalTickInterval, true);
 | 
				
			||||||
            Scribe_Values.Look(ref EnableWombIcon, "EnableWombIcon", EnableWombIcon, true);
 | 
					            Scribe_Values.Look(ref EnableWombIcon, "EnableWombIcon", EnableWombIcon, true);
 | 
				
			||||||
            Scribe_Values.Look(ref EnableDraftedIcon, "EnableDraftedIcon", EnableDraftedIcon, true);
 | 
					            Scribe_Values.Look(ref EnableDraftedIcon, "EnableDraftedIcon", EnableDraftedIcon, true);
 | 
				
			||||||
            Scribe_Values.Look(ref EnableAnimalCycle, "EnableAnimalCycle", EnableAnimalCycle, true);
 | 
					            Scribe_Values.Look(ref EnableAnimalCycle, "EnableAnimalCycle", EnableAnimalCycle, true);
 | 
				
			||||||
| 
						 | 
					@ -274,8 +287,9 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public override void DoSettingsWindowContents(Rect inRect)
 | 
					        public override void DoSettingsWindowContents(Rect inRect)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Rect outRect = new Rect(0f, 30f, inRect.width, inRect.height - 30f);
 | 
					            Rect outRect = new Rect(0f, 30f, inRect.width, inRect.height - 30f);
 | 
				
			||||||
            float mainRectHeight = 30f +
 | 
					            float mainRectHeight = 126f +
 | 
				
			||||||
                (Configurations.EnableWombIcon || Configurations.EnableButtonInHT ? 400f : 0f) +
 | 
					                (Configurations.EnableWombIcon || Configurations.EnableButtonInHT ? 400f : 0f) +
 | 
				
			||||||
 | 
					                (Configurations.EnableAnimalCycle ? 48f : 0f) +
 | 
				
			||||||
                (Configurations.EstrusOverridesHookupSettings ? 144f : 0f) +
 | 
					                (Configurations.EstrusOverridesHookupSettings ? 144f : 0f) +
 | 
				
			||||||
                (Configurations.PregnancySource == Configurations.PregnancyType.MultiplePregnancy ? (Configurations.EnableEnzygoticTwins ? 175f : 75f) : 0f) +
 | 
					                (Configurations.PregnancySource == Configurations.PregnancyType.MultiplePregnancy ? (Configurations.EnableEnzygoticTwins ? 175f : 75f) : 0f) +
 | 
				
			||||||
                (Configurations.PregnancySource == Configurations.PregnancyType.Biotech ? 75f : 0f) +
 | 
					                (Configurations.PregnancySource == Configurations.PregnancyType.Biotech ? 75f : 0f) +
 | 
				
			||||||
| 
						 | 
					@ -403,11 +417,11 @@ namespace RJW_Menstruation
 | 
				
			||||||
            string estimatedlifespan;
 | 
					            string estimatedlifespan;
 | 
				
			||||||
            if (semenlifespan < 0)
 | 
					            if (semenlifespan < 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                estimatedlifespan = String.Format(": Infinite", semenlifespan);
 | 
					                estimatedlifespan = string.Format(": Infinite", semenlifespan);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                estimatedlifespan = String.Format(": {0:0}h", semenlifespan);
 | 
					                estimatedlifespan = string.Format(": {0:0}h", semenlifespan);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            listmain.LabelDouble(Translations.Option6_Label + " " + Configurations.CumFertilityDecayRatio * 100 + "%", Translations.EstimatedCumLifespan + estimatedlifespan, Translations.Option6_Desc);
 | 
					            listmain.LabelDouble(Translations.Option6_Label + " " + Configurations.CumFertilityDecayRatio * 100 + "%", Translations.EstimatedCumLifespan + estimatedlifespan, Translations.Option6_Desc);
 | 
				
			||||||
            Configurations.CumFertilityDecayRatioAdjust = (int)listmain.Slider(Configurations.CumFertilityDecayRatioAdjust, 0, 1000);
 | 
					            Configurations.CumFertilityDecayRatioAdjust = (int)listmain.Slider(Configurations.CumFertilityDecayRatioAdjust, 0, 1000);
 | 
				
			||||||
| 
						 | 
					@ -416,6 +430,20 @@ namespace RJW_Menstruation
 | 
				
			||||||
            listmain.Label(Translations.Option7_Label + " x" + Configurations.CycleAcceleration, -1, Translations.Option7_Desc);
 | 
					            listmain.Label(Translations.Option7_Label + " x" + Configurations.CycleAcceleration, -1, Translations.Option7_Desc);
 | 
				
			||||||
            Configurations.CycleAcceleration = (int)listmain.Slider(Configurations.CycleAcceleration, 1, 50);
 | 
					            Configurations.CycleAcceleration = (int)listmain.Slider(Configurations.CycleAcceleration, 1, 50);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Adjust = Configurations.ColonistTickInterval / 25;
 | 
				
			||||||
 | 
					            listmain.LabelDouble(Translations.Option_ColonistUpdateInterval_Label, GenDate.ToStringTicksToPeriod(Configurations.ColonistTickInterval), Translations.Option_ColonistUpdateInterval_Desc);
 | 
				
			||||||
 | 
					            Configurations.ColonistTickInterval = (int)listmain.Slider(Adjust, 0, 400) * 25;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Adjust = Configurations.NonColonistTickInterval / 25;
 | 
				
			||||||
 | 
					            listmain.LabelDouble(Translations.Option_NonColonistUpdateInterval_Label, GenDate.ToStringTicksToPeriod(Configurations.NonColonistTickInterval), Translations.Option_NonColonistUpdateInterval_Desc);
 | 
				
			||||||
 | 
					            Configurations.NonColonistTickInterval = (int)listmain.Slider(Adjust, 0, 400) * 25;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(Configurations.EnableAnimalCycle)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Adjust = Configurations.AnimalTickInterval / 25;
 | 
				
			||||||
 | 
					                listmain.LabelDouble(Translations.Option_AnimalUpdateInterval_Label, GenDate.ToStringTicksToPeriod(Configurations.AnimalTickInterval), Translations.Option_AnimalUpdateInterval_Desc);
 | 
				
			||||||
 | 
					                Configurations.AnimalTickInterval = (int)listmain.Slider(Adjust, 0, 400) * 25;
 | 
				
			||||||
 | 
					            }            
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            float var2 = EstimatedBleedingAmountPerHour;
 | 
					            float var2 = EstimatedBleedingAmountPerHour;
 | 
				
			||||||
            float var1 = Math.Max(EstimatedBleedingAmount, var2);
 | 
					            float var1 = Math.Max(EstimatedBleedingAmount, var2);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -205,8 +205,10 @@ namespace RJW_Menstruation
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // comp is used for Hydrogen's RJW Muscle Injury
 | 
					            // comp is used for Hydrogen's RJW Muscle Injury
 | 
				
			||||||
            float totalleak = volume;
 | 
					            float totalleak = volume;
 | 
				
			||||||
            volume *= Math.Max(0, (1 - (Configurations.CumDecayRatio * (1 - DecayResist)) * leakfactor));
 | 
					            float decayPerInterval = 1 - Mathf.Pow(1 - Configurations.CumDecayRatio, comp.TickInterval / GenDate.TicksPerHour);
 | 
				
			||||||
            fertility *= Math.Max(0, 1 - (Configurations.CumFertilityDecayRatio * (1 - DecayResist) + antisperm));
 | 
					            float fertilityDecayPerInterval = 1 - Mathf.Pow(Configurations.CumFertilityDecayRatio, comp.TickInterval / GenDate.TicksPerHour);
 | 
				
			||||||
 | 
					            volume *= Math.Max(0, 1 - decayPerInterval * (1 - DecayResist) * leakfactor);
 | 
				
			||||||
 | 
					            fertility *= Math.Max(0, 1 - (fertilityDecayPerInterval * (1 - DecayResist) + antisperm));
 | 
				
			||||||
            CutMinor();
 | 
					            CutMinor();
 | 
				
			||||||
            totalleak -= volume;
 | 
					            totalleak -= volume;
 | 
				
			||||||
            return totalleak;
 | 
					            return totalleak;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,7 +70,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                    case Stage.Ovulatory:
 | 
					                    case Stage.Ovulatory:
 | 
				
			||||||
                        return true;
 | 
					                        return true;
 | 
				
			||||||
                    case Stage.Luteal:
 | 
					                    case Stage.Luteal:
 | 
				
			||||||
                        return IsEggExist && curStageHrs < EggLifespanHours;
 | 
					                        return IsEggExist && curStageTicks < EggLifespanTicks;
 | 
				
			||||||
                    default:
 | 
					                    default:
 | 
				
			||||||
                        return false;
 | 
					                        return false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -84,11 +84,11 @@ namespace RJW_Menstruation
 | 
				
			||||||
            switch (curStage)
 | 
					            switch (curStage)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                case Stage.Follicular:
 | 
					                case Stage.Follicular:
 | 
				
			||||||
                    return curStageHrs > currentIntervalHours - Props.estrusDaysBeforeOvulation * 24;
 | 
					                    return curStageTicks > currentIntervalTicks - Props.estrusDaysBeforeOvulation * GenDate.TicksPerDay;
 | 
				
			||||||
                case Stage.Ovulatory:
 | 
					                case Stage.Ovulatory:
 | 
				
			||||||
                    return true;
 | 
					                    return true;
 | 
				
			||||||
                case Stage.Luteal:
 | 
					                case Stage.Luteal:
 | 
				
			||||||
                    return IsEggExist && curStageHrs < EggLifespanHours;
 | 
					                    return IsEggExist && curStageTicks < EggLifespanTicks;
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public float baseImplantationChanceFactor;
 | 
					        public float baseImplantationChanceFactor;
 | 
				
			||||||
        public float basefertilizationChanceFactor;
 | 
					        public float basefertilizationChanceFactor;
 | 
				
			||||||
        public int follicularIntervalDays = 14; //before ovulation including beginning of bleeding
 | 
					        public int follicularIntervalDays = 14; //before ovulation including beginning of bleeding
 | 
				
			||||||
 | 
					        public int ovulationIntervalHours = 12; //between the end of follicular and the egg emerging
 | 
				
			||||||
        public int lutealIntervalDays = 14; //after ovulation until bleeding
 | 
					        public int lutealIntervalDays = 14; //after ovulation until bleeding
 | 
				
			||||||
        public int bleedingIntervalDays = 6; //must be less than folicularIntervalDays
 | 
					        public int bleedingIntervalDays = 6; //must be less than folicularIntervalDays
 | 
				
			||||||
        public int recoveryIntervalDays = 10; //additional infertile days after gave birth
 | 
					        public int recoveryIntervalDays = 10; //additional infertile days after gave birth
 | 
				
			||||||
| 
						 | 
					@ -63,17 +64,16 @@ namespace RJW_Menstruation
 | 
				
			||||||
    public class HediffComp_Menstruation : HediffComp
 | 
					    public class HediffComp_Menstruation : HediffComp
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        const float minmakefilthvalue = 1.0f;
 | 
					        const float minmakefilthvalue = 1.0f;
 | 
				
			||||||
        //const int ovarypowerthreshold = 72;
 | 
					        const int maxImplantDelayHours = 30 * GenDate.HoursPerDay;
 | 
				
			||||||
 | 
					        const int minImplantAgeHours = 3 * GenDate.HoursPerDay;
 | 
				
			||||||
        const int tickInterval = GenDate.TicksPerHour;
 | 
					 | 
				
			||||||
        const int maxImplantDelayHours = 30 * 24;
 | 
					 | 
				
			||||||
        const int minImplantAgeHours = 3 * 24;
 | 
					 | 
				
			||||||
        const float pulloutSuccessRate = 0.8f;
 | 
					        const float pulloutSuccessRate = 0.8f;
 | 
				
			||||||
        const float fetishPulloutSuccessModifier = 0.25f;
 | 
					        const float fetishPulloutSuccessModifier = 0.25f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public CompProperties_Menstruation Props;
 | 
					        public CompProperties_Menstruation Props;
 | 
				
			||||||
        public Stage curStage = Stage.Follicular;
 | 
					        public Stage curStage = Stage.Follicular;
 | 
				
			||||||
        public int curStageHrs = 0;
 | 
					        public int curStageTicks = 0;   // Actual number of ticks equals this / cycleAcceleration
 | 
				
			||||||
 | 
					        private int tickInterval = -1;
 | 
				
			||||||
 | 
					        const int recalculateTickInterval = GenDate.TicksPerDay;
 | 
				
			||||||
        public bool loaded = false;
 | 
					        public bool loaded = false;
 | 
				
			||||||
        public bool initError = false;
 | 
					        public bool initError = false;
 | 
				
			||||||
        public int ovarypower = -100000;
 | 
					        public int ovarypower = -100000;
 | 
				
			||||||
| 
						 | 
					@ -114,7 +114,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
        protected List<Egg> eggs;
 | 
					        protected List<Egg> eggs;
 | 
				
			||||||
        protected float cycleSpeed = -1;
 | 
					        protected float cycleSpeed = -1;
 | 
				
			||||||
        protected float cycleVariability = -1;
 | 
					        protected float cycleVariability = -1;
 | 
				
			||||||
        protected int currentIntervalHours = -1;
 | 
					        protected int currentIntervalTicks = -1;   // Actual number of ticks equals this / cycleAcceleration
 | 
				
			||||||
        protected float crampPain = -1;
 | 
					        protected float crampPain = -1;
 | 
				
			||||||
        protected Need sexNeed = null;
 | 
					        protected Need sexNeed = null;
 | 
				
			||||||
        protected string customwombtex = null;
 | 
					        protected string customwombtex = null;
 | 
				
			||||||
| 
						 | 
					@ -126,7 +126,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
        // RJW pregnancy, or Biotech pregnancy/labor/laborpushing
 | 
					        // RJW pregnancy, or Biotech pregnancy/labor/laborpushing
 | 
				
			||||||
        protected Hediff pregnancy = null;
 | 
					        protected Hediff pregnancy = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected int eggLifeSpanHours = 48;
 | 
					        protected int eggLifeSpanTicks = 2 * GenDate.TicksPerDay;
 | 
				
			||||||
        protected EstrusLevel estrusLevel = EstrusLevel.Visible;
 | 
					        protected EstrusLevel estrusLevel = EstrusLevel.Visible;
 | 
				
			||||||
        protected float ovulationFactor = 1f;
 | 
					        protected float ovulationFactor = 1f;
 | 
				
			||||||
        protected bool noBleeding = false;
 | 
					        protected bool noBleeding = false;
 | 
				
			||||||
| 
						 | 
					@ -155,6 +155,21 @@ namespace RJW_Menstruation
 | 
				
			||||||
            new CurvePoint(1.0f,0.5f)
 | 
					            new CurvePoint(1.0f,0.5f)
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public int TickInterval
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (tickInterval <= 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    if (Pawn.IsAnimal()) tickInterval = Configurations.AnimalTickInterval;
 | 
				
			||||||
 | 
					                    else if (Pawn.IsColonist || Pawn.IsPrisonerOfColony || Pawn.IsSlaveOfColony) tickInterval = Configurations.ColonistTickInterval;
 | 
				
			||||||
 | 
					                    else tickInterval = Configurations.NonColonistTickInterval;
 | 
				
			||||||
 | 
					                    if (tickInterval <= 0) tickInterval = 1;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return tickInterval;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Hediff Pregnancy {
 | 
					        public Hediff Pregnancy {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
| 
						 | 
					@ -480,12 +495,12 @@ namespace RJW_Menstruation
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// returns fertstage. if not fertilized returns -1
 | 
					        /// returns fertstage. if not fertilized returns -1
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        public int IsFertilized
 | 
					        public int EggFertilizedTime
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (eggs?.All(egg => !egg.fertilized) ?? true) return -1;
 | 
					                if (eggs?.All(egg => !egg.fertilized) ?? true) return -1;
 | 
				
			||||||
                return eggs.Max(egg => egg.fertstage);
 | 
					                return eggs.Max(egg => egg.ticksSinceFertilization);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public IEnumerable<Pawn> GetCummersAndFertilizers()
 | 
					        public IEnumerable<Pawn> GetCummersAndFertilizers()
 | 
				
			||||||
| 
						 | 
					@ -502,9 +517,9 @@ namespace RJW_Menstruation
 | 
				
			||||||
            get => !eggs.NullOrEmpty();
 | 
					            get => !eggs.NullOrEmpty();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public int EggLifespanHours
 | 
					        public int EggLifespanTicks
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get => eggLifeSpanHours;
 | 
					            get => eggLifeSpanTicks;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public virtual bool IsDangerDay
 | 
					        public virtual bool IsDangerDay
 | 
				
			||||||
| 
						 | 
					@ -516,11 +531,11 @@ namespace RJW_Menstruation
 | 
				
			||||||
                switch (curStage)
 | 
					                switch (curStage)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    case Stage.Follicular:
 | 
					                    case Stage.Follicular:
 | 
				
			||||||
                        return curStageHrs > 0.7f * currentIntervalHours;
 | 
					                        return curStageTicks > 0.7f * currentIntervalTicks;
 | 
				
			||||||
                    case Stage.Ovulatory:
 | 
					                    case Stage.Ovulatory:
 | 
				
			||||||
                        return true;
 | 
					                        return true;
 | 
				
			||||||
                    case Stage.Luteal:
 | 
					                    case Stage.Luteal:
 | 
				
			||||||
                        return curStageHrs < EggLifespanHours;
 | 
					                        return curStageTicks < EggLifespanTicks;
 | 
				
			||||||
                    default:
 | 
					                    default:
 | 
				
			||||||
                        return false;
 | 
					                        return false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -559,16 +574,16 @@ namespace RJW_Menstruation
 | 
				
			||||||
            set => originvagsize = value;
 | 
					            set => originvagsize = value;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public float CurStageIntervalHours
 | 
					        public int CurStageIntervalTicks
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get => currentIntervalHours;
 | 
					            get => currentIntervalTicks;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public float StageProgress
 | 
					        public float StageProgress
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (pregnancy == null) return Mathf.Clamp01(curStageHrs / CurStageIntervalHours);
 | 
					                if (pregnancy == null) return Mathf.Clamp01((float)curStageTicks / currentIntervalTicks);
 | 
				
			||||||
                bool is_discovered = false;
 | 
					                bool is_discovered = false;
 | 
				
			||||||
                switch (pregnancy)
 | 
					                switch (pregnancy)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
| 
						 | 
					@ -590,7 +605,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                if (Pawn.story?.bodyType == BodyTypeDefOf.Thin) discoveryTime = 0.25f;
 | 
					                if (Pawn.story?.bodyType == BodyTypeDefOf.Thin) discoveryTime = 0.25f;
 | 
				
			||||||
                else if (Pawn.story?.bodyType == BodyTypeDefOf.Female) discoveryTime = 0.35f;
 | 
					                else if (Pawn.story?.bodyType == BodyTypeDefOf.Female) discoveryTime = 0.35f;
 | 
				
			||||||
                // Estimated; there's no way to get the exact value after the fact without writing it into the save
 | 
					                // Estimated; there's no way to get the exact value after the fact without writing it into the save
 | 
				
			||||||
                float lutealProgressWhenImplanted = Math.Min(0.5f, maxImplantDelayHours / (Props.lutealIntervalDays * 24));
 | 
					                float lutealProgressWhenImplanted = Math.Min(0.5f, maxImplantDelayHours / (Props.lutealIntervalDays * GenDate.HoursPerDay));
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                return GenMath.LerpDouble(0, discoveryTime, lutealProgressWhenImplanted, 1.0f, pregnancy.Severity);
 | 
					                return GenMath.LerpDouble(0, discoveryTime, lutealProgressWhenImplanted, 1.0f, pregnancy.Severity);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -608,13 +623,23 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public override void CompExposeData()
 | 
					        public override void CompExposeData()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            base.CompExposeData();
 | 
					            base.CompExposeData();
 | 
				
			||||||
 | 
					            if (Scribe.mode == LoadSaveMode.LoadingVars)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                int curStageHrs = -1;
 | 
				
			||||||
 | 
					                int currentIntervalHours = -1;
 | 
				
			||||||
 | 
					                Scribe_Values.Look(ref curStageHrs, "curStageHrs", curStageHrs, true);
 | 
				
			||||||
 | 
					                Scribe_Values.Look(ref currentIntervalHours, "currentIntervalHours", currentIntervalHours, true);
 | 
				
			||||||
 | 
					                if (curStageHrs >= 0) curStageTicks = curStageHrs * GenDate.TicksPerHour;
 | 
				
			||||||
 | 
					                if (currentIntervalHours >= 0) currentIntervalTicks = currentIntervalHours * GenDate.TicksPerHour;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Scribe_Collections.Look(ref cums, saveDestroyedThings: true, label: "cums", lookMode: LookMode.Deep, ctorArgs: new object[0]);
 | 
					            Scribe_Collections.Look(ref cums, saveDestroyedThings: true, label: "cums", lookMode: LookMode.Deep, ctorArgs: new object[0]);
 | 
				
			||||||
            Scribe_Collections.Look(ref eggs, saveDestroyedThings: true, label: "eggs", lookMode: LookMode.Deep, ctorArgs: new object[0]);
 | 
					            Scribe_Collections.Look(ref eggs, saveDestroyedThings: true, label: "eggs", lookMode: LookMode.Deep, ctorArgs: new object[0]);
 | 
				
			||||||
            Scribe_Values.Look(ref curStage, "curStage", curStage, true);
 | 
					            Scribe_Values.Look(ref curStage, "curStage", curStage, true);
 | 
				
			||||||
            Scribe_Values.Look(ref curStageHrs, "curStageHrs", curStageHrs, true);
 | 
					            Scribe_Values.Look(ref curStageTicks, "curStageTicks", curStageTicks, true);
 | 
				
			||||||
            Scribe_Values.Look(ref cycleSpeed, "cycleSpeed", cycleSpeed, true);
 | 
					            Scribe_Values.Look(ref cycleSpeed, "cycleSpeed", cycleSpeed, true);
 | 
				
			||||||
            Scribe_Values.Look(ref cycleVariability, "cycleVariability", cycleVariability, true);
 | 
					            Scribe_Values.Look(ref cycleVariability, "cycleVariability", cycleVariability, true);
 | 
				
			||||||
            Scribe_Values.Look(ref currentIntervalHours, "currentIntervalHours", currentIntervalHours, true);
 | 
					            Scribe_Values.Look(ref currentIntervalTicks, "currentIntervalTicks", currentIntervalTicks, true);
 | 
				
			||||||
            Scribe_Values.Look(ref crampPain, "crampPain", crampPain, true);
 | 
					            Scribe_Values.Look(ref crampPain, "crampPain", crampPain, true);
 | 
				
			||||||
            Scribe_Values.Look(ref ovarypower, "ovarypower", ovarypower, true);
 | 
					            Scribe_Values.Look(ref ovarypower, "ovarypower", ovarypower, true);
 | 
				
			||||||
            Scribe_Values.Look(ref eggstack, "eggstack", eggstack, true);
 | 
					            Scribe_Values.Look(ref eggstack, "eggstack", eggstack, true);
 | 
				
			||||||
| 
						 | 
					@ -635,16 +660,16 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void Notify_UpdatedGenes()
 | 
					        public void Notify_UpdatedGenes()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            eggLifeSpanHours = Props.eggLifespanDays * 24;
 | 
					            eggLifeSpanTicks = Props.eggLifespanDays * GenDate.TicksPerDay;
 | 
				
			||||||
            estrusLevel = Props.concealedEstrus ? EstrusLevel.Concealed : EstrusLevel.Visible;
 | 
					            estrusLevel = Props.concealedEstrus ? EstrusLevel.Concealed : EstrusLevel.Visible;
 | 
				
			||||||
            ovulationFactor = 1f;
 | 
					            ovulationFactor = 1f;
 | 
				
			||||||
            noBleeding = false;
 | 
					            noBleeding = false;
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            if (Pawn.genes == null || !ModsConfig.BiotechActive) return;
 | 
					            if (Pawn.genes == null || !ModsConfig.BiotechActive) return;
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            if (Pawn.genes.HasGene(VariousDefOf.ShortEggLifetime)) eggLifeSpanHours = eggLifeSpanHours * 3 / 4;
 | 
					            if (Pawn.genes.HasGene(VariousDefOf.ShortEggLifetime)) eggLifeSpanTicks = eggLifeSpanTicks * 3 / 4;
 | 
				
			||||||
            else if (Pawn.genes.HasGene(VariousDefOf.DoubleEggLifetime)) eggLifeSpanHours *= 2;
 | 
					            else if (Pawn.genes.HasGene(VariousDefOf.DoubleEggLifetime)) eggLifeSpanTicks *= 2;
 | 
				
			||||||
            else if (Pawn.genes.HasGene(VariousDefOf.QuadEggLifetime)) eggLifeSpanHours *= 4;
 | 
					            else if (Pawn.genes.HasGene(VariousDefOf.QuadEggLifetime)) eggLifeSpanTicks *= 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (Pawn.genes.HasGene(VariousDefOf.NeverEstrus)) estrusLevel = EstrusLevel.None;
 | 
					            if (Pawn.genes.HasGene(VariousDefOf.NeverEstrus)) estrusLevel = EstrusLevel.None;
 | 
				
			||||||
            else if (Pawn.genes.HasGene(VariousDefOf.FullEstrus)) estrusLevel = EstrusLevel.Visible;
 | 
					            else if (Pawn.genes.HasGene(VariousDefOf.FullEstrus)) estrusLevel = EstrusLevel.Visible;
 | 
				
			||||||
| 
						 | 
					@ -688,7 +713,8 @@ namespace RJW_Menstruation
 | 
				
			||||||
                    Initialize();
 | 
					                    Initialize();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (!Pawn.IsHashIntervalTick(tickInterval)) return;
 | 
					                if (Pawn.IsHashIntervalTick(recalculateTickInterval)) tickInterval = -1;  // Every so often, force TickInterval to be recalculated in case the pawn's status changed.
 | 
				
			||||||
 | 
					                if (!Pawn.IsHashIntervalTick(TickInterval)) return;
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                if (initError) Log.Warning($"Attempting to process {Pawn}'s womb uninitialized");
 | 
					                if (initError) Log.Warning($"Attempting to process {Pawn}'s womb uninitialized");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -784,9 +810,9 @@ namespace RJW_Menstruation
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected virtual int HoursToNextStage()
 | 
					        protected virtual int TicksToNextStage()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return Math.Max(0,(currentIntervalHours - curStageHrs) / Configurations.CycleAcceleration);
 | 
					            return Math.Max(0,(currentIntervalTicks - curStageTicks) / Configurations.CycleAcceleration);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public override string CompDebugString()
 | 
					        public override string CompDebugString()
 | 
				
			||||||
| 
						 | 
					@ -794,7 +820,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
            if (curStage == Stage.None || curStage == Stage.Infertile || curStage == Stage.Pregnant) return base.CompDebugString();
 | 
					            if (curStage == Stage.None || curStage == Stage.Infertile || curStage == Stage.Pregnant) return base.CompDebugString();
 | 
				
			||||||
            StringBuilder debugString = new StringBuilder();
 | 
					            StringBuilder debugString = new StringBuilder();
 | 
				
			||||||
            debugString.Append($"Time to next state: ");
 | 
					            debugString.Append($"Time to next state: ");
 | 
				
			||||||
            debugString.Append(GenDate.ToStringTicksToPeriod(HoursToNextStage() * GenDate.TicksPerHour));
 | 
					            debugString.Append(GenDate.ToStringTicksToPeriod(TicksToNextStage()));
 | 
				
			||||||
            return debugString.ToString();
 | 
					            return debugString.ToString();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -805,11 +831,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
        /// <returns></returns>
 | 
					        /// <returns></returns>
 | 
				
			||||||
        public Cum GetNotCum(string notcumlabel)
 | 
					        public Cum GetNotCum(string notcumlabel)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!cums.NullOrEmpty()) foreach (Cum cum in cums)
 | 
					            return cums?.Find(cum => cum.notcum && cum.notcumLabel.Equals(notcumlabel));
 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    if (cum.notcum && cum.notcumLabel.Equals(notcumlabel)) return cum;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
| 
						 | 
					@ -825,17 +847,17 @@ namespace RJW_Menstruation
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Inject pawn's cum into womb
 | 
					        /// Inject pawn's cum into womb
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <param name="pawn"></param>
 | 
					        /// <param name="cummer"></param>
 | 
				
			||||||
        /// <param name="volume"></param>
 | 
					        /// <param name="volume"></param>
 | 
				
			||||||
        /// <param name="fertility"></param>
 | 
					        /// <param name="fertility"></param>
 | 
				
			||||||
        /// <param name="precum"></param>
 | 
					        /// <param name="precum"></param>
 | 
				
			||||||
        public void CumIn(Pawn pawn, float volume, float fertility = 1.0f, bool precum = false)
 | 
					        public void CumIn(Pawn cummer, float volume, float fertility = 1.0f, bool precum = false)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (volume <= 0) return;
 | 
					            if (volume <= 0) return;
 | 
				
			||||||
            if (!precum && fertility > 0 && IsDangerDay && pawn.relations.GetPregnancyApproachForPartner(Pawn) == PregnancyApproach.AvoidPregnancy)
 | 
					            if (!precum && fertility > 0 && IsDangerDay && cummer.relations.GetPregnancyApproachForPartner(Pawn) == PregnancyApproach.AvoidPregnancy)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                float successChance = pulloutSuccessRate;
 | 
					                float successChance = pulloutSuccessRate;
 | 
				
			||||||
                if (pawn.HasQuirk(QuirkUtility.Quirks.ImpregnationFetish)) successChance *= fetishPulloutSuccessModifier;
 | 
					                if (cummer.HasQuirk(QuirkUtility.Quirks.ImpregnationFetish)) successChance *= fetishPulloutSuccessModifier;
 | 
				
			||||||
                if (Pawn.HasQuirk(QuirkUtility.Quirks.ImpregnationFetish)) successChance *= fetishPulloutSuccessModifier;
 | 
					                if (Pawn.HasQuirk(QuirkUtility.Quirks.ImpregnationFetish)) successChance *= fetishPulloutSuccessModifier;
 | 
				
			||||||
                if (Rand.Chance(successChance)) return;
 | 
					                if (Rand.Chance(successChance)) return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -848,14 +870,14 @@ namespace RJW_Menstruation
 | 
				
			||||||
                bool merged = false;
 | 
					                bool merged = false;
 | 
				
			||||||
                if (!cums.NullOrEmpty()) foreach (Cum cum in cums)
 | 
					                if (!cums.NullOrEmpty()) foreach (Cum cum in cums)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        if (cum.pawn.Equals(pawn))
 | 
					                        if (cum.pawn.Equals(cummer))
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            cum.MergeWithCum(volume, fertility);
 | 
					                            cum.MergeWithCum(volume, fertility);
 | 
				
			||||||
                            merged = true;
 | 
					                            merged = true;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        cum.DismishForce(cumoutrate);
 | 
					                        cum.DismishForce(cumoutrate);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                if (!merged) cums.Add(new Cum(pawn, volume * (1 - cumoutrate), fertility));
 | 
					                if (!merged) cums.Add(new Cum(cummer, volume * (1 - cumoutrate), fertility));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
| 
						 | 
					@ -863,20 +885,20 @@ namespace RJW_Menstruation
 | 
				
			||||||
                bool merged = false;
 | 
					                bool merged = false;
 | 
				
			||||||
                if (!cums.NullOrEmpty()) foreach (Cum cum in cums)
 | 
					                if (!cums.NullOrEmpty()) foreach (Cum cum in cums)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        if (cum.pawn.Equals(pawn))
 | 
					                        if (cum.pawn.Equals(cummer))
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            cum.MergeWithCum(volume, fertility);
 | 
					                            cum.MergeWithCum(volume, fertility);
 | 
				
			||||||
                            merged = true;
 | 
					                            merged = true;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                if (!merged) cums.Add(new Cum(pawn, volume, fertility));
 | 
					                if (!merged) cums.Add(new Cum(cummer, volume, fertility));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            cumd = TotalCumPercent - cumd;
 | 
					            cumd = TotalCumPercent - cumd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!precum)
 | 
					            if (!precum)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Pawn.records.AddTo(VariousDefOf.AmountofCreampied, volume);
 | 
					                Pawn.records.AddTo(VariousDefOf.AmountofCreampied, volume);
 | 
				
			||||||
                AfterCumIn(pawn);
 | 
					                AfterCumIn(cummer);
 | 
				
			||||||
                AfterFluidIn(cumd);
 | 
					                AfterFluidIn(cumd);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -884,12 +906,12 @@ namespace RJW_Menstruation
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Inject pawn's fluid into womb
 | 
					        /// Inject pawn's fluid into womb
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <param name="pawn"></param>
 | 
					        /// <param name="cummer"></param>
 | 
				
			||||||
        /// <param name="volume"></param>
 | 
					        /// <param name="volume"></param>
 | 
				
			||||||
        /// <param name="notcumlabel"></param>
 | 
					        /// <param name="notcumlabel"></param>
 | 
				
			||||||
        /// <param name="decayresist"></param>
 | 
					        /// <param name="decayresist"></param>
 | 
				
			||||||
        /// <param name="filthdef"></param>
 | 
					        /// <param name="filthdef"></param>
 | 
				
			||||||
        public void CumIn(Pawn pawn, float volume, string notcumlabel, float decayresist = 0, ThingDef filthdef = null)
 | 
					        public void CumIn(Pawn cummer, float volume, string notcumlabel, float decayresist = 0, ThingDef filthdef = null)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (volume <= 0) return;
 | 
					            if (volume <= 0) return;
 | 
				
			||||||
            float tmp = TotalCum + volume;
 | 
					            float tmp = TotalCum + volume;
 | 
				
			||||||
| 
						 | 
					@ -900,14 +922,14 @@ namespace RJW_Menstruation
 | 
				
			||||||
                bool merged = false;
 | 
					                bool merged = false;
 | 
				
			||||||
                if (!cums.NullOrEmpty()) foreach (Cum cum in cums)
 | 
					                if (!cums.NullOrEmpty()) foreach (Cum cum in cums)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        if (cum.notcum && cum.pawn.Equals(pawn) && cum.notcumLabel.Equals(notcumlabel))
 | 
					                        if (cum.notcum && cum.pawn.Equals(cummer) && cum.notcumLabel.Equals(notcumlabel))
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            cum.MergeWithFluid(volume, decayresist, filthdef);
 | 
					                            cum.MergeWithFluid(volume, decayresist, filthdef);
 | 
				
			||||||
                            merged = true;
 | 
					                            merged = true;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        cum.DismishForce(cumoutrate);
 | 
					                        cum.DismishForce(cumoutrate);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                if (!merged) cums.Add(new Cum(pawn, volume * (1 - cumoutrate), notcumlabel, decayresist, filthdef));
 | 
					                if (!merged) cums.Add(new Cum(cummer, volume * (1 - cumoutrate), notcumlabel, decayresist, filthdef));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
| 
						 | 
					@ -915,13 +937,13 @@ namespace RJW_Menstruation
 | 
				
			||||||
                bool merged = false;
 | 
					                bool merged = false;
 | 
				
			||||||
                if (!cums.NullOrEmpty()) foreach (Cum cum in cums)
 | 
					                if (!cums.NullOrEmpty()) foreach (Cum cum in cums)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        if (cum.notcum && cum.pawn.Equals(pawn) && cum.notcumLabel.Equals(notcumlabel))
 | 
					                        if (cum.notcum && cum.pawn.Equals(cummer) && cum.notcumLabel.Equals(notcumlabel))
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            cum.MergeWithFluid(volume, decayresist, filthdef);
 | 
					                            cum.MergeWithFluid(volume, decayresist, filthdef);
 | 
				
			||||||
                            merged = true;
 | 
					                            merged = true;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                if (!merged) cums.Add(new Cum(pawn, volume, notcumlabel, decayresist, filthdef));
 | 
					                if (!merged) cums.Add(new Cum(cummer, volume, notcumlabel, decayresist, filthdef));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            cumd = TotalCumPercent - cumd;
 | 
					            cumd = TotalCumPercent - cumd;
 | 
				
			||||||
            AfterNotCumIn();
 | 
					            AfterNotCumIn();
 | 
				
			||||||
| 
						 | 
					@ -961,8 +983,8 @@ namespace RJW_Menstruation
 | 
				
			||||||
            absorber = (Absorber)Pawn.apparel?.WornApparel?.Find(x => x is Absorber);
 | 
					            absorber = (Absorber)Pawn.apparel?.WornApparel?.Find(x => x is Absorber);
 | 
				
			||||||
            if (absorber != null)
 | 
					            if (absorber != null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                absorber.WearEffect();
 | 
					                absorber.WearEffect(TickInterval);
 | 
				
			||||||
                if (absorber.dirty && absorber.EffectAfterDirty) absorber.DirtyEffect();
 | 
					                if (absorber.dirty && absorber.EffectAfterDirty) absorber.DirtyEffect(TickInterval);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -994,13 +1016,13 @@ namespace RJW_Menstruation
 | 
				
			||||||
            float leakfactor = 1.0f;
 | 
					            float leakfactor = 1.0f;
 | 
				
			||||||
            float totalleak = 0f;
 | 
					            float totalleak = 0f;
 | 
				
			||||||
            float cumd = TotalCumPercent;
 | 
					            float cumd = TotalCumPercent;
 | 
				
			||||||
 | 
					            int preCumAmount = Mathf.CeilToInt(TotalCum);
 | 
				
			||||||
            List<string> filthlabels = new List<string>();
 | 
					            List<string> filthlabels = new List<string>();
 | 
				
			||||||
            BeforeCumOut(out Absorber absorber);
 | 
					            BeforeCumOut(out Absorber absorber);
 | 
				
			||||||
            if (cums.NullOrEmpty()) return;
 | 
					            if (cums.NullOrEmpty()) return;
 | 
				
			||||||
            if (TotalCum > Props.maxCumCapacity * Pawn.BodySize) leakfactor = Math.Min(1 + (TotalCum - Props.maxCumCapacity * Pawn.BodySize) / 10, 2f);
 | 
					            if (TotalCum > Props.maxCumCapacity * Pawn.BodySize) leakfactor = Math.Min(1 + (TotalCum - Props.maxCumCapacity * Pawn.BodySize) / 10, 2f);
 | 
				
			||||||
            if (absorber != null && absorber.dirty && !absorber.LeakAfterDirty) leakfactor = 0f;
 | 
					            if (absorber != null && absorber.dirty && !absorber.LeakAfterDirty) leakfactor = 0f;
 | 
				
			||||||
            if (Pawn.CurJobDef == xxx.knotted) leakfactor = 0f;
 | 
					            if (Pawn.CurJobDef == xxx.knotted) leakfactor = 0f;
 | 
				
			||||||
            HashSet<Cum> removecums = new HashSet<Cum>();
 | 
					 | 
				
			||||||
            foreach (Cum cum in cums)
 | 
					            foreach (Cum cum in cums)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                cum.CumEffects(Pawn);
 | 
					                cum.CumEffects(Pawn);
 | 
				
			||||||
| 
						 | 
					@ -1009,11 +1031,14 @@ namespace RJW_Menstruation
 | 
				
			||||||
                totalleak += AbsorbCum(vd, absorber);
 | 
					                totalleak += AbsorbCum(vd, absorber);
 | 
				
			||||||
                string tmp = "FilthLabelWithSource".Translate(cum.FilthDef.label, cum.pawn?.LabelShort ?? "Unknown", 1.ToString());
 | 
					                string tmp = "FilthLabelWithSource".Translate(cum.FilthDef.label, cum.pawn?.LabelShort ?? "Unknown", 1.ToString());
 | 
				
			||||||
                filthlabels.Add(tmp.Replace(" x1", ""));
 | 
					                filthlabels.Add(tmp.Replace(" x1", ""));
 | 
				
			||||||
                if (cum.ShouldRemove()) removecums.Add(cum);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            int postCumAmount = Mathf.CeilToInt(TotalCum);
 | 
				
			||||||
 | 
					            for (int i = 0; i < postCumAmount - preCumAmount; i++)  // Emit a filth every time the integer cum amount drops
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
                if (cums.Count > 1) MakeCumFilthMixture(totalleak, filthlabels);
 | 
					                if (cums.Count > 1) MakeCumFilthMixture(totalleak, filthlabels);
 | 
				
			||||||
                else if (cums.Count == 1) MakeCumFilth(cums.First(), totalleak);
 | 
					                else if (cums.Count == 1) MakeCumFilth(cums.First(), totalleak);
 | 
				
			||||||
            cums.RemoveAll(cum => removecums.Contains(cum));
 | 
					            }
 | 
				
			||||||
 | 
					            cums.RemoveAll(cum => cum.ShouldRemove());
 | 
				
			||||||
            cumd = TotalCumPercent - cumd;
 | 
					            cumd = TotalCumPercent - cumd;
 | 
				
			||||||
            if (totalleak >= 1.0f) AfterCumOut();
 | 
					            if (totalleak >= 1.0f) AfterCumOut();
 | 
				
			||||||
            AfterFluidOut(cumd);
 | 
					            AfterFluidOut(cumd);
 | 
				
			||||||
| 
						 | 
					@ -1127,17 +1152,17 @@ namespace RJW_Menstruation
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            InitOvary();
 | 
					            InitOvary();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (currentIntervalHours < 0)
 | 
					            if (currentIntervalTicks < 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (ShouldBeInfertile()) curStage = Stage.Infertile;
 | 
					                if (ShouldBeInfertile()) curStage = Stage.Infertile;
 | 
				
			||||||
                else if (!IsBreedingSeason()) curStage = Stage.Anestrus;
 | 
					                else if (!IsBreedingSeason()) curStage = Stage.Anestrus;
 | 
				
			||||||
                else curStage = RandomStage();
 | 
					                else curStage = RandomStage();
 | 
				
			||||||
                if (curStage == Stage.Follicular)
 | 
					                if (curStage == Stage.Follicular)
 | 
				
			||||||
                    currentIntervalHours = PeriodRandomizer(Stage.Follicular) - PeriodRandomizer(Stage.Bleeding);
 | 
					                    currentIntervalTicks = PeriodRandomizer(Stage.Follicular) - PeriodRandomizer(Stage.Bleeding);
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                    currentIntervalHours = PeriodRandomizer(curStage);
 | 
					                    currentIntervalTicks = PeriodRandomizer(curStage);
 | 
				
			||||||
                if (currentIntervalHours <= 0) currentIntervalHours = 1;
 | 
					                if (currentIntervalTicks < 0) currentIntervalTicks = 0;
 | 
				
			||||||
                else if (currentIntervalHours < curStageHrs) curStageHrs = currentIntervalHours;
 | 
					                else if (currentIntervalTicks < curStageTicks) curStageTicks = currentIntervalTicks;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (crampPain < 0) crampPain = PainRandomizer();
 | 
					            if (crampPain < 0) crampPain = PainRandomizer();
 | 
				
			||||||
            InitializeExtraValues();
 | 
					            InitializeExtraValues();
 | 
				
			||||||
| 
						 | 
					@ -1242,11 +1267,11 @@ namespace RJW_Menstruation
 | 
				
			||||||
            switch (curStage)
 | 
					            switch (curStage)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                case Stage.Follicular:
 | 
					                case Stage.Follicular:
 | 
				
			||||||
                    return curStageHrs > currentIntervalHours - Props.estrusDaysBeforeOvulation * 24;
 | 
					                    return curStageTicks > currentIntervalTicks - Props.estrusDaysBeforeOvulation * GenDate.TicksPerDay;
 | 
				
			||||||
                case Stage.Ovulatory:
 | 
					                case Stage.Ovulatory:
 | 
				
			||||||
                    return true;
 | 
					                    return true;
 | 
				
			||||||
                case Stage.Luteal:
 | 
					                case Stage.Luteal:
 | 
				
			||||||
                    return curStageHrs < EggLifespanHours;
 | 
					                    return curStageTicks < EggLifespanTicks;
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1297,8 +1322,10 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            float totalFertPower = eligibleCum.Sum(cum => cum.FertVolume);
 | 
					            float totalFertPower = eligibleCum.Sum(cum => cum.FertVolume);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (Rand.Chance(Mathf.Pow(1.0f - Configurations.FertilizeChance, totalFertPower * Props.basefertilizationChanceFactor)))
 | 
					            float fertFailChancePerHour = Mathf.Pow(1.0f - Configurations.FertilizeChance, totalFertPower * Props.basefertilizationChanceFactor);
 | 
				
			||||||
                return null;
 | 
					            float fertFailChancePerInterval = Mathf.Pow(fertFailChancePerHour, (float)TickInterval / GenDate.TicksPerHour);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if (Rand.Chance(fertFailChancePerInterval)) return null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Pawn.records.AddTo(VariousDefOf.AmountofFertilizedEggs, 1);
 | 
					            Pawn.records.AddTo(VariousDefOf.AmountofFertilizedEggs, 1);
 | 
				
			||||||
            float selection = Rand.Range(0.0f, totalFertPower);
 | 
					            float selection = Rand.Range(0.0f, totalFertPower);
 | 
				
			||||||
| 
						 | 
					@ -1323,8 +1350,8 @@ namespace RJW_Menstruation
 | 
				
			||||||
            foreach (Egg egg in eggs)
 | 
					            foreach (Egg egg in eggs)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (!egg.fertilized ||
 | 
					                if (!egg.fertilized ||
 | 
				
			||||||
                    egg.fertstage < minImplantAgeHours ||
 | 
					                    egg.ticksSinceFertilization < minImplantAgeHours * GenDate.TicksPerHour ||
 | 
				
			||||||
                    egg.position < Math.Min(Props.lutealIntervalDays * 24 / 2, maxImplantDelayHours))
 | 
					                    egg.ageTicks < Math.Min(Props.lutealIntervalDays * GenDate.TicksPerDay / 2, maxImplantDelayHours * GenDate.TicksPerHour))
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                else if (egg.fertilizer == null)
 | 
					                else if (egg.fertilizer == null)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
| 
						 | 
					@ -1408,8 +1435,8 @@ namespace RJW_Menstruation
 | 
				
			||||||
                        if (pregnancy is Hediff_BasePregnancy rjw_preg)
 | 
					                        if (pregnancy is Hediff_BasePregnancy rjw_preg)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            // TODO: advance biotech pregnancy
 | 
					                            // TODO: advance biotech pregnancy
 | 
				
			||||||
                            rjw_preg.p_start_tick -= egg.fertstage / Configurations.CycleAcceleration * GenDate.TicksPerHour;
 | 
					                            rjw_preg.p_start_tick -= egg.ticksSinceFertilization / Configurations.CycleAcceleration;
 | 
				
			||||||
                            rjw_preg.p_end_tick -= egg.fertstage / Configurations.CycleAcceleration * GenDate.TicksPerHour;
 | 
					                            rjw_preg.p_end_tick -= egg.ticksSinceFertilization / Configurations.CycleAcceleration;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -1434,7 +1461,9 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected void BleedOut()
 | 
					        protected void BleedOut()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            CumIn(Pawn, Rand.Range(0.02f * Configurations.BleedingAmount, 0.04f * Configurations.BleedingAmount), Translations.Menstrual_Blood, -5.0f, Pawn.def.race?.BloodDef ?? ThingDefOf.Filth_Blood);
 | 
					            // ~1.5 per hour times acceleration
 | 
				
			||||||
 | 
					            float bledAmount = 0.03f * Configurations.BleedingAmount * Configurations.CycleAcceleration * Rand.Range(0.5f, 1.5f) * TickInterval / GenDate.TicksPerHour;
 | 
				
			||||||
 | 
					            CumIn(Pawn, bledAmount, Translations.Menstrual_Blood, -5.0f, Pawn.def.race?.BloodDef ?? ThingDefOf.Filth_Blood);
 | 
				
			||||||
            Cum blood = GetNotCum(Translations.Menstrual_Blood);
 | 
					            Cum blood = GetNotCum(Translations.Menstrual_Blood);
 | 
				
			||||||
            if (blood != null) blood.Color = BloodColor;
 | 
					            if (blood != null) blood.Color = BloodColor;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1501,12 +1530,12 @@ namespace RJW_Menstruation
 | 
				
			||||||
            HashSet<Egg> deadeggs = new HashSet<Egg>();
 | 
					            HashSet<Egg> deadeggs = new HashSet<Egg>();
 | 
				
			||||||
            foreach (Egg egg in eggs)
 | 
					            foreach (Egg egg in eggs)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                egg.position += Configurations.CycleAcceleration;
 | 
					                egg.ageTicks += TickInterval * Configurations.CycleAcceleration;
 | 
				
			||||||
                if (egg.fertilized) egg.fertstage += Configurations.CycleAcceleration;
 | 
					                if (egg.fertilized) egg.ticksSinceFertilization += TickInterval * Configurations.CycleAcceleration;
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    egg.lifespanhrs -= Configurations.CycleAcceleration;
 | 
					                    egg.lifeSpanTicks -= TickInterval * Configurations.CycleAcceleration;
 | 
				
			||||||
                    if (egg.lifespanhrs < 0) deadeggs.Add(egg);
 | 
					                    if (egg.lifeSpanTicks < 0) deadeggs.Add(egg);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            eggs.RemoveAll(egg => deadeggs.Contains(egg));
 | 
					            eggs.RemoveAll(egg => deadeggs.Contains(egg));
 | 
				
			||||||
| 
						 | 
					@ -1517,7 +1546,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
            Hediff hediff = HediffMaker.MakeHediff(VariousDefOf.Hediff_MenstrualCramp, Pawn);
 | 
					            Hediff hediff = HediffMaker.MakeHediff(VariousDefOf.Hediff_MenstrualCramp, Pawn);
 | 
				
			||||||
            hediff.Severity = crampPain * Rand.Range(0.9f, 1.1f);
 | 
					            hediff.Severity = crampPain * Rand.Range(0.9f, 1.1f);
 | 
				
			||||||
            HediffCompProperties_SeverityPerDay Prop = (HediffCompProperties_SeverityPerDay)hediff.TryGetComp<HediffComp_SeverityPerDay>().props;
 | 
					            HediffCompProperties_SeverityPerDay Prop = (HediffCompProperties_SeverityPerDay)hediff.TryGetComp<HediffComp_SeverityPerDay>().props;
 | 
				
			||||||
            Prop.severityPerDay = -hediff.Severity / (currentIntervalHours / 24) * Configurations.CycleAcceleration;
 | 
					            Prop.severityPerDay = -hediff.Severity / (currentIntervalTicks / GenDate.TicksPerDay) * Configurations.CycleAcceleration;
 | 
				
			||||||
            Pawn.health.AddHediff(hediff, Genital_Helper.get_genitalsBPR(Pawn));
 | 
					            Pawn.health.AddHediff(hediff, Genital_Helper.get_genitalsBPR(Pawn));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1529,14 +1558,14 @@ namespace RJW_Menstruation
 | 
				
			||||||
                GoNextStage(Stage.Anestrus);
 | 
					                GoNextStage(Stage.Anestrus);
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (curStageHrs >= currentIntervalHours)
 | 
					            else if (curStageTicks >= currentIntervalTicks)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                GoOvulatoryStage();
 | 
					                GoOvulatoryStage();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                curStageHrs += Configurations.CycleAcceleration;
 | 
					                curStageTicks += TickInterval * Configurations.CycleAcceleration;
 | 
				
			||||||
                if (!estrusflag && curStageHrs > currentIntervalHours - Props.estrusDaysBeforeOvulation * 24)
 | 
					                if (!estrusflag && curStageTicks > currentIntervalTicks - Props.estrusDaysBeforeOvulation * GenDate.TicksPerDay)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    estrusflag = true;
 | 
					                    estrusflag = true;
 | 
				
			||||||
                    SetEstrus();
 | 
					                    SetEstrus();
 | 
				
			||||||
| 
						 | 
					@ -1547,6 +1576,11 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected virtual void OvulatoryAction()
 | 
					        protected virtual void OvulatoryAction()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            if (curStageTicks < currentIntervalTicks)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                curStageTicks += TickInterval * Configurations.CycleAcceleration;
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            estrusflag = false;
 | 
					            estrusflag = false;
 | 
				
			||||||
            float eggnum;
 | 
					            float eggnum;
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
| 
						 | 
					@ -1570,7 +1604,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
            for (int i = 0; i < toOvulate; i++)
 | 
					            for (int i = 0; i < toOvulate; i++)
 | 
				
			||||||
                if (i < eggstack || Rand.Chance(ovulationChance))   // eggstack comes from drugs and are guaranteed ovulated
 | 
					                if (i < eggstack || Rand.Chance(ovulationChance))   // eggstack comes from drugs and are guaranteed ovulated
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    eggs.Add(new Egg((int)(EggLifespanHours / CycleFactor)));
 | 
					                    eggs.Add(new Egg((int)(EggLifespanTicks / CycleFactor)));
 | 
				
			||||||
                    ++ovulated;
 | 
					                    ++ovulated;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            ovarypower -= ovulated;
 | 
					            ovarypower -= ovulated;
 | 
				
			||||||
| 
						 | 
					@ -1583,7 +1617,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected virtual void LutealAction()
 | 
					        protected virtual void LutealAction()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (curStageHrs >= currentIntervalHours)
 | 
					            if (curStageTicks >= currentIntervalTicks)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                eggs.Clear();
 | 
					                eggs.Clear();
 | 
				
			||||||
                if (EggHealth < 1f / 4f || (EggHealth < 1f / 3f && Rand.Chance(0.3f))) //skips bleeding
 | 
					                if (EggHealth < 1f / 4f || (EggHealth < 1f / 3f && Rand.Chance(0.3f))) //skips bleeding
 | 
				
			||||||
| 
						 | 
					@ -1605,13 +1639,13 @@ namespace RJW_Menstruation
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    curStageHrs += Configurations.CycleAcceleration;
 | 
					                    curStageTicks += TickInterval * Configurations.CycleAcceleration;
 | 
				
			||||||
                    StayCurrentStage();
 | 
					                    StayCurrentStage();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                curStageHrs += Configurations.CycleAcceleration;
 | 
					                curStageTicks += TickInterval * Configurations.CycleAcceleration;
 | 
				
			||||||
                StayCurrentStage();
 | 
					                StayCurrentStage();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1619,23 +1653,23 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected virtual void BleedingAction()
 | 
					        protected virtual void BleedingAction()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (curStageHrs >= currentIntervalHours)
 | 
					            if (curStageTicks >= currentIntervalTicks)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Hediff hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_MenstrualCramp);
 | 
					                Hediff hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_MenstrualCramp);
 | 
				
			||||||
                if (hediff != null && !Pawn.GetMenstruationComps().Any(comp => comp != this && comp.curStage == Stage.Bleeding)) Pawn.health.RemoveHediff(hediff);
 | 
					                if (hediff != null && !Pawn.GetMenstruationComps().Any(comp => comp != this && comp.curStage == Stage.Bleeding)) Pawn.health.RemoveHediff(hediff);
 | 
				
			||||||
                int totalFollicularHours = PeriodRandomizer(Stage.Follicular);  // The total amount of time for both bleeding and follicular
 | 
					                int totalFollicularTicks = PeriodRandomizer(Stage.Follicular);  // The total amount of time for both bleeding and follicular
 | 
				
			||||||
                if (totalFollicularHours <= currentIntervalHours)   // We've bled for so long that we completely missed the follicular phase
 | 
					                if (totalFollicularTicks <= currentIntervalTicks)   // We've bled for so long that we completely missed the follicular phase
 | 
				
			||||||
                    GoOvulatoryStage();
 | 
					                    GoOvulatoryStage();
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    currentIntervalHours = totalFollicularHours - currentIntervalHours; // I.e., the remaining follicular hours equals the total minus the bleeding hours elapsed
 | 
					                    currentIntervalTicks = totalFollicularTicks - currentIntervalTicks; // I.e., the remaining follicular time equals the total minus the bleeding time elapsed
 | 
				
			||||||
                    GoNextStage(Stage.Follicular, false);
 | 
					                    GoNextStage(Stage.Follicular, false);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (curStageHrs < currentIntervalHours / 4) for (int i = 0; i < Configurations.CycleAcceleration; i++) BleedOut();
 | 
					                if (curStageTicks < currentIntervalTicks / 4) BleedOut();
 | 
				
			||||||
                curStageHrs += Configurations.CycleAcceleration;
 | 
					                curStageTicks += TickInterval * Configurations.CycleAcceleration;
 | 
				
			||||||
                StayCurrentStage();
 | 
					                StayCurrentStage();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1651,7 +1685,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (pregnancy != null && Pawn.health.hediffSet.hediffs.Contains(pregnancy))
 | 
					            if (pregnancy != null && Pawn.health.hediffSet.hediffs.Contains(pregnancy))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                curStageHrs += 1;
 | 
					                curStageTicks += TickInterval;
 | 
				
			||||||
                StayCurrentStageConst(Stage.Pregnant);
 | 
					                StayCurrentStageConst(Stage.Pregnant);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
| 
						 | 
					@ -1663,7 +1697,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected virtual void RecoverAction()
 | 
					        protected virtual void RecoverAction()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (curStageHrs >= currentIntervalHours)
 | 
					            if (curStageTicks >= currentIntervalTicks)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (ShouldBeInfertile())
 | 
					                if (ShouldBeInfertile())
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
| 
						 | 
					@ -1680,7 +1714,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                curStageHrs += Configurations.CycleAcceleration;
 | 
					                curStageTicks += TickInterval * Configurations.CycleAcceleration;
 | 
				
			||||||
                StayCurrentStage();
 | 
					                StayCurrentStage();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -1776,8 +1810,8 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void GoNextStage(Stage nextstage, bool calculateHours = true)
 | 
					        public void GoNextStage(Stage nextstage, bool calculateHours = true)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            curStageHrs = 0;
 | 
					            curStageTicks = 0;
 | 
				
			||||||
            if (calculateHours) currentIntervalHours = PeriodRandomizer(nextstage);
 | 
					            if (calculateHours) currentIntervalTicks = PeriodRandomizer(nextstage);
 | 
				
			||||||
            curStage = nextstage;
 | 
					            curStage = nextstage;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1819,15 +1853,17 @@ namespace RJW_Menstruation
 | 
				
			||||||
            switch (stage)
 | 
					            switch (stage)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                case Stage.Follicular:
 | 
					                case Stage.Follicular:
 | 
				
			||||||
                    return (int)(Props.follicularIntervalDays * 24 * (1 + Rand.Range(-cycleVariability, cycleVariability) * 1.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 1.5f));
 | 
					                    return (int)(Props.follicularIntervalDays * GenDate.TicksPerDay * (1 + Rand.Range(-cycleVariability, cycleVariability) * 1.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 1.5f));
 | 
				
			||||||
 | 
					                case Stage.Ovulatory:
 | 
				
			||||||
 | 
					                    return Props.ovulationIntervalHours * GenDate.TicksPerHour; // No variability for now
 | 
				
			||||||
                case Stage.Luteal:
 | 
					                case Stage.Luteal:
 | 
				
			||||||
                    return (int)(Props.lutealIntervalDays * 24 * (1 + Rand.Range(-cycleVariability, cycleVariability) * 0.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 0.5f));
 | 
					                    return (int)(Props.lutealIntervalDays * GenDate.TicksPerDay * (1 + Rand.Range(-cycleVariability, cycleVariability) * 0.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 0.5f));
 | 
				
			||||||
                case Stage.Bleeding:
 | 
					                case Stage.Bleeding:
 | 
				
			||||||
                    return (int)(Props.bleedingIntervalDays * 24 * (1 + Rand.Range(-cycleVariability, cycleVariability) * 0.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 0.5f));
 | 
					                    return (int)(Props.bleedingIntervalDays * GenDate.TicksPerDay * (1 + Rand.Range(-cycleVariability, cycleVariability) * 0.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 0.5f));
 | 
				
			||||||
                case Stage.Recover:
 | 
					                case Stage.Recover:
 | 
				
			||||||
                    return (int)(Props.recoveryIntervalDays * 24 * Rand.Range(0.95f, 1.05f));
 | 
					                    return (int)(Props.recoveryIntervalDays * GenDate.TicksPerDay * Rand.Range(0.95f, 1.05f));
 | 
				
			||||||
                case Stage.Pregnant:
 | 
					                case Stage.Pregnant:
 | 
				
			||||||
                    return (int)MenstruationUtility.GestationHours(pregnancy);
 | 
					                    return (int)(MenstruationUtility.GestationHours(pregnancy) * GenDate.TicksPerHour);
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    return 1;
 | 
					                    return 1;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1863,13 +1899,13 @@ namespace RJW_Menstruation
 | 
				
			||||||
            switch (stage)
 | 
					            switch (stage)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                case Stage.Follicular:
 | 
					                case Stage.Follicular:
 | 
				
			||||||
                    curStageHrs = Rand.Range(0, (Props.follicularIntervalDays - Props.bleedingIntervalDays) * 24);
 | 
					                    curStageTicks = Rand.Range(0, (Props.follicularIntervalDays - Props.bleedingIntervalDays) * GenDate.TicksPerDay);
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                case Stage.Luteal:
 | 
					                case Stage.Luteal:
 | 
				
			||||||
                    curStageHrs = Rand.Range(0, Props.lutealIntervalDays * 24);
 | 
					                    curStageTicks = Rand.Range(0, Props.lutealIntervalDays * GenDate.TicksPerDay);
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                case Stage.Bleeding:
 | 
					                case Stage.Bleeding:
 | 
				
			||||||
                    curStageHrs = Rand.Range(0, Props.bleedingIntervalDays * 24);
 | 
					                    curStageTicks = Rand.Range(0, Props.bleedingIntervalDays * GenDate.TicksPerDay);
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return stage;
 | 
					            return stage;
 | 
				
			||||||
| 
						 | 
					@ -1915,34 +1951,46 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public class Egg : IExposable
 | 
					        public class Egg : IExposable
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            public bool fertilized;
 | 
					            public bool fertilized;
 | 
				
			||||||
            public int lifespanhrs;
 | 
					            public int lifeSpanTicks;
 | 
				
			||||||
            public Pawn fertilizer;
 | 
					            public Pawn fertilizer;
 | 
				
			||||||
            public int position;
 | 
					            public int ageTicks;
 | 
				
			||||||
            public int fertstage = 0;
 | 
					            public int ticksSinceFertilization = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            public Egg()
 | 
					            public Egg()
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                fertilized = false;
 | 
					                fertilized = false;
 | 
				
			||||||
                lifespanhrs = (int)(96 * Configurations.EggLifespanMultiplier);
 | 
					                lifeSpanTicks = (int)(96 * GenDate.TicksPerHour * Configurations.EggLifespanMultiplier);
 | 
				
			||||||
                fertilizer = null;
 | 
					                fertilizer = null;
 | 
				
			||||||
                position = 0;
 | 
					                ageTicks = 0;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            public Egg(int lifespanhrs)
 | 
					            public Egg(int lifespanhrs)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                fertilized = false;
 | 
					                fertilized = false;
 | 
				
			||||||
                this.lifespanhrs = (int)(lifespanhrs * Configurations.EggLifespanMultiplier);
 | 
					                lifeSpanTicks = (int)(lifespanhrs * GenDate.TicksPerHour * Configurations.EggLifespanMultiplier);
 | 
				
			||||||
                fertilizer = null;
 | 
					                fertilizer = null;
 | 
				
			||||||
                position = 0;
 | 
					                ageTicks = 0;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            public void ExposeData()
 | 
					            public void ExposeData()
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Scribe_References.Look(ref fertilizer, "fertilizer", true);
 | 
					                if (Scribe.mode == LoadSaveMode.LoadingVars)
 | 
				
			||||||
                Scribe_Values.Look(ref fertilized, "fertilized", fertilized, true);
 | 
					                {
 | 
				
			||||||
 | 
					                    int lifespanhrs = -1;
 | 
				
			||||||
 | 
					                    int position = -1;
 | 
				
			||||||
 | 
					                    int fertstage = -1;
 | 
				
			||||||
                    Scribe_Values.Look(ref lifespanhrs, "lifespanhrs", lifespanhrs, true);
 | 
					                    Scribe_Values.Look(ref lifespanhrs, "lifespanhrs", lifespanhrs, true);
 | 
				
			||||||
                    Scribe_Values.Look(ref position, "position", position, true);
 | 
					                    Scribe_Values.Look(ref position, "position", position, true);
 | 
				
			||||||
                    Scribe_Values.Look(ref fertstage, "fertstage", fertstage, true);
 | 
					                    Scribe_Values.Look(ref fertstage, "fertstage", fertstage, true);
 | 
				
			||||||
 | 
					                    if (lifespanhrs >= 0) lifeSpanTicks = lifespanhrs * GenDate.TicksPerHour;
 | 
				
			||||||
 | 
					                    if (position >= 0) ageTicks = position * GenDate.TicksPerHour;
 | 
				
			||||||
 | 
					                    if (fertstage >= 0) ticksSinceFertilization = fertstage * GenDate.TicksPerHour;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Scribe_References.Look(ref fertilizer, "fertilizer", true);
 | 
				
			||||||
 | 
					                Scribe_Values.Look(ref fertilized, "fertilized", fertilized, true);
 | 
				
			||||||
 | 
					                Scribe_Values.Look(ref lifeSpanTicks, "lifeSpanTicks", lifeSpanTicks, true);
 | 
				
			||||||
 | 
					                Scribe_Values.Look(ref ageTicks, "ageTicks", ageTicks, true);
 | 
				
			||||||
 | 
					                Scribe_Values.Look(ref ticksSinceFertilization, "ticksSinceFertilization", ticksSinceFertilization, true);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,8 +16,8 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class HediffComp_PeriodicOvulator : HediffComp_Menstruation
 | 
					    public class HediffComp_PeriodicOvulator : HediffComp_Menstruation
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public int hoursToNextCycle = -100000;
 | 
					        public int ticksToNextCycle = -100000;
 | 
				
			||||||
        public int averageCycleIntervalHours = -1;
 | 
					        public int averageCycleIntervalTicks = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public new CompProperties_PeriodicOvulator Props;
 | 
					        public new CompProperties_PeriodicOvulator Props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,14 +25,14 @@ namespace RJW_Menstruation
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            base.InitializeExtraValues();
 | 
					            base.InitializeExtraValues();
 | 
				
			||||||
            Props = (CompProperties_PeriodicOvulator)props;
 | 
					            Props = (CompProperties_PeriodicOvulator)props;
 | 
				
			||||||
            if (averageCycleIntervalHours < 0)
 | 
					            if (averageCycleIntervalTicks < 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                averageCycleIntervalHours = (int)(24f * Props.cycleIntervalDays.RandomInRange / cycleSpeed);
 | 
					                averageCycleIntervalTicks = (int)(Props.cycleIntervalDays.RandomInRange * GenDate.TicksPerDay / cycleSpeed);
 | 
				
			||||||
                if (hoursToNextCycle < -50000)
 | 
					                if (ticksToNextCycle < -50000)
 | 
				
			||||||
                    hoursToNextCycle = Rand.Range(0, averageCycleIntervalHours);
 | 
					                    ticksToNextCycle = Rand.Range(0, averageCycleIntervalTicks);
 | 
				
			||||||
                // Make the cutoff halfway into cycle, just to be sure there isn't a double-cycle the first time
 | 
					                // Make the cutoff halfway into cycle, just to be sure there isn't a double-cycle the first time
 | 
				
			||||||
                if ((curStage == Stage.Follicular || curStage == Stage.Luteal || curStage == Stage.Bleeding)
 | 
					                if ((curStage == Stage.Follicular || curStage == Stage.Luteal || curStage == Stage.Bleeding)
 | 
				
			||||||
                    && (averageCycleIntervalHours - hoursToNextCycle) / 2 >= 24 * (Props.follicularIntervalDays + Props.lutealIntervalDays) / cycleSpeed)
 | 
					                    && (averageCycleIntervalTicks - ticksToNextCycle) / 2 >= GenDate.TicksPerDay * (Props.follicularIntervalDays + Props.lutealIntervalDays) / cycleSpeed)
 | 
				
			||||||
                    GoNextStage(Stage.Anestrus);
 | 
					                    GoNextStage(Stage.Anestrus);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -41,31 +41,40 @@ namespace RJW_Menstruation
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // Don't bother trying to work seasonal breeding into the math
 | 
					            // Don't bother trying to work seasonal breeding into the math
 | 
				
			||||||
            // Due to the enormous variation in possible cycle gaps, cheat and base it off the individual
 | 
					            // Due to the enormous variation in possible cycle gaps, cheat and base it off the individual
 | 
				
			||||||
            return averageCycleIntervalHours * cycleSpeed / (24 * 360); // cancel out their cycleSpeed from initialization to get their "normal" speed
 | 
					            return averageCycleIntervalTicks * cycleSpeed / GenDate.TicksPerYear; // cancel out their cycleSpeed from initialization to get their "normal" speed
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override void BeforeSimulator()
 | 
					        protected override void BeforeSimulator()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            base.BeforeSimulator();
 | 
					            base.BeforeSimulator();
 | 
				
			||||||
            if (hoursToNextCycle > 0) hoursToNextCycle -= Configurations.CycleAcceleration;
 | 
					            if (ticksToNextCycle > 0) ticksToNextCycle -= TickInterval * Configurations.CycleAcceleration;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public override void CompExposeData()
 | 
					        public override void CompExposeData()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            base.CompExposeData();
 | 
					            base.CompExposeData();
 | 
				
			||||||
 | 
					            if (Scribe.mode == LoadSaveMode.LoadingVars)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                int hoursToNextCycle = -1;
 | 
				
			||||||
 | 
					                int averageCycleIntervalHours = -1;
 | 
				
			||||||
                Scribe_Values.Look(ref hoursToNextCycle, "hoursToNextCycle", hoursToNextCycle, true);
 | 
					                Scribe_Values.Look(ref hoursToNextCycle, "hoursToNextCycle", hoursToNextCycle, true);
 | 
				
			||||||
                Scribe_Values.Look(ref averageCycleIntervalHours, "averageCycleIntervalHours", averageCycleIntervalHours, true);
 | 
					                Scribe_Values.Look(ref averageCycleIntervalHours, "averageCycleIntervalHours", averageCycleIntervalHours, true);
 | 
				
			||||||
 | 
					                if (hoursToNextCycle >= 0) ticksToNextCycle = hoursToNextCycle * GenDate.TicksPerHour;
 | 
				
			||||||
 | 
					                if (averageCycleIntervalHours >= 0) averageCycleIntervalTicks = averageCycleIntervalHours * GenDate.TicksPerHour;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Scribe_Values.Look(ref ticksToNextCycle, "ticksToNextCycle", ticksToNextCycle, true);
 | 
				
			||||||
 | 
					            Scribe_Values.Look(ref averageCycleIntervalTicks, "averageCycleIntervalTicks", averageCycleIntervalTicks, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override int HoursToNextStage()
 | 
					        protected override int TicksToNextStage()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (curStage == Stage.Anestrus &&  hoursToNextCycle > 0) return hoursToNextCycle / Configurations.CycleAcceleration;
 | 
					            if (curStage == Stage.Anestrus &&  ticksToNextCycle > 0) return ticksToNextCycle / Configurations.CycleAcceleration;
 | 
				
			||||||
            else return base.HoursToNextStage();
 | 
					            else return base.TicksToNextStage();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override void BleedingAction()
 | 
					        protected override void BleedingAction()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (curStageHrs >= currentIntervalHours)
 | 
					            if (curStageTicks >= currentIntervalTicks)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Hediff hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_MenstrualCramp);
 | 
					                Hediff hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_MenstrualCramp);
 | 
				
			||||||
                if (hediff != null && !Pawn.GetMenstruationComps().Any(comp => comp != this && comp.curStage == Stage.Bleeding)) Pawn.health.RemoveHediff(hediff);
 | 
					                if (hediff != null && !Pawn.GetMenstruationComps().Any(comp => comp != this && comp.curStage == Stage.Bleeding)) Pawn.health.RemoveHediff(hediff);
 | 
				
			||||||
| 
						 | 
					@ -81,14 +90,14 @@ namespace RJW_Menstruation
 | 
				
			||||||
            base.PregnantAction();
 | 
					            base.PregnantAction();
 | 
				
			||||||
            if (curStage != Stage.Pregnant)
 | 
					            if (curStage != Stage.Pregnant)
 | 
				
			||||||
                // Go halfway into the cycle
 | 
					                // Go halfway into the cycle
 | 
				
			||||||
                hoursToNextCycle = (int)(averageCycleIntervalHours * (1 + Rand.Range(-cycleVariability, cycleVariability))) / 2;
 | 
					                ticksToNextCycle = (int)(averageCycleIntervalTicks * (1 + Rand.Range(-cycleVariability, cycleVariability))) / 2;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override void AnestrusAction()
 | 
					        protected override void AnestrusAction()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (hoursToNextCycle <= 0)
 | 
					            if (ticksToNextCycle <= 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                hoursToNextCycle = (int)(averageCycleIntervalHours * (1 + Rand.Range(-cycleVariability, cycleVariability)));
 | 
					                ticksToNextCycle = (int)(averageCycleIntervalTicks * (1 + Rand.Range(-cycleVariability, cycleVariability)));
 | 
				
			||||||
                if (IsBreedingSeason()) GoNextStage(Stage.Follicular);
 | 
					                if (IsBreedingSeason()) GoNextStage(Stage.Follicular);
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -99,7 +108,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            base.CopyCycleProperties(original);
 | 
					            base.CopyCycleProperties(original);
 | 
				
			||||||
            if (original is HediffComp_PeriodicOvulator comp)
 | 
					            if (original is HediffComp_PeriodicOvulator comp)
 | 
				
			||||||
                averageCycleIntervalHours = comp.averageCycleIntervalHours;
 | 
					                averageCycleIntervalTicks = comp.averageCycleIntervalTicks;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -219,6 +219,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public static Texture2D GetEggIcon(this HediffComp_Menstruation comp, bool includeOvary)
 | 
					        public static Texture2D GetEggIcon(this HediffComp_Menstruation comp, bool includeOvary)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            float ovulationChance = comp.OvulationChance;
 | 
				
			||||||
            const float ovaryChanceToShow_01 = 0.4f;
 | 
					            const float ovaryChanceToShow_01 = 0.4f;
 | 
				
			||||||
            const float ovaryChanceToShow_02 = 1.0f;
 | 
					            const float ovaryChanceToShow_02 = 1.0f;
 | 
				
			||||||
            switch (comp.CurrentVisibleStage)
 | 
					            switch (comp.CurrentVisibleStage)
 | 
				
			||||||
| 
						 | 
					@ -231,28 +232,28 @@ namespace RJW_Menstruation
 | 
				
			||||||
                            job.Sexprops != null &&
 | 
					                            job.Sexprops != null &&
 | 
				
			||||||
                            !job.Sexprops.usedCondom &&
 | 
					                            !job.Sexprops.usedCondom &&
 | 
				
			||||||
                            (job.Sexprops.sexType == xxx.rjwSextype.Vaginal || job.Sexprops.sexType == xxx.rjwSextype.DoublePenetration))
 | 
					                            (job.Sexprops.sexType == xxx.rjwSextype.Vaginal || job.Sexprops.sexType == xxx.rjwSextype.DoublePenetration))
 | 
				
			||||||
                            return ContentFinder<Texture2D>.Get((comp.OvulationChance >= ovaryChanceToShow_01) ? "Ovaries/Ovary_01" : "Ovaries/Ovary_00", true);
 | 
					                            return ContentFinder<Texture2D>.Get((ovulationChance >= ovaryChanceToShow_01) ? "Ovaries/Ovary_01" : "Ovaries/Ovary_00", true);
 | 
				
			||||||
                        else break;
 | 
					                        else break;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    if (comp.curStageHrs > comp.CurStageIntervalHours - 30)   // Approximate time for ovulation to occur
 | 
					                    if (comp.curStageTicks > comp.CurStageIntervalTicks - 30 * GenDate.TicksPerHour)   // Approximate time for ovulation to occur
 | 
				
			||||||
                        return ContentFinder<Texture2D>.Get((comp.OvulationChance >= ovaryChanceToShow_01) ? "Ovaries/Ovary_01" : "Ovaries/Ovary_00", true);
 | 
					                        return ContentFinder<Texture2D>.Get((ovulationChance >= ovaryChanceToShow_01) ? "Ovaries/Ovary_01" : "Ovaries/Ovary_00", true);
 | 
				
			||||||
                    else break;
 | 
					                    else break;
 | 
				
			||||||
                case HediffComp_Menstruation.Stage.Ovulatory:
 | 
					                case HediffComp_Menstruation.Stage.Ovulatory:
 | 
				
			||||||
                    if (!includeOvary) break;
 | 
					                    if (!includeOvary) break;
 | 
				
			||||||
                    if (comp.OvulationChance >= ovaryChanceToShow_02)
 | 
					                    if (ovulationChance >= ovaryChanceToShow_02)
 | 
				
			||||||
                        return ContentFinder<Texture2D>.Get("Ovaries/Ovary_02", true);
 | 
					                        return ContentFinder<Texture2D>.Get("Ovaries/Ovary_02", true);
 | 
				
			||||||
                    else if (comp.OvulationChance >= ovaryChanceToShow_01)
 | 
					                    else if (ovulationChance >= ovaryChanceToShow_01)
 | 
				
			||||||
                        return ContentFinder<Texture2D>.Get("Ovaries/Ovary_01", true);
 | 
					                        return ContentFinder<Texture2D>.Get("Ovaries/Ovary_01", true);
 | 
				
			||||||
                    else
 | 
					                    else
 | 
				
			||||||
                        return ContentFinder<Texture2D>.Get("Ovaries/Ovary_00", true);
 | 
					                        return ContentFinder<Texture2D>.Get("Ovaries/Ovary_00", true);
 | 
				
			||||||
                case HediffComp_Menstruation.Stage.Luteal:
 | 
					                case HediffComp_Menstruation.Stage.Luteal:
 | 
				
			||||||
                    if (!comp.IsEggExist) break;
 | 
					                    if (!comp.IsEggExist) break;
 | 
				
			||||||
                    int fertstage = comp.IsFertilized;
 | 
					                    int fertTime = comp.EggFertilizedTime;
 | 
				
			||||||
                    if (fertstage >= 0)
 | 
					                    if (fertTime >= 0)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        if (fertstage <= Configurations.CycleAcceleration) return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilizing02", true);
 | 
					                        if (fertTime <= GenDate.TicksPerHour * Configurations.CycleAcceleration) return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilizing02", true);
 | 
				
			||||||
                        else if (fertstage <= 18) return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilized00", true);
 | 
					                        else if (fertTime <= 18 * GenDate.TicksPerHour) return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilized00", true);
 | 
				
			||||||
                        else if (fertstage <= 54) return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilized01", true);
 | 
					                        else if (fertTime <= 54 * GenDate.TicksPerHour) return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilized01", true);
 | 
				
			||||||
                        else return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilized02", true);
 | 
					                        else return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilized02", true);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else if (comp.IsEggFertilizing)
 | 
					                    else if (comp.IsEggFertilizing)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
using HarmonyLib;
 | 
					using HarmonyLib;
 | 
				
			||||||
 | 
					using RimWorld;
 | 
				
			||||||
using rjw;
 | 
					using rjw;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
| 
						 | 
					@ -47,7 +48,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
            if (Configurations.Debug)
 | 
					            if (Configurations.Debug)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                description
 | 
					                description
 | 
				
			||||||
                    .AppendFormat("{0}: {1}\n", comp.curStage, comp.curStageHrs);
 | 
					                    .AppendFormat("{0}: {1}\n", comp.curStage, comp.curStageTicks / GenDate.TicksPerHour);
 | 
				
			||||||
                if (comp.Pregnancy is Hediff_BasePregnancy rjwpreg) description
 | 
					                if (comp.Pregnancy is Hediff_BasePregnancy rjwpreg) description
 | 
				
			||||||
                    .AppendFormat("due: {0}\n", rjwpreg.DueDate());
 | 
					                    .AppendFormat("due: {0}\n", rjwpreg.DueDate());
 | 
				
			||||||
                else if (comp.Pregnancy is Hediff_Pregnant biopreg) description
 | 
					                else if (comp.Pregnancy is Hediff_Pregnant biopreg) description
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -197,7 +197,8 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public float absorbedfluids = 0;
 | 
					        public float absorbedfluids = 0;
 | 
				
			||||||
        public bool dirty = false;
 | 
					        public bool dirty = false;
 | 
				
			||||||
        public int wearhours = 0;
 | 
					        public int wearTicks = 0;
 | 
				
			||||||
 | 
					        protected virtual float PassiveAbsorptionPerHour => 0.1f;
 | 
				
			||||||
        public virtual bool LeakAfterDirty => def.GetModExtension<AbsorberModExtension>().leakAfterDirty;
 | 
					        public virtual bool LeakAfterDirty => def.GetModExtension<AbsorberModExtension>().leakAfterDirty;
 | 
				
			||||||
        public virtual bool EffectAfterDirty => def.GetModExtension<AbsorberModExtension>().effectsAfterDirty;
 | 
					        public virtual bool EffectAfterDirty => def.GetModExtension<AbsorberModExtension>().effectsAfterDirty;
 | 
				
			||||||
        public virtual ThingDef DirtyDef => def.GetModExtension<AbsorberModExtension>().dirtyDef;
 | 
					        public virtual ThingDef DirtyDef => def.GetModExtension<AbsorberModExtension>().dirtyDef;
 | 
				
			||||||
| 
						 | 
					@ -205,12 +206,12 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Color fluidColor = Color.white;
 | 
					        public Color fluidColor = Color.white;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public virtual void DirtyEffect() { }
 | 
					        public virtual void DirtyEffect(int tickInterval) { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public virtual void WearEffect()
 | 
					        public virtual void WearEffect(int tickInterval)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            absorbedfluids += 0.1f;
 | 
					            absorbedfluids += PassiveAbsorptionPerHour * tickInterval / GenDate.TicksPerHour;
 | 
				
			||||||
            if (dirty) wearhours++;
 | 
					            if (dirty) wearTicks += tickInterval;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public override Color DrawColorTwo => fluidColor;
 | 
					        public override Color DrawColorTwo => fluidColor;
 | 
				
			||||||
| 
						 | 
					@ -218,9 +219,15 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public override void ExposeData()
 | 
					        public override void ExposeData()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            base.ExposeData();
 | 
					            base.ExposeData();
 | 
				
			||||||
 | 
					            if(Scribe.mode == LoadSaveMode.LoadingVars)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                int wearhours = -1;
 | 
				
			||||||
 | 
					                Scribe_Values.Look(ref wearhours, "wearhours", wearhours, true);
 | 
				
			||||||
 | 
					                if (wearhours >= 0) wearTicks = wearhours * GenDate.TicksPerHour;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            Scribe_Values.Look(ref absorbedfluids, "absorbedfluids", absorbedfluids, true);
 | 
					            Scribe_Values.Look(ref absorbedfluids, "absorbedfluids", absorbedfluids, true);
 | 
				
			||||||
            Scribe_Values.Look(ref dirty, "dirty", dirty, true);
 | 
					            Scribe_Values.Look(ref dirty, "dirty", dirty, true);
 | 
				
			||||||
            Scribe_Values.Look(ref wearhours, "wearhours", wearhours, true);
 | 
					            Scribe_Values.Look(ref wearTicks, "wearTicks", wearTicks, true);
 | 
				
			||||||
            Scribe_Values.Look(ref fluidColor, "fluidColor", fluidColor, true);
 | 
					            Scribe_Values.Look(ref fluidColor, "fluidColor", fluidColor, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -228,16 +235,11 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class Absorber_Tampon : Absorber
 | 
					    public class Absorber_Tampon : Absorber
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        protected override float PassiveAbsorptionPerHour => 0.5f;
 | 
				
			||||||
        public override void WearEffect()
 | 
					        public override void DirtyEffect(int tickInterval)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (dirty) wearhours++;
 | 
					 | 
				
			||||||
            absorbedfluids += 0.5f;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public override void DirtyEffect()
 | 
					            if (wearTicks > MinHrstoDirtyEffect * GenDate.TicksPerHour && Rand.MTBEventOccurs(100.0f, GenDate.TicksPerHour, tickInterval) && !Wearer.apparel.IsLocked(this))
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (wearhours > MinHrstoDirtyEffect && Rand.Chance(0.01f) && !Wearer.apparel.IsLocked(this))
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Wearer.health.AddHediff(HediffDefOf.WoundInfection, Genital_Helper.get_genitalsBPR(Wearer));
 | 
					                Wearer.health.AddHediff(HediffDefOf.WoundInfection, Genital_Helper.get_genitalsBPR(Wearer));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,6 +60,12 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public static readonly string Option6_Desc = "Option6_Desc".Translate();
 | 
					        public static readonly string Option6_Desc = "Option6_Desc".Translate();
 | 
				
			||||||
        public static readonly string Option7_Label = "Option7_Label".Translate();
 | 
					        public static readonly string Option7_Label = "Option7_Label".Translate();
 | 
				
			||||||
        public static readonly string Option7_Desc = "Option7_Desc".Translate();
 | 
					        public static readonly string Option7_Desc = "Option7_Desc".Translate();
 | 
				
			||||||
 | 
					        public static readonly string Option_ColonistUpdateInterval_Label = "Option_ColonistUpdateInterval_Label".Translate();
 | 
				
			||||||
 | 
					        public static readonly string Option_ColonistUpdateInterval_Desc = "Option_ColonistUpdateInterval_Desc".Translate();
 | 
				
			||||||
 | 
					        public static readonly string Option_NonColonistUpdateInterval_Label = "Option_NonColonistUpdateInterval_Label".Translate();
 | 
				
			||||||
 | 
					        public static readonly string Option_NonColonistUpdateInterval_Desc = "Option_NonColonistUpdateInterval_Desc".Translate();
 | 
				
			||||||
 | 
					        public static readonly string Option_AnimalUpdateInterval_Label = "Option_AnimalUpdateInterval_Label".Translate();
 | 
				
			||||||
 | 
					        public static readonly string Option_AnimalUpdateInterval_Desc = "Option_AnimalUpdateInterval_Desc".Translate();
 | 
				
			||||||
        public static readonly string Option8_Label = "Option8_Label".Translate();
 | 
					        public static readonly string Option8_Label = "Option8_Label".Translate();
 | 
				
			||||||
        public static readonly string Option8_Desc = "Option8_Desc".Translate();
 | 
					        public static readonly string Option8_Desc = "Option8_Desc".Translate();
 | 
				
			||||||
        public static readonly string Option9_Label = "Option9_Label".Translate();
 | 
					        public static readonly string Option9_Label = "Option9_Label".Translate();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
Version 1.0.9.0
 | 
					Version 1.0.9.0
 | 
				
			||||||
 - Fix errors when opening the womb dialog of some low fertility pawns.
 | 
					 - Fix errors when opening the womb dialog of some low fertility pawns.
 | 
				
			||||||
 - Updated Traditional Chinese translation by Hydrogen.
 | 
					 - Updated Traditional Chinese translation by Hydrogen.
 | 
				
			||||||
 | 
					 - New options to update wombs more or less often, defaulting to every hour.
 | 
				
			||||||
 - Menstruation-related genes will now stay on females during initial pawn setup.
 | 
					 - Menstruation-related genes will now stay on females during initial pawn setup.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Version 1.0.8.9
 | 
					Version 1.0.8.9
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue