mirror of
				https://gitgud.io/lutepickle/rjw_menstruation.git
				synced 2024-08-14 22:46:52 +00:00 
			
		
		
		
	Merge branch 'dev'
This commit is contained in:
		
						commit
						4fdd66989b
					
				
					 19 changed files with 338 additions and 121 deletions
				
			
		
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -225,7 +225,20 @@
 | 
				
			||||||
			</li>
 | 
								</li>
 | 
				
			||||||
		</stages>
 | 
							</stages>
 | 
				
			||||||
	</ThoughtDef>
 | 
						</ThoughtDef>
 | 
				
			||||||
	
 | 
					
 | 
				
			||||||
	
 | 
						<ThoughtDef MayRequire="Ludeon.Rimworld.Ideology">
 | 
				
			||||||
 | 
							<defName>EggRestorationReceived</defName>
 | 
				
			||||||
 | 
							<thoughtClass>Thought_Memory</thoughtClass>
 | 
				
			||||||
 | 
							<durationDays>4</durationDays>
 | 
				
			||||||
 | 
							<stackLimit>1</stackLimit>
 | 
				
			||||||
 | 
							<stages>
 | 
				
			||||||
 | 
								<li>
 | 
				
			||||||
 | 
									<label>egg restoration received</label>
 | 
				
			||||||
 | 
									<description>I can breed for a little longer now.</description>
 | 
				
			||||||
 | 
									<baseMoodEffect>2</baseMoodEffect>
 | 
				
			||||||
 | 
								</li>
 | 
				
			||||||
 | 
							</stages>
 | 
				
			||||||
 | 
						</ThoughtDef>
 | 
				
			||||||
 | 
							
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
</Defs>
 | 
					</Defs>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,7 @@
 | 
				
			||||||
  <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>
 | 
				
			||||||
  <Option8_Label>Debug</Option8_Label>
 | 
					  <Option8_Label>Debug</Option8_Label>
 | 
				
			||||||
  <Option8_Desc>Show debug information.
Also overrides "Fetus information level" to All.</Option8_Desc>
 | 
					  <Option8_Desc>Show debug information.</Option8_Desc>
 | 
				
			||||||
  <Option9_Label>Womb status</Option9_Label>
 | 
					  <Option9_Label>Womb status</Option9_Label>
 | 
				
			||||||
  <Option9_Desc>Draw womb icon in status window.</Option9_Desc>
 | 
					  <Option9_Desc>Draw womb icon in status window.</Option9_Desc>
 | 
				
			||||||
  <Option10_Label>Vagina and breast status</Option10_Label>
 | 
					  <Option10_Label>Vagina and breast status</Option10_Label>
 | 
				
			||||||
| 
						 | 
					@ -68,7 +68,7 @@
 | 
				
			||||||
  <Option11_Desc_3>Show only image of a fetus after discovered pregnancy.</Option11_Desc_3>
 | 
					  <Option11_Desc_3>Show only image of a fetus after discovered pregnancy.</Option11_Desc_3>
 | 
				
			||||||
  <Option11_Desc_4>Do not show any information about a fetus.</Option11_Desc_4>
 | 
					  <Option11_Desc_4>Do not show any information about a fetus.</Option11_Desc_4>
 | 
				
			||||||
  <Option12_Label>Enable menopause</Option12_Label>
 | 
					  <Option12_Label>Enable menopause</Option12_Label>
 | 
				
			||||||
  <Option12_Desc>Enable menopause effect that makes pawn infertile in time progress
If you have problems with long life races, turn off this option.</Option12_Desc>
 | 
					  <Option12_Desc>Enable menopause effect that makes pawn infertile when they run out of eggs
If you have problems with long lived races, turn off this option.</Option12_Desc>
 | 
				
			||||||
  <Option13_Label>Use multiple pregnancy</Option13_Label>
 | 
					  <Option13_Label>Use multiple pregnancy</Option13_Label>
 | 
				
			||||||
  <Option13_Desc>Use multiple pregnancy instead RJW's default pregnancy
Disable this option if you are in trouble with impregnation
RJW pregnancy should be turned on.</Option13_Desc>
 | 
					  <Option13_Desc>Use multiple pregnancy instead RJW's default pregnancy
Disable this option if you are in trouble with impregnation
RJW pregnancy should be turned on.</Option13_Desc>
 | 
				
			||||||
  <Option14_Label>Enable hetero ovular twins</Option14_Label>
 | 
					  <Option14_Label>Enable hetero ovular twins</Option14_Label>
 | 
				
			||||||
| 
						 | 
					@ -136,5 +136,7 @@
 | 
				
			||||||
  <CustomHybrid_Tooltip>When {0} breed with {1}, {2} will be born at {3} chance.
If both races have hybrid definitions for each other, the father's definition will be used.</CustomHybrid_Tooltip>
 | 
					  <CustomHybrid_Tooltip>When {0} breed with {1}, {2} will be born at {3} chance.
If both races have hybrid definitions for each other, the father's definition will be used.</CustomHybrid_Tooltip>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <CannotNoEggs>No eggs</CannotNoEggs>
 | 
					  <CannotNoEggs>No eggs</CannotNoEggs>
 | 
				
			||||||
 | 
					  <CannotNoWomb>Must have a womb</CannotNoWomb>
 | 
				
			||||||
 | 
					  <EggRestorationCompleted>{PAWN_labelShort} has completed {PAWN_possessive} egg restoration cycle.</EggRestorationCompleted>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
</LanguageData>
 | 
					</LanguageData>
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										24
									
								
								1.4/Patches/Biosculpter_Patch.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								1.4/Patches/Biosculpter_Patch.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,24 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" encoding="utf-8" ?>
 | 
				
			||||||
 | 
					<Patch>
 | 
				
			||||||
 | 
						<Operation Class="PatchOperationFindMod">
 | 
				
			||||||
 | 
							<mods>
 | 
				
			||||||
 | 
								<li>Ideology</li>
 | 
				
			||||||
 | 
							</mods>
 | 
				
			||||||
 | 
							<match Class="PatchOperationAdd">
 | 
				
			||||||
 | 
								<xpath>/Defs/ThingDef[defName="BiosculpterPod"]/comps</xpath>
 | 
				
			||||||
 | 
								<value>
 | 
				
			||||||
 | 
									<li Class="RJW_Menstruation.CompProperties_BiosculpterPod_EggRestorationCycle">
 | 
				
			||||||
 | 
										<key>eggRestoration</key>
 | 
				
			||||||
 | 
										<label>egg restoration</label>
 | 
				
			||||||
 | 
										<description>Restore one year worth of eggs in each womb.</description>
 | 
				
			||||||
 | 
										<iconPath>UI/Icon/EggRegeneration</iconPath>
 | 
				
			||||||
 | 
										<durationDays>4</durationDays>
 | 
				
			||||||
 | 
										<!--Apparently the game is hardcoded to give the age reversal thought to anything with gainThoughtOnCompletion-->
 | 
				
			||||||
 | 
										<!--<gainThoughtOnCompletion>EggRestorationReceived</gainThoughtOnCompletion>-->
 | 
				
			||||||
 | 
										<operatingColor>(0.867, 0.373, 0.396)</operatingColor>
 | 
				
			||||||
 | 
										<yearsToRestore>1.0</yearsToRestore>
 | 
				
			||||||
 | 
									</li>
 | 
				
			||||||
 | 
								</value>
 | 
				
			||||||
 | 
							</match>
 | 
				
			||||||
 | 
						</Operation>
 | 
				
			||||||
 | 
					</Patch>
 | 
				
			||||||
| 
						 | 
					@ -30,6 +30,28 @@
 | 
				
			||||||
			</comps>
 | 
								</comps>
 | 
				
			||||||
		</value>
 | 
							</value>
 | 
				
			||||||
	</Operation>
 | 
						</Operation>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<!--<Operation Class="PatchOperationAdd">
 | 
				
			||||||
 | 
							<xpath>/Defs/rjw.HediffDef_PartBase[defName="DogVagina"]</xpath>
 | 
				
			||||||
 | 
							<value>
 | 
				
			||||||
 | 
								<comps>
 | 
				
			||||||
 | 
									<li Class="RJW_Menstruation.CompProperties_PeriodicOvulator">
 | 
				
			||||||
 | 
										<maxCumCapacity>8</maxCumCapacity>
 | 
				
			||||||
 | 
										<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
 | 
				
			||||||
 | 
										<basefertilizationChanceFactor>1.0</basefertilizationChanceFactor>
 | 
				
			||||||
 | 
										<follicularIntervalDays>14</follicularIntervalDays>
 | 
				
			||||||
 | 
										<lutealIntervalDays>36</lutealIntervalDays>
 | 
				
			||||||
 | 
										<bleedingIntervalDays>8</bleedingIntervalDays>
 | 
				
			||||||
 | 
										<recoveryIntervalDays>15</recoveryIntervalDays>
 | 
				
			||||||
 | 
										<eggLifespanDays>4</eggLifespanDays>
 | 
				
			||||||
 | 
										<wombTex>Womb/Womb</wombTex>
 | 
				
			||||||
 | 
										<vagTex>Genitals/Vagina</vagTex>
 | 
				
			||||||
 | 
										<estrusDaysBeforeOvulation>9</estrusDaysBeforeOvulation>
 | 
				
			||||||
 | 
										<cycleIntervalDays>180~360</cycleIntervalDays>
 | 
				
			||||||
 | 
									</li>
 | 
				
			||||||
 | 
								</comps>
 | 
				
			||||||
 | 
							</value>
 | 
				
			||||||
 | 
						</Operation>-->
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	<Operation Class="PatchOperationAdd">
 | 
						<Operation Class="PatchOperationAdd">
 | 
				
			||||||
		<xpath>/Defs/rjw.HediffDef_PartBase[defName="CatVagina"]</xpath>
 | 
							<xpath>/Defs/rjw.HediffDef_PartBase[defName="CatVagina"]</xpath>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								1.4/Textures/UI/Icon/EggRegeneration.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								1.4/Textures/UI/Icon/EggRegeneration.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 25 KiB  | 
| 
						 | 
					@ -0,0 +1,27 @@
 | 
				
			||||||
 | 
					using RimWorld;
 | 
				
			||||||
 | 
					using Verse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace RJW_Menstruation
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class CompProperties_BiosculpterPod_EggRestorationCycle : CompProperties_BiosculpterPod_BaseCycle
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public CompProperties_BiosculpterPod_EggRestorationCycle()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            compClass = typeof(CompBiosculpterPod_EggRestorationCycle);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public float yearsToRestore;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class CompBiosculpterPod_EggRestorationCycle : CompBiosculpterPod_Cycle
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public override void CycleCompleted(Pawn occupant)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            foreach (HediffComp_Menstruation comp in occupant.GetMenstruationComps())
 | 
				
			||||||
 | 
					                comp.RestoreEggs(((CompProperties_BiosculpterPod_EggRestorationCycle)Props).yearsToRestore);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Messages.Message(Translations.EggRestorationCompleted(occupant.Named("PAWN")), occupant, MessageTypeDefOf.PositiveEvent);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -246,8 +246,14 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected void CalculateBreastSize()
 | 
					        protected void CalculateBreastSize()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // Scenario A: the youngest child is less than halfway into babyhood: Full size
 | 
					            // Ageless pawns can't depend on the chrono age, so just disable their growth entirely
 | 
				
			||||||
            if (ageOfLastBirth + BabyHalfAge * GenDate.TicksPerYear > Pawn.ageTracker.AgeBiologicalTicks)
 | 
					            if (Pawn.ageTracker.BiologicalTicksPerTick <= 0f && breastSizeIncreased > 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ShrinkBreasts();
 | 
				
			||||||
 | 
					                debugGrowthStatus = "Base size (ageless)";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // The youngest child is less than halfway into babyhood: Full size
 | 
				
			||||||
 | 
					            else if (ageOfLastBirth + BabyHalfAge * GenDate.TicksPerYear > Pawn.ageTracker.AgeBiologicalTicks)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                debugGrowthStatus = "Full size due to young child";
 | 
					                debugGrowthStatus = "Full size due to young child";
 | 
				
			||||||
                if (breastSizeIncreased < MaxBreastIncrement)
 | 
					                if (breastSizeIncreased < MaxBreastIncrement)
 | 
				
			||||||
| 
						 | 
					@ -256,7 +262,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                    breastSizeIncreased = MaxBreastIncrement;
 | 
					                    breastSizeIncreased = MaxBreastIncrement;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            // Scenario B: Pregnant, grow in the second half of first trimester
 | 
					            // Pregnant, grow in the second half of first trimester
 | 
				
			||||||
            else if (Pawn.IsRJWPregnant() || Pawn.IsBiotechPregnant())
 | 
					            else if (Pawn.IsRJWPregnant() || Pawn.IsBiotechPregnant())
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                float pregnancySize = Mathf.InverseLerp(breastGrowthStart, breastGrowthEnd, Pawn.GetFarthestPregnancyProgress()) * MaxBreastIncrement;
 | 
					                float pregnancySize = Mathf.InverseLerp(breastGrowthStart, breastGrowthEnd, Pawn.GetFarthestPregnancyProgress()) * MaxBreastIncrement;
 | 
				
			||||||
| 
						 | 
					@ -279,7 +285,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else debugGrowthStatus = "Pregnant and full size";
 | 
					                else debugGrowthStatus = "Pregnant and full size";
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            // Scenario C: Not (or very early) pregnant and youngest child nonexistent or more than halfway into babyhood, time to shrink
 | 
					            // Not (or very early) pregnant and youngest child nonexistent or more than halfway into babyhood, time to shrink
 | 
				
			||||||
            else if (breastSizeIncreased > 0)
 | 
					            else if (breastSizeIncreased > 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                debugGrowthStatus = "Shrinking due to no pregnancy nor young child";
 | 
					                debugGrowthStatus = "Shrinking due to no pregnancy nor young child";
 | 
				
			||||||
| 
						 | 
					@ -291,7 +297,9 @@ namespace RJW_Menstruation
 | 
				
			||||||
        protected void CalculateNipples()
 | 
					        protected void CalculateNipples()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            float newNippleProgress;
 | 
					            float newNippleProgress;
 | 
				
			||||||
            if (ageOfLastBirth + BabyHalfAge * GenDate.TicksPerYear > Pawn.ageTracker.AgeBiologicalTicks)
 | 
					            if (Pawn.ageTracker.BiologicalTicksPerTick <= 0f)
 | 
				
			||||||
 | 
					                newNippleProgress = 0f;
 | 
				
			||||||
 | 
					            else if (ageOfLastBirth + BabyHalfAge * GenDate.TicksPerYear > Pawn.ageTracker.AgeBiologicalTicks)
 | 
				
			||||||
                newNippleProgress = 1f;
 | 
					                newNippleProgress = 1f;
 | 
				
			||||||
            else if (Pawn.IsRJWPregnant() || Pawn.IsBiotechPregnant())
 | 
					            else if (Pawn.IsRJWPregnant() || Pawn.IsBiotechPregnant())
 | 
				
			||||||
                newNippleProgress = nippleTransitions.Evaluate(Pawn.GetFarthestPregnancyProgress());
 | 
					                newNippleProgress = nippleTransitions.Evaluate(Pawn.GetFarthestPregnancyProgress());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,6 +68,8 @@ namespace RJW_Menstruation
 | 
				
			||||||
        const int tickInterval = GenDate.TicksPerHour;
 | 
					        const int tickInterval = GenDate.TicksPerHour;
 | 
				
			||||||
        const int maxImplantDelayHours = 30 * 24;
 | 
					        const int maxImplantDelayHours = 30 * 24;
 | 
				
			||||||
        const int minImplantAgeHours = 3 * 24;
 | 
					        const int minImplantAgeHours = 3 * 24;
 | 
				
			||||||
 | 
					        const float pulloutSuccessRate = 0.8f;
 | 
				
			||||||
 | 
					        const float fetishPulloutSuccessModifier = 0.25f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public CompProperties_Menstruation Props;
 | 
					        public CompProperties_Menstruation Props;
 | 
				
			||||||
        public Stage curStage = Stage.Follicular;
 | 
					        public Stage curStage = Stage.Follicular;
 | 
				
			||||||
| 
						 | 
					@ -637,7 +639,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                    curStage = Stage.Pregnant;
 | 
					                    curStage = Stage.Pregnant;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                CumOut();
 | 
					                BeforeSimulator();
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                if (pregnancy == null && (Pawn.health.capacities.GetLevel(xxx.reproduction) <= 0 || EggHealth <= 0 || Pawn.SterileGenes())) curStage = Stage.Infertile;
 | 
					                if (pregnancy == null && (Pawn.health.capacities.GetLevel(xxx.reproduction) <= 0 || EggHealth <= 0 || Pawn.SterileGenes())) curStage = Stage.Infertile;
 | 
				
			||||||
                switch (curStage)
 | 
					                switch (curStage)
 | 
				
			||||||
| 
						 | 
					@ -735,10 +737,17 @@ namespace RJW_Menstruation
 | 
				
			||||||
        /// <param name="pawn"></param>
 | 
					        /// <param name="pawn"></param>
 | 
				
			||||||
        /// <param name="volume"></param>
 | 
					        /// <param name="volume"></param>
 | 
				
			||||||
        /// <param name="fertility"></param>
 | 
					        /// <param name="fertility"></param>
 | 
				
			||||||
        /// <param name="filthdef"></param>
 | 
					        /// <param name="precum"></param>
 | 
				
			||||||
        public void CumIn(Pawn pawn, float volume, float fertility = 1.0f, ThingDef filthdef = null)
 | 
					        public void CumIn(Pawn pawn, 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)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                float successChance = pulloutSuccessRate;
 | 
				
			||||||
 | 
					                if (pawn.Has(Quirk.ImpregnationFetish)) successChance *= fetishPulloutSuccessModifier;
 | 
				
			||||||
 | 
					                if (Pawn.Has(Quirk.ImpregnationFetish)) successChance *= fetishPulloutSuccessModifier;
 | 
				
			||||||
 | 
					                if (Rand.Chance(successChance)) return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            if (Pawn.HasIUD()) fertility /= 100f;
 | 
					            if (Pawn.HasIUD()) fertility /= 100f;
 | 
				
			||||||
            float cumd = TotalCumPercent;
 | 
					            float cumd = TotalCumPercent;
 | 
				
			||||||
            float tmp = TotalCum + volume;
 | 
					            float tmp = TotalCum + volume;
 | 
				
			||||||
| 
						 | 
					@ -750,12 +759,12 @@ namespace RJW_Menstruation
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        if (cum.pawn.Equals(pawn))
 | 
					                        if (cum.pawn.Equals(pawn))
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            cum.MergeWithCum(volume, fertility, filthdef);
 | 
					                            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, filthdef));
 | 
					                if (!merged) cums.Add(new Cum(pawn, volume * (1 - cumoutrate), fertility));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
| 
						 | 
					@ -765,17 +774,20 @@ namespace RJW_Menstruation
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        if (cum.pawn.Equals(pawn))
 | 
					                        if (cum.pawn.Equals(pawn))
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            cum.MergeWithCum(volume, fertility, filthdef);
 | 
					                            cum.MergeWithCum(volume, fertility);
 | 
				
			||||||
                            merged = true;
 | 
					                            merged = true;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                if (!merged) cums.Add(new Cum(pawn, volume, fertility, filthdef));
 | 
					                if (!merged) cums.Add(new Cum(pawn, volume, fertility));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            cumd = TotalCumPercent - cumd;
 | 
					            cumd = TotalCumPercent - cumd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Pawn.records.AddTo(VariousDefOf.AmountofCreampied, volume);
 | 
					            if (!precum)
 | 
				
			||||||
            AfterCumIn(pawn);
 | 
					            {
 | 
				
			||||||
            AfterFluidIn(cumd);
 | 
					                Pawn.records.AddTo(VariousDefOf.AmountofCreampied, volume);
 | 
				
			||||||
 | 
					                AfterCumIn(pawn);
 | 
				
			||||||
 | 
					                AfterFluidIn(cumd);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
| 
						 | 
					@ -1041,6 +1053,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                else if (currentIntervalHours < curStageHrs) curStageHrs = currentIntervalHours;
 | 
					                else if (currentIntervalHours < curStageHrs) curStageHrs = currentIntervalHours;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (crampPain < 0) crampPain = PainRandomizer();
 | 
					            if (crampPain < 0) crampPain = PainRandomizer();
 | 
				
			||||||
 | 
					            InitializeExtraValues();
 | 
				
			||||||
            if (cums == null) cums = new List<Cum>();
 | 
					            if (cums == null) cums = new List<Cum>();
 | 
				
			||||||
            if (eggs == null) eggs = new List<Egg>();
 | 
					            if (eggs == null) eggs = new List<Egg>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1053,6 +1066,10 @@ namespace RJW_Menstruation
 | 
				
			||||||
            initError = false;
 | 
					            initError = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected virtual void InitializeExtraValues()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected virtual float RaceCyclesPerYear()
 | 
					        protected virtual float RaceCyclesPerYear()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            int breedingSeasons = 0;
 | 
					            int breedingSeasons = 0;
 | 
				
			||||||
| 
						 | 
					@ -1118,8 +1135,12 @@ namespace RJW_Menstruation
 | 
				
			||||||
            ovarypower = Math.Max(0, (int)(ovarypower * multiply));
 | 
					            ovarypower = Math.Max(0, (int)(ovarypower * multiply));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected virtual void BeforeSimulator()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            CumOut();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected void AfterSimulator()
 | 
					        protected virtual void AfterSimulator()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (EggHealth < 1f)
 | 
					            if (EggHealth < 1f)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
| 
						 | 
					@ -1468,7 +1489,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected virtual void LutealAction()
 | 
					        protected virtual void LutealAction()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (curStageHrs > currentIntervalHours)
 | 
					            if (curStageHrs >= currentIntervalHours)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                eggs.Clear();
 | 
					                eggs.Clear();
 | 
				
			||||||
                if (EggHealth < 1f / 4f || (EggHealth < 1f / 3f && Rand.Range(0.0f, 1.0f) < 0.3f)) //skips bleeding
 | 
					                if (EggHealth < 1f / 4f || (EggHealth < 1f / 3f && Rand.Range(0.0f, 1.0f) < 0.3f)) //skips bleeding
 | 
				
			||||||
| 
						 | 
					@ -1507,7 +1528,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
            if (curStageHrs >= currentIntervalHours)
 | 
					            if (curStageHrs >= currentIntervalHours)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Hediff hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_MenstrualCramp);
 | 
					                Hediff hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_MenstrualCramp);
 | 
				
			||||||
                if (hediff != null) 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 totalFollicularHours = 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 (totalFollicularHours <= currentIntervalHours)   // We've bled for so long that we completely missed the follicular phase
 | 
				
			||||||
                    GoOvulatoryStage();
 | 
					                    GoOvulatoryStage();
 | 
				
			||||||
| 
						 | 
					@ -1784,7 +1805,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                GoNextStage(Stage.Pregnant);
 | 
					                GoNextStage(Stage.Pregnant);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void CopyCycleProperties(HediffComp_Menstruation original)
 | 
					        public virtual void CopyCycleProperties(HediffComp_Menstruation original)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            cycleSpeed = original.cycleSpeed;
 | 
					            cycleSpeed = original.cycleSpeed;
 | 
				
			||||||
            cycleVariability = original.cycleVariability;
 | 
					            cycleVariability = original.cycleVariability;
 | 
				
			||||||
| 
						 | 
					@ -1792,6 +1813,16 @@ namespace RJW_Menstruation
 | 
				
			||||||
            crampPain = original.crampPain;
 | 
					            crampPain = original.crampPain;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public int EggsRestoredPerBiosculptor(float yearsWorth)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return Math.Max(1, (int)((float)RaceCyclesPerYear() * yearsWorth));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void RestoreEggs(float yearsWorth)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ovarypower += EggsRestoredPerBiosculptor(yearsWorth);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public class Egg : IExposable
 | 
					        public class Egg : IExposable
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            public bool fertilized;
 | 
					            public bool fertilized;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,99 @@
 | 
				
			||||||
 | 
					using RimWorld;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using Verse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace RJW_Menstruation
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class CompProperties_PeriodicOvulator : CompProperties_Menstruation
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public FloatRange cycleIntervalDays; // From the start of one cycle to the start of the next
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public CompProperties_PeriodicOvulator()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            compClass = typeof(HediffComp_PeriodicOvulator);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class HediffComp_PeriodicOvulator : HediffComp_Menstruation
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public int hoursToNextCycle = -100000;
 | 
				
			||||||
 | 
					        public int averageCycleIntervalHours = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public new CompProperties_PeriodicOvulator Props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override void InitializeExtraValues()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            base.InitializeExtraValues();
 | 
				
			||||||
 | 
					            Props = (CompProperties_PeriodicOvulator)props;
 | 
				
			||||||
 | 
					            if (averageCycleIntervalHours < 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                averageCycleIntervalHours = (int)(24f * Props.cycleIntervalDays.RandomInRange / cycleSpeed);
 | 
				
			||||||
 | 
					                if (hoursToNextCycle < -50000)
 | 
				
			||||||
 | 
					                    hoursToNextCycle = Rand.Range(0, averageCycleIntervalHours);
 | 
				
			||||||
 | 
					                // 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)
 | 
				
			||||||
 | 
					                    && (averageCycleIntervalHours - hoursToNextCycle) / 2 >= 24 * (Props.follicularIntervalDays + Props.lutealIntervalDays) / cycleSpeed)
 | 
				
			||||||
 | 
					                    curStage = Stage.Anestrus;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override float RaceCyclesPerYear()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // 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
 | 
				
			||||||
 | 
					            return averageCycleIntervalHours * cycleSpeed / (24 * 360); // cancel out their cycleSpeed from initialization to get their "normal" speed
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override void BeforeSimulator()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            base.BeforeSimulator();
 | 
				
			||||||
 | 
					            if (hoursToNextCycle > 0) hoursToNextCycle -= Configurations.CycleAcceleration;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public override void CompExposeData()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            base.CompExposeData();
 | 
				
			||||||
 | 
					            Scribe_Values.Look(ref hoursToNextCycle, "hoursToNextCycle", hoursToNextCycle, true);
 | 
				
			||||||
 | 
					            Scribe_Values.Look(ref averageCycleIntervalHours, "averageCycleIntervalHours", averageCycleIntervalHours, true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override void BleedingAction()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (curStageHrs >= currentIntervalHours)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                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);
 | 
				
			||||||
 | 
					                estrusflag = false;
 | 
				
			||||||
 | 
					                GoNextStage(Stage.Anestrus);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else base.BleedingAction();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override void PregnantAction()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            base.PregnantAction();
 | 
				
			||||||
 | 
					            if (curStage != Stage.Pregnant)
 | 
				
			||||||
 | 
					                // Go halfway into the cycle
 | 
				
			||||||
 | 
					                hoursToNextCycle = (int)(averageCycleIntervalHours * Rand.Range(-cycleVariability, cycleVariability)) / 2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override void AnestrusAction()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (hoursToNextCycle <= 0)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                hoursToNextCycle = (int)(averageCycleIntervalHours * Rand.Range(-cycleVariability, cycleVariability));
 | 
				
			||||||
 | 
					                if (IsBreedingSeason()) GoNextStage(Stage.Follicular);
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            StayCurrentStage();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public override void CopyCycleProperties(HediffComp_Menstruation original)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            base.CopyCycleProperties(original);
 | 
				
			||||||
 | 
					            if (original is HediffComp_PeriodicOvulator comp)
 | 
				
			||||||
 | 
					                averageCycleIntervalHours = comp.averageCycleIntervalHours;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,10 @@
 | 
				
			||||||
using RimWorld;
 | 
					using RimWorld;
 | 
				
			||||||
using rjw;
 | 
					using rjw;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Reflection;
 | 
				
			||||||
using System.Text;
 | 
					using System.Text;
 | 
				
			||||||
using UnityEngine;
 | 
					 | 
				
			||||||
using Verse;
 | 
					using Verse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace RJW_Menstruation
 | 
					namespace RJW_Menstruation
 | 
				
			||||||
| 
						 | 
					@ -12,6 +13,9 @@ namespace RJW_Menstruation
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        protected Dictionary<Pawn, Pawn> enzygoticSiblings = new Dictionary<Pawn, Pawn>();  // Each pawn and who they split from
 | 
					        protected Dictionary<Pawn, Pawn> enzygoticSiblings = new Dictionary<Pawn, Pawn>();  // Each pawn and who they split from
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected readonly MethodInfo TryGetInheritedXenotype = typeof(PregnancyUtility).GetMethod("TryGetInheritedXenotype", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(Pawn), typeof(Pawn), typeof(XenotypeDef).MakeByRefType() }, null );
 | 
				
			||||||
 | 
					        protected readonly MethodInfo ShouldByHybrid = typeof(PregnancyUtility).GetMethod("ShouldByHybrid", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(Pawn), typeof(Pawn) }, null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public override void DiscoverPregnancy()
 | 
					        public override void DiscoverPregnancy()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            PregnancyThought();
 | 
					            PregnancyThought();
 | 
				
			||||||
| 
						 | 
					@ -160,6 +164,21 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (xxx.is_human(mother)) TaleRecorder.RecordTale(TaleDefOf.GaveBirth, new object[] { mother, baby });
 | 
					            if (xxx.is_human(mother)) TaleRecorder.RecordTale(TaleDefOf.GaveBirth, new object[] { mother, baby });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (ModsConfig.BiotechActive)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // Ugly, but it'll have to do
 | 
				
			||||||
 | 
					                OutcomeChance bestOutcome = RitualOutcomeEffectDefOf.ChildBirth.outcomeChances.Find(chance => chance.positivityIndex == 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                string label = bestOutcome.label;
 | 
				
			||||||
 | 
					                string description = bestOutcome.description.Formatted(mother.Named("MOTHER"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                ChoiceLetter_BabyBirth choiceLetter_BabyBirth = (ChoiceLetter_BabyBirth)LetterMaker.MakeLetter(
 | 
				
			||||||
 | 
					                    label, description, LetterDefOf.BabyBirth, baby
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                choiceLetter_BabyBirth.Start();
 | 
				
			||||||
 | 
					                Find.LetterStack.ReceiveLetter(choiceLetter_BabyBirth);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            PostBirth(mother, father, baby);
 | 
					            PostBirth(mother, father, baby);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -416,9 +435,13 @@ namespace RJW_Menstruation
 | 
				
			||||||
                        baby.genes.xenotypeName = mother.genes.xenotypeName;
 | 
					                        baby.genes.xenotypeName = mother.genes.xenotypeName;
 | 
				
			||||||
                        baby.genes.iconDef = mother.genes.iconDef;
 | 
					                        baby.genes.iconDef = mother.genes.iconDef;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    XenotypeDef xenoTypeDef = BabyXenoTypeDecider(mother, father, out bool hybridBaby);
 | 
					
 | 
				
			||||||
                    if (xenoTypeDef != null) baby.genes.SetXenotypeDirect(xenoTypeDef);
 | 
					                    object[] args = new object[] { mother, father, null };
 | 
				
			||||||
                    if (hybridBaby)
 | 
					                    if ((bool)TryGetInheritedXenotype.Invoke(null, args))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        baby.genes.SetXenotypeDirect((XenotypeDef)args[2]);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else if((bool)ShouldByHybrid.Invoke(null, new object[] { mother, father }))
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        baby.genes.hybrid = true;
 | 
					                        baby.genes.hybrid = true;
 | 
				
			||||||
                        baby.genes.xenotypeName = "Hybrid".Translate();
 | 
					                        baby.genes.xenotypeName = "Hybrid".Translate();
 | 
				
			||||||
| 
						 | 
					@ -623,39 +646,6 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public XenotypeDef BabyXenoTypeDecider(Pawn mother, Pawn father, out bool hybrid)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            hybrid = false;
 | 
					 | 
				
			||||||
            bool hybridMother = mother?.genes?.hybrid ?? false;
 | 
					 | 
				
			||||||
            bool hybridFather = father?.genes?.hybrid ?? false;
 | 
					 | 
				
			||||||
            if (hybridMother && hybridFather)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                hybrid = true;
 | 
					 | 
				
			||||||
                return null;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            XenotypeDef motherInheritableXenotype = mother?.genes?.Xenotype;
 | 
					 | 
				
			||||||
            XenotypeDef fatherInheritableXenotype = father?.genes?.Xenotype;
 | 
					 | 
				
			||||||
            if (!(motherInheritableXenotype?.inheritable ?? false)) motherInheritableXenotype = null;
 | 
					 | 
				
			||||||
            if (!(fatherInheritableXenotype?.inheritable ?? false)) fatherInheritableXenotype = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // If they're the same (or both null)
 | 
					 | 
				
			||||||
            if (motherInheritableXenotype == fatherInheritableXenotype)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                // Both null, but one's a hybrid
 | 
					 | 
				
			||||||
                if (motherInheritableXenotype == null && (hybridMother || hybridFather))
 | 
					 | 
				
			||||||
                    hybrid = true;
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
                return motherInheritableXenotype;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // If one is null and the other isn't
 | 
					 | 
				
			||||||
            if ((motherInheritableXenotype == null) != (fatherInheritableXenotype == null)) return motherInheritableXenotype ?? fatherInheritableXenotype;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // So two different inheritable ones
 | 
					 | 
				
			||||||
            hybrid = true;
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public PawnKindDef GetHybrid(Pawn first, Pawn second)
 | 
					        public PawnKindDef GetHybrid(Pawn first, Pawn second)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            PawnKindDef res = null;
 | 
					            PawnKindDef res = null;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,7 +132,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                if (pregnancy == null) continue;
 | 
					                if (pregnancy == null) continue;
 | 
				
			||||||
                if (Earliest_Pregnancy == null || Earliest_Pregnancy.Severity > pregnancy.Severity) Earliest_Pregnancy = pregnancy;
 | 
					                if (Earliest_Pregnancy == null || Earliest_Pregnancy.Severity > pregnancy.Severity) Earliest_Pregnancy = pregnancy;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
            return Earliest_Pregnancy;
 | 
					            return Earliest_Pregnancy;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -176,4 +176,5 @@ namespace RJW_Menstruation
 | 
				
			||||||
            return TryTerminatePregnancy_Patch.Transpiler(instructions);
 | 
					            return TryTerminatePregnancy_Patch.Transpiler(instructions);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,8 @@
 | 
				
			||||||
using HarmonyLib;
 | 
					using HarmonyLib;
 | 
				
			||||||
using RimWorld;
 | 
					using RimWorld;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
using UnityEngine;
 | 
					using UnityEngine;
 | 
				
			||||||
using Verse;
 | 
					using Verse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,11 +20,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                comp.Initialize();
 | 
					                comp.Initialize();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            HediffComp_Breast bcomp = __instance.GetBreastComp();
 | 
					            __instance.GetBreastComp()?.Initialize();
 | 
				
			||||||
            if (bcomp != null)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                bcomp.Initialize();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -111,56 +109,15 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [HarmonyPatch(typeof(CompBiosculpterPod), nameof(CompBiosculpterPod.CannotUseNowPawnCycleReason), new Type[] { typeof(Pawn), typeof(Pawn), typeof(CompBiosculpterPod_Cycle), typeof(bool) })]
 | 
				
			||||||
    //Merged to RJW
 | 
					    public class CannotUseNowPawnCycleReason_Patch
 | 
				
			||||||
    //[HarmonyPatch(typeof(PawnColumnWorker_Pregnant), "GetIconFor")]
 | 
					    {
 | 
				
			||||||
    //public class PawnColumnWorker_Patch_Icon
 | 
					        private const string eggRestorationKey = "eggRestoration";
 | 
				
			||||||
    //{
 | 
					        public static void Postfix(ref string __result, Pawn biosculptee, CompBiosculpterPod_Cycle cycle)
 | 
				
			||||||
    //    public static void Postfix(Pawn pawn, ref Texture2D __result)
 | 
					        {
 | 
				
			||||||
    //    {
 | 
					            if (__result != null) return;
 | 
				
			||||||
    //        if (pawn.IsVisiblyPregnant()) __result = ContentFinder<Texture2D>.Get("UI/Icons/Animal/Pregnant", true);
 | 
					            if (cycle.Props.key == eggRestorationKey && !biosculptee.GetMenstruationComps().Any())
 | 
				
			||||||
    //    }
 | 
					                __result = Translations.CannotNoWomb;
 | 
				
			||||||
    //
 | 
					        }
 | 
				
			||||||
    //}
 | 
					    }
 | 
				
			||||||
    //
 | 
					 | 
				
			||||||
    //[HarmonyPatch(typeof(PawnColumnWorker_Pregnant), "GetTooltipText")]
 | 
					 | 
				
			||||||
    //public class PawnColumnWorker_Patch_Tooltip
 | 
					 | 
				
			||||||
    //{
 | 
					 | 
				
			||||||
    //    public static bool Prefix(Pawn pawn, ref string __result)
 | 
					 | 
				
			||||||
    //    {
 | 
					 | 
				
			||||||
    //        float gestationProgress = PregnancyHelper.GetPregnancy(pawn).Severity;
 | 
					 | 
				
			||||||
    //        int num = (int)(pawn.RaceProps.gestationPeriodDays * 60000f);
 | 
					 | 
				
			||||||
    //        int numTicks = (int)(gestationProgress * (float)num);
 | 
					 | 
				
			||||||
    //        __result = "PregnantIconDesc".Translate(numTicks.ToStringTicksToDays("F0"), num.ToStringTicksToDays("F0"));
 | 
					 | 
				
			||||||
    //        return false;
 | 
					 | 
				
			||||||
    //    }
 | 
					 | 
				
			||||||
    //
 | 
					 | 
				
			||||||
    //}
 | 
					 | 
				
			||||||
    //
 | 
					 | 
				
			||||||
    //[HarmonyPatch(typeof(TransferableUIUtility), "DoExtraAnimalIcons")]
 | 
					 | 
				
			||||||
    //public class TransferableUIUtility_Patch_Icon
 | 
					 | 
				
			||||||
    //{
 | 
					 | 
				
			||||||
    //    //private static readonly Texture2D PregnantIcon = ContentFinder<Texture2D>.Get("UI/Icons/Animal/Pregnant", true);
 | 
					 | 
				
			||||||
    //
 | 
					 | 
				
			||||||
    //
 | 
					 | 
				
			||||||
    //
 | 
					 | 
				
			||||||
    //    public static void Postfix(Transferable trad, Rect rect, ref float curX, Texture2D ___PregnantIcon)
 | 
					 | 
				
			||||||
    //    {
 | 
					 | 
				
			||||||
    //        Pawn pawn = trad.AnyThing as Pawn;
 | 
					 | 
				
			||||||
    //        if (pawn?.health?.hediffSet != null && pawn.IsVisiblyPregnant())
 | 
					 | 
				
			||||||
    //        {
 | 
					 | 
				
			||||||
    //            Rect rect3 = new Rect(curX - 24f, (rect.height - 24f) / 2f, 24f, 24f);
 | 
					 | 
				
			||||||
    //            curX -= 24f;
 | 
					 | 
				
			||||||
    //            if (Mouse.IsOver(rect3))
 | 
					 | 
				
			||||||
    //            {
 | 
					 | 
				
			||||||
    //                TooltipHandler.TipRegion(rect3, PawnColumnWorker_Pregnant.GetTooltipText(pawn));
 | 
					 | 
				
			||||||
    //            }
 | 
					 | 
				
			||||||
    //            GUI.DrawTexture(rect3, ___PregnantIcon);
 | 
					 | 
				
			||||||
    //        }
 | 
					 | 
				
			||||||
    //    }
 | 
					 | 
				
			||||||
    //}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,7 +43,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (Genital_Helper.has_ovipositorM(pawn, pawnparts))
 | 
					            else if (Genital_Helper.has_ovipositorM(pawn, pawnparts))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                comp.CumIn(pawn, Rand.Range(0.75f, 4.5f) * pawn.BodySize, partner.SterileGenes() ? 0.0f : 1.0f);
 | 
					                comp.CumIn(pawn, Rand.Range(0.75f, 4.5f) * pawn.BodySize, pawn.SterileGenes() ? 0.0f : 1.0f);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else comp.CumIn(pawn, pawn.GetCumVolume(pawnparts), 0);
 | 
					            else comp.CumIn(pawn, pawn.GetCumVolume(pawnparts), 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,7 +70,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <param name="props"></param>
 | 
					        /// <param name="props"></param>
 | 
				
			||||||
        /// <returns>Interaction can result in pregnancy</returns>
 | 
					        /// <returns>Interaction can result in pregnancy</returns>
 | 
				
			||||||
        private static bool InteractionCanCausePregnancy(SexProps props)
 | 
					        public static bool InteractionCanCausePregnancy(SexProps props)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            InteractionWithExtension interaction = rjw.Modules.Interactions.Helpers.InteractionHelper.GetWithExtension(props.dictionaryKey);
 | 
					            InteractionWithExtension interaction = rjw.Modules.Interactions.Helpers.InteractionHelper.GetWithExtension(props.dictionaryKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -331,6 +331,34 @@ namespace RJW_Menstruation
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [HarmonyPatch(typeof(JobDriver_Sex), nameof(JobDriver_Sex.SexTick))]
 | 
				
			||||||
 | 
					    public static class SexTick_Patch
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private const float fertilePrecummersPercentage = 0.33f;
 | 
				
			||||||
 | 
					        private const float precumRatio = 0.1f; // Relative to ejaculation volume
 | 
				
			||||||
 | 
					        private const float precumFertility = 0.5f;
 | 
				
			||||||
 | 
					        private const float expectedDurationTicks = 2000f * (0.9f - 0.5f) / 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static void Postfix(JobDriver_Sex __instance, Pawn pawn, Thing target)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (!pawn.IsHashIntervalTick(__instance.ticks_between_thrusts)) return;
 | 
				
			||||||
 | 
					            xxx.rjwSextype sextype = __instance.Sexprops.sexType;
 | 
				
			||||||
 | 
					            if (!(target is Pawn partner) || pawn == partner) return;
 | 
				
			||||||
 | 
					            if (sextype != xxx.rjwSextype.Vaginal && sextype != xxx.rjwSextype.DoublePenetration) return;
 | 
				
			||||||
 | 
					            if (__instance.Sexprops.usedCondom) return;
 | 
				
			||||||
 | 
					            if (!Impregnate_Patch.InteractionCanCausePregnancy(__instance.Sexprops)) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Archotech penises have more control. Or something.
 | 
				
			||||||
 | 
					            CompHediffBodyPart penisComp = pawn.GetGenitalsList()?.Find(genital => (genital as Hediff_PartBaseNatural)?.def.defName.ToLower().Contains("penis") ?? false)?.TryGetComp<CompHediffBodyPart>();
 | 
				
			||||||
 | 
					            if (penisComp == null || Rand.ChanceSeeded(1.0f - fertilePrecummersPercentage, Gen.HashOffset(penisComp.parent.loadID))) return;
 | 
				
			||||||
 | 
					            HediffComp_Menstruation vaginaComp = partner.GetRandomMenstruationComp();
 | 
				
			||||||
 | 
					            if (vaginaComp == null) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            float precumAmount = pawn.GetCumVolume(penisComp) * precumRatio * __instance.ticks_between_thrusts / expectedDurationTicks;
 | 
				
			||||||
 | 
					            vaginaComp.CumIn(pawn, precumAmount, pawn.SterileGenes() ? 0.0f : precumFertility * pawn.health.capacities.GetLevel(xxx.reproduction), true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [HarmonyPatch(typeof(CompHediffBodyPart), nameof(CompHediffBodyPart.updatesize))]
 | 
					    [HarmonyPatch(typeof(CompHediffBodyPart), nameof(CompHediffBodyPart.updatesize))]
 | 
				
			||||||
    public static class Updatesize_Patch
 | 
					    public static class Updatesize_Patch
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,12 +61,14 @@
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <Compile Include="Compatibility\AnimalGeneticsCompatibility.cs" />
 | 
					    <Compile Include="Compatibility\AnimalGeneticsCompatibility.cs" />
 | 
				
			||||||
    <Compile Include="Compatibility\HARCompatibility.cs" />
 | 
					    <Compile Include="Compatibility\HARCompatibility.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="CompBiosculpterPod_EggRestorationCycle.cs" />
 | 
				
			||||||
    <Compile Include="Configurations.cs" />
 | 
					    <Compile Include="Configurations.cs" />
 | 
				
			||||||
    <Compile Include="Cum.cs" />
 | 
					    <Compile Include="Cum.cs" />
 | 
				
			||||||
    <Compile Include="DebugActions.cs" />
 | 
					    <Compile Include="DebugActions.cs" />
 | 
				
			||||||
    <Compile Include="DrugOutcomeDoers.cs" />
 | 
					    <Compile Include="DrugOutcomeDoers.cs" />
 | 
				
			||||||
    <Compile Include="EstrusPartKindUsageRule.cs" />
 | 
					    <Compile Include="EstrusPartKindUsageRule.cs" />
 | 
				
			||||||
    <Compile Include="HediffComps\HediffComp_InducedOvulator.cs" />
 | 
					    <Compile Include="HediffComps\HediffComp_InducedOvulator.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="HediffComps\HediffComp_PeriodicOvulator.cs" />
 | 
				
			||||||
    <Compile Include="HediffComps\MenstruationUtility.cs" />
 | 
					    <Compile Include="HediffComps\MenstruationUtility.cs" />
 | 
				
			||||||
    <Compile Include="Hediff_Estrus.cs" />
 | 
					    <Compile Include="Hediff_Estrus.cs" />
 | 
				
			||||||
    <Compile Include="IngestionOutcomeDoers.cs" />
 | 
					    <Compile Include="IngestionOutcomeDoers.cs" />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,6 +139,9 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static readonly string CannotNoEggs = "CannotNoEggs".Translate();
 | 
					        public static readonly string CannotNoEggs = "CannotNoEggs".Translate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static readonly string CannotNoWomb = "CannotNoWomb".Translate();
 | 
				
			||||||
 | 
					        public static string EggRestorationCompleted(NamedArgument name) { return "EggRestorationCompleted".Translate(name); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static readonly string CustomHybrid_List_Title = "CustomHybrid_List_Title".Translate();
 | 
					        public static readonly string CustomHybrid_List_Title = "CustomHybrid_List_Title".Translate();
 | 
				
			||||||
        static public string CustomHybrid_Title(string label) { return TranslatorFormattedStringExtensions.Translate("CustomHybrid_Title", label); }
 | 
					        static public string CustomHybrid_Title(string label) { return TranslatorFormattedStringExtensions.Translate("CustomHybrid_Title", label); }
 | 
				
			||||||
        static public string CustomHybrid_Tooltip(string label, string breedee, string baby, string chance) { return TranslatorFormattedStringExtensions.Translate("CustomHybrid_Tooltip", label, breedee, baby, chance); }
 | 
					        static public string CustomHybrid_Tooltip(string label, string breedee, string baby, string chance) { return TranslatorFormattedStringExtensions.Translate("CustomHybrid_Tooltip", label, breedee, baby, chance); }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
					<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
				
			||||||
<Manifest>
 | 
					<Manifest>
 | 
				
			||||||
	<identifier>RJW Menstruation</identifier>
 | 
						<identifier>RJW Menstruation</identifier>
 | 
				
			||||||
	<version>1.0.8.4</version>
 | 
						<version>1.0.8.5</version>
 | 
				
			||||||
	<dependencies>
 | 
						<dependencies>
 | 
				
			||||||
	</dependencies>
 | 
						</dependencies>
 | 
				
			||||||
	<incompatibleWith />
 | 
						<incompatibleWith />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,13 @@
 | 
				
			||||||
 | 
					Version 1.0.8.5
 | 
				
			||||||
 | 
					 - Added biosculpter recipe to restore 1 year's worth of eggs, with icon by DestinyPlayer.
 | 
				
			||||||
 | 
					 - Vaginal sex with the "avoid pregnancy" relation will (usually) pull out prevent cum from entering the womb if there's a risk of pregnancy.
 | 
				
			||||||
 | 
					 - Impregnation fetishists are significantly less likely to pull out.
 | 
				
			||||||
 | 
					 - Some males will release small amounts of semen into a womb during vaginal sex before their actual ejaculation.
 | 
				
			||||||
 | 
					 - Babies born from multiple pregnancy will properly produce the prompt to name them.
 | 
				
			||||||
 | 
					 - Hopefully improve compatibility with xenotype inhertiance-altering mods for multiple pregnancy.
 | 
				
			||||||
 | 
					 - Pawns that have stopped aging will no longer have larger breasts during and after pregnancy.
 | 
				
			||||||
 | 
					 - Experimental "periodic ovulator" cycle type added, currently not used. See Patches/Hediffs_Private_Parts_Animal.xml for an example.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Version 1.0.8.4
 | 
					Version 1.0.8.4
 | 
				
			||||||
 - Fix Biotech xenotype inheritance for single-child pregnancies.
 | 
					 - Fix Biotech xenotype inheritance for single-child pregnancies.
 | 
				
			||||||
 - Fix error in Traditional Chinese translation.
 | 
					 - Fix error in Traditional Chinese translation.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue