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
						b254273935
					
				
					 32 changed files with 1099 additions and 371 deletions
				
			
		
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										107
									
								
								1.4/Defs/GeneDefs/GeneDefs_Menstruation.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								1.4/Defs/GeneDefs/GeneDefs_Menstruation.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,107 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<Defs>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<GeneCategoryDef>
 | 
				
			||||||
 | 
							<defName>Menstruation</defName>
 | 
				
			||||||
 | 
							<label>menstruation</label>
 | 
				
			||||||
 | 
							<displayPriorityInXenotype>402</displayPriorityInXenotype>
 | 
				
			||||||
 | 
						</GeneCategoryDef>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<GeneDef Name="Menstruation_EggLifetime" Abstract="True">
 | 
				
			||||||
 | 
							<displayCategory>Menstruation</displayCategory>
 | 
				
			||||||
 | 
							<exclusionTags>
 | 
				
			||||||
 | 
								<li>Menstruation_EggLifetime</li>
 | 
				
			||||||
 | 
							</exclusionTags>
 | 
				
			||||||
 | 
						</GeneDef>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<GeneDef ParentName="Menstruation_EggLifetime">
 | 
				
			||||||
 | 
							<defName>Menstruation_ShortEggLifetime</defName>
 | 
				
			||||||
 | 
							<label>short egg lifetime</label>
 | 
				
			||||||
 | 
							<description>Unfertilized eggs with this gene last three-quarters as long.</description>
 | 
				
			||||||
 | 
							<iconPath>UI/Genes/Placeholder</iconPath>
 | 
				
			||||||
 | 
							<biostatMet>1</biostatMet>
 | 
				
			||||||
 | 
							<displayOrderInCategory>10</displayOrderInCategory>
 | 
				
			||||||
 | 
						</GeneDef>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<GeneDef ParentName="Menstruation_EggLifetime">
 | 
				
			||||||
 | 
							<defName>Menstruation_DoubleEggLifetime</defName>
 | 
				
			||||||
 | 
							<label>double egg lifetime</label>
 | 
				
			||||||
 | 
							<description>Unfertilized eggs with this gene last twice as long.</description>
 | 
				
			||||||
 | 
							<iconPath>UI/Genes/Placeholder</iconPath>
 | 
				
			||||||
 | 
							<biostatMet>-1</biostatMet>
 | 
				
			||||||
 | 
							<displayOrderInCategory>12</displayOrderInCategory>
 | 
				
			||||||
 | 
						</GeneDef>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<GeneDef ParentName="Menstruation_EggLifetime">
 | 
				
			||||||
 | 
							<defName>Menstruation_QuadEggLifetime</defName>
 | 
				
			||||||
 | 
							<label>quadrule egg lifetime</label>
 | 
				
			||||||
 | 
							<description>Eggs with this gene last four times as long.</description>
 | 
				
			||||||
 | 
							<iconPath>UI/Genes/Placeholder</iconPath>
 | 
				
			||||||
 | 
							<biostatMet>-2</biostatMet>
 | 
				
			||||||
 | 
							<biostatCpx>1</biostatCpx>
 | 
				
			||||||
 | 
							<displayOrderInCategory>16</displayOrderInCategory>
 | 
				
			||||||
 | 
						</GeneDef>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<GeneDef Name="Menstruation_Estrus" Abstract="True">
 | 
				
			||||||
 | 
							<displayCategory>Menstruation</displayCategory>
 | 
				
			||||||
 | 
							<exclusionTags>
 | 
				
			||||||
 | 
								<li>Menstruation_Estrus</li>
 | 
				
			||||||
 | 
							</exclusionTags>
 | 
				
			||||||
 | 
						</GeneDef>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<GeneDef ParentName="Menstruation_Estrus">
 | 
				
			||||||
 | 
							<defName>Menstruation_NeverEstrus</defName>
 | 
				
			||||||
 | 
							<label>never estrus</label>
 | 
				
			||||||
 | 
							<description>Carriers of this gene will never go into estrus.</description>
 | 
				
			||||||
 | 
							<iconPath>UI/Genes/Placeholder</iconPath>
 | 
				
			||||||
 | 
							<biostatMet>1</biostatMet>
 | 
				
			||||||
 | 
							<displayOrderInCategory>20</displayOrderInCategory>
 | 
				
			||||||
 | 
						</GeneDef>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<GeneDef ParentName="Menstruation_Estrus">
 | 
				
			||||||
 | 
							<defName>Menstruation_FullEstrus</defName>
 | 
				
			||||||
 | 
							<label>full estrus</label>
 | 
				
			||||||
 | 
							<description>Carriers of this gene will enter full estrus every menstrual cycle, regardless of vagina type.</description>
 | 
				
			||||||
 | 
							<iconPath>UI/Genes/Placeholder</iconPath>
 | 
				
			||||||
 | 
							<biostatMet>-1</biostatMet>
 | 
				
			||||||
 | 
							<biostatCpx>1</biostatCpx>
 | 
				
			||||||
 | 
							<displayOrderInCategory>25</displayOrderInCategory>
 | 
				
			||||||
 | 
						</GeneDef>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<GeneDef Name="Menstruation_Ovulation" Abstract="True">
 | 
				
			||||||
 | 
							<displayCategory>Menstruation</displayCategory>
 | 
				
			||||||
 | 
							<exclusionTags>
 | 
				
			||||||
 | 
								<li>Menstruation_Ovulation</li>
 | 
				
			||||||
 | 
							</exclusionTags>
 | 
				
			||||||
 | 
						</GeneDef>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<GeneDef ParentName="Menstruation_Ovulation">
 | 
				
			||||||
 | 
							<defName>Menstruation_DoubleOvulation</defName>
 | 
				
			||||||
 | 
							<label>double ovulation</label>
 | 
				
			||||||
 | 
							<description>Carriers of this gene will ovulate twice as many eggs.</description>
 | 
				
			||||||
 | 
							<iconPath>UI/Genes/Placeholder</iconPath>
 | 
				
			||||||
 | 
							<biostatMet>-1</biostatMet>
 | 
				
			||||||
 | 
							<displayOrderInCategory>30</displayOrderInCategory>
 | 
				
			||||||
 | 
						</GeneDef>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<GeneDef ParentName="Menstruation_Ovulation">
 | 
				
			||||||
 | 
							<defName>Menstruation_QuadOvulation</defName>
 | 
				
			||||||
 | 
							<label>quadruple ovulation</label>
 | 
				
			||||||
 | 
							<description>Carriers of this gene will ovulate four times as many eggs.</description>
 | 
				
			||||||
 | 
							<iconPath>UI/Genes/Placeholder</iconPath>
 | 
				
			||||||
 | 
							<biostatMet>-1</biostatMet>
 | 
				
			||||||
 | 
							<displayOrderInCategory>35</displayOrderInCategory>
 | 
				
			||||||
 | 
						</GeneDef>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<GeneDef>
 | 
				
			||||||
 | 
							<defName>Menstruation_NoBleeding</defName>
 | 
				
			||||||
 | 
							<label>no bleeding</label>
 | 
				
			||||||
 | 
							<displayCategory>Menstruation</displayCategory>
 | 
				
			||||||
 | 
							<description>Carriers of this gene will not bleed at the end of their cycle.</description>
 | 
				
			||||||
 | 
							<iconPath>UI/Genes/Placeholder</iconPath>
 | 
				
			||||||
 | 
							<biostatMet>1</biostatMet>
 | 
				
			||||||
 | 
							<displayOrderInCategory>40</displayOrderInCategory>
 | 
				
			||||||
 | 
						</GeneDef>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<!-- Pheromones? -->
 | 
				
			||||||
 | 
					</Defs>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<LanguageData>
 | 
				
			||||||
 | 
					    <Menstruation.label>月經週期</Menstruation.label>
 | 
				
			||||||
 | 
					    <Menstruation_ShortEggLifetime.label>較短卵細胞壽命</Menstruation_ShortEggLifetime.label>
 | 
				
			||||||
 | 
					    <Menstruation_ShortEggLifetime.description>未受精卵細胞存活時長僅有原先的3/4</Menstruation_ShortEggLifetime.description>
 | 
				
			||||||
 | 
					    <Menstruation_DoubleEggLifetime.label>雙倍卵細胞壽命</Menstruation_DoubleEggLifetime.label>
 | 
				
			||||||
 | 
					    <Menstruation_DoubleEggLifetime.description>未受精卵細胞可存活至原先的2倍之久</Menstruation_DoubleEggLifetime.description>
 | 
				
			||||||
 | 
					    <Menstruation_QuadEggLifetime.label>四倍卵細胞壽命</Menstruation_QuadEggLifetime.label>
 | 
				
			||||||
 | 
					    <Menstruation_QuadEggLifetime.description>未受精卵細胞可存活至原先的4倍之久</Menstruation_QuadEggLifetime.description>
 | 
				
			||||||
 | 
					    <Menstruation_NeverEstrus.label>永不發情</Menstruation_NeverEstrus.label>
 | 
				
			||||||
 | 
					    <Menstruation_NeverEstrus.description>基因攜帶者永遠不會進入發情期。</Menstruation_NeverEstrus.description>
 | 
				
			||||||
 | 
					    <Menstruation_FullEstrus.label>始終發情</Menstruation_FullEstrus.label>
 | 
				
			||||||
 | 
					    <Menstruation_FullEstrus.description>基因攜帶者的每一個月經週期均具備發情期,無論陰道類型為何。</Menstruation_FullEstrus.description>
 | 
				
			||||||
 | 
					    <Menstruation_DoubleOvulation.label>雙倍排卵</Menstruation_DoubleOvulation.label>
 | 
				
			||||||
 | 
					    <Menstruation_DoubleOvulation.description>基因攜帶者的子宮可以在每個排卵週期產生雙倍的卵子。</Menstruation_DoubleOvulation.description>
 | 
				
			||||||
 | 
					    <Menstruation_QuadOvulation.label>四倍排卵</Menstruation_QuadOvulation.label>
 | 
				
			||||||
 | 
					    <Menstruation_QuadOvulation.description>基因攜帶者的子宮可以在每個排卵週期產生四倍的卵子。</Menstruation_QuadOvulation.description>
 | 
				
			||||||
 | 
					    <Menstruation_NoBleeding.label>無經血</Menstruation_NoBleeding.label>
 | 
				
			||||||
 | 
					    <Menstruation_NoBleeding.description>基因攜帶者的子宮內膜不會脫落出血。</Menstruation_NoBleeding.description>
 | 
				
			||||||
 | 
					</LanguageData>
 | 
				
			||||||
| 
						 | 
					@ -8,4 +8,7 @@
 | 
				
			||||||
    <TookContraceptivePill.stages.0.description>總算把這事了結了。</TookContraceptivePill.stages.0.description>
 | 
					    <TookContraceptivePill.stages.0.description>總算把這事了結了。</TookContraceptivePill.stages.0.description>
 | 
				
			||||||
    <HateTookContraceptivePill.stages.0.label>吃了避孕藥</HateTookContraceptivePill.stages.0.label>
 | 
					    <HateTookContraceptivePill.stages.0.label>吃了避孕藥</HateTookContraceptivePill.stages.0.label>
 | 
				
			||||||
    <HateTookContraceptivePill.stages.0.description>我想要小孩!</HateTookContraceptivePill.stages.0.description>
 | 
					    <HateTookContraceptivePill.stages.0.description>我想要小孩!</HateTookContraceptivePill.stages.0.description>
 | 
				
			||||||
 | 
					    <!--Auto generated: Thu Jan  5 22:13:15 2023-->
 | 
				
			||||||
 | 
					    <EggRestorationReceived.stages.0.label>卵母細胞再生術</EggRestorationReceived.stages.0.label>
 | 
				
			||||||
 | 
					    <EggRestorationReceived.stages.0.description>我可以繼續繁衍一小段時間了!</EggRestorationReceived.stages.0.description>
 | 
				
			||||||
</LanguageData>
 | 
					</LanguageData>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,7 @@
 | 
				
			||||||
    <Option7_Label>月經加速</Option7_Label>
 | 
					    <Option7_Label>月經加速</Option7_Label>
 | 
				
			||||||
    <Option7_Desc>加快月經週期</Option7_Desc>
 | 
					    <Option7_Desc>加快月經週期</Option7_Desc>
 | 
				
			||||||
    <Option8_Label>除錯</Option8_Label>
 | 
					    <Option8_Label>除錯</Option8_Label>
 | 
				
			||||||
    <Option8_Desc>顯示除錯資訊</Option8_Desc>
 | 
					    <Option8_Desc>顯示除錯資訊
啟用時會令「胎兒信息級別」選項調至「全部細節」。</Option8_Desc>
 | 
				
			||||||
    <Option9_Label>子宮狀態</Option9_Label>
 | 
					    <Option9_Label>子宮狀態</Option9_Label>
 | 
				
			||||||
    <Option9_Desc>在狀態窗口中繪製子宮圖標</Option9_Desc>
 | 
					    <Option9_Desc>在狀態窗口中繪製子宮圖標</Option9_Desc>
 | 
				
			||||||
    <Option10_Label>陰道狀態</Option10_Label>
 | 
					    <Option10_Label>陰道狀態</Option10_Label>
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,6 @@
 | 
				
			||||||
    <Option17_Label>最大雙胞胎數量</Option17_Label>
 | 
					    <Option17_Label>最大雙胞胎數量</Option17_Label>
 | 
				
			||||||
    <Option17_Desc>設置最大雙胞胎數量</Option17_Desc>
 | 
					    <Option17_Desc>設置最大雙胞胎數量</Option17_Desc>
 | 
				
			||||||
    <FloatMenu_CleanSelf>清洗陰道</FloatMenu_CleanSelf>
 | 
					    <FloatMenu_CleanSelf>清洗陰道</FloatMenu_CleanSelf>
 | 
				
			||||||
 | 
					 | 
				
			||||||
    <!--Auto generated: Mon Oct  3 21:49:26 2022-->
 | 
					    <!--Auto generated: Mon Oct  3 21:49:26 2022-->
 | 
				
			||||||
    <Stage_Menopause>絕經</Stage_Menopause>
 | 
					    <Stage_Menopause>絕經</Stage_Menopause>
 | 
				
			||||||
    <Stage_Anestrus>乏情期</Stage_Anestrus>
 | 
					    <Stage_Anestrus>乏情期</Stage_Anestrus>
 | 
				
			||||||
| 
						 | 
					@ -98,7 +97,7 @@
 | 
				
			||||||
    <Option21_Label>本模組作用於:</Option21_Label>
 | 
					    <Option21_Label>本模組作用於:</Option21_Label>
 | 
				
			||||||
    <Option21_Desc>這些小人的「RJW月經週期」工具欄對玩家可見。</Option21_Desc>
 | 
					    <Option21_Desc>這些小人的「RJW月經週期」工具欄對玩家可見。</Option21_Desc>
 | 
				
			||||||
    <Option22_Label>使用進階雜交定義</Option22_Label>
 | 
					    <Option22_Label>使用進階雜交定義</Option22_Label>
 | 
				
			||||||
    <Option22_Desc>複寫RJW和RaceSupport插件的雜交定義。Overrides RJW and RaceSupport's hybrid definition.
 | 
					    <Option22_Desc>覆寫RJW和RaceSupport插件的雜交定義。Overrides RJW and RaceSupport's hybrid definition.
 | 
				
			||||||
主導混合擴展決定了首先使用誰的定義。不建議更改此設置。Dominant hybrid extension determines whose definition used first. Not recommended to change this.</Option22_Desc>
 | 
					主導混合擴展決定了首先使用誰的定義。不建議更改此設置。Dominant hybrid extension determines whose definition used first. Not recommended to change this.</Option22_Desc>
 | 
				
			||||||
    <Option23_Label>主導混合擴展Dominant hybrid extension</Option23_Label>
 | 
					    <Option23_Label>主導混合擴展Dominant hybrid extension</Option23_Label>
 | 
				
			||||||
    <Option23_Label_1>母本</Option23_Label_1>
 | 
					    <Option23_Label_1>母本</Option23_Label_1>
 | 
				
			||||||
| 
						 | 
					@ -111,7 +110,7 @@
 | 
				
			||||||
    <Option_PermanentNippleChange_Desc>乳頭在孕期間的改變會在孕期結束後保留多少?</Option_PermanentNippleChange_Desc>
 | 
					    <Option_PermanentNippleChange_Desc>乳頭在孕期間的改變會在孕期結束後保留多少?</Option_PermanentNippleChange_Desc>
 | 
				
			||||||
    <Option28_Label>客製化雜交細節</Option28_Label>
 | 
					    <Option28_Label>客製化雜交細節</Option28_Label>
 | 
				
			||||||
    <Option28_Tooltip>開啟雜交編輯器
 | 
					    <Option28_Tooltip>開啟雜交編輯器
 | 
				
			||||||
該選項會複寫XML文件中的雜交定義。</Option28_Tooltip>
 | 
					該選項會覆寫XML文件中的雜交定義。</Option28_Tooltip>
 | 
				
			||||||
    <Option29_Label>允許圖標縮小</Option29_Label>
 | 
					    <Option29_Label>允許圖標縮小</Option29_Label>
 | 
				
			||||||
    <Option29_Desc>允許圖標在特殊場合縮小。</Option29_Desc>
 | 
					    <Option29_Desc>允許圖標在特殊場合縮小。</Option29_Desc>
 | 
				
			||||||
    <Option30_Label>卵細胞生命期乘數</Option30_Label>
 | 
					    <Option30_Label>卵細胞生命期乘數</Option30_Label>
 | 
				
			||||||
| 
						 | 
					@ -123,7 +122,7 @@
 | 
				
			||||||
    <Option32_Label>擴張力度</Option32_Label>
 | 
					    <Option32_Label>擴張力度</Option32_Label>
 | 
				
			||||||
    <Option32_Desc>調節擴張力度。</Option32_Desc>
 | 
					    <Option32_Desc>調節擴張力度。</Option32_Desc>
 | 
				
			||||||
    <Option_EnableGatherCumGizmo_Label>啟用「擠出精液」按鈕</Option_EnableGatherCumGizmo_Label>
 | 
					    <Option_EnableGatherCumGizmo_Label>啟用「擠出精液」按鈕</Option_EnableGatherCumGizmo_Label>
 | 
				
			||||||
    <Option_EstrusOverride_Label>令「發情期」機制複寫RJW的濫交選項</Option_EstrusOverride_Label>
 | 
					    <Option_EstrusOverride_Label>令「發情期」機制覆寫RJW的濫交選項</Option_EstrusOverride_Label>
 | 
				
			||||||
    <Option_EstrusOverride_Desc>啟用時,處於顯式發情期的小人將會使用以下選項來選定床伴。RJW的原始設定會被忽略。
 | 
					    <Option_EstrusOverride_Desc>啟用時,處於顯式發情期的小人將會使用以下選項來選定床伴。RJW的原始設定會被忽略。
 | 
				
			||||||
所有數值與RJW的對應選項相同。</Option_EstrusOverride_Desc>
 | 
					所有數值與RJW的對應選項相同。</Option_EstrusOverride_Desc>
 | 
				
			||||||
    <Option_EstrusFuckability_Label>發情期床伴:最低fuckability</Option_EstrusFuckability_Label>
 | 
					    <Option_EstrusFuckability_Label>發情期床伴:最低fuckability</Option_EstrusFuckability_Label>
 | 
				
			||||||
| 
						 | 
					@ -139,4 +138,13 @@
 | 
				
			||||||
    <CustomHybrid_Title>{0}之雜交</CustomHybrid_Title>
 | 
					    <CustomHybrid_Title>{0}之雜交</CustomHybrid_Title>
 | 
				
			||||||
    <CustomHybrid_Tooltip>當{0}與{1}產生後代,有{3}的概率生出{2}。
 | 
					    <CustomHybrid_Tooltip>當{0}與{1}產生後代,有{3}的概率生出{2}。
 | 
				
			||||||
若兩個種族相互間皆存在雜交定義,則以父本的定義為準。</CustomHybrid_Tooltip>
 | 
					若兩個種族相互間皆存在雜交定義,則以父本的定義為準。</CustomHybrid_Tooltip>
 | 
				
			||||||
 | 
					    <!--Auto generated: Thu Jan  5 22:13:15 2023-->
 | 
				
			||||||
 | 
					    <Option_PregnancyFromBaseRJW_Label>使用RJW的簡單懷孕系統</Option_PregnancyFromBaseRJW_Label>
 | 
				
			||||||
 | 
					    <Option_PregnancyFromMultiplePregnancy_Label>使用本模組的多重懷孕</Option_PregnancyFromMultiplePregnancy_Label>
 | 
				
			||||||
 | 
					    <Option_PregnancyFromBiotech_Label>使用「生機」(Biotech)追加的懷孕機制</Option_PregnancyFromBiotech_Label>
 | 
				
			||||||
 | 
					    <Option_EnableDraftedIcon_Label>於「徵召」狀態下仍顯示子宮狀態</Option_EnableDraftedIcon_Label>
 | 
				
			||||||
 | 
					    <Option_EnableDraftedIcon_Desc>角色處於被徵召狀態時,子宮圖標不予隱藏。</Option_EnableDraftedIcon_Desc>
 | 
				
			||||||
 | 
					    <CannotNoEggs>沒有卵細胞</CannotNoEggs>
 | 
				
			||||||
 | 
					    <CannotNoWomb>必須擁有子宮</CannotNoWomb>
 | 
				
			||||||
 | 
					    <EggRestorationCompleted>{PAWN_labelShort}完成了{PAWN_possessive}卵母細胞再生術(cycle)</EggRestorationCompleted>
 | 
				
			||||||
</LanguageData>
 | 
					</LanguageData>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -124,6 +124,8 @@
 | 
				
			||||||
  <Option_PregnancyFromBaseRJW_Label>Use basic RJW pregnancy</Option_PregnancyFromBaseRJW_Label>
 | 
					  <Option_PregnancyFromBaseRJW_Label>Use basic RJW pregnancy</Option_PregnancyFromBaseRJW_Label>
 | 
				
			||||||
  <Option_PregnancyFromMultiplePregnancy_Label>Use menstruation multiple pregnancy</Option_PregnancyFromMultiplePregnancy_Label>
 | 
					  <Option_PregnancyFromMultiplePregnancy_Label>Use menstruation multiple pregnancy</Option_PregnancyFromMultiplePregnancy_Label>
 | 
				
			||||||
  <Option_PregnancyFromBiotech_Label>Use Biotech pregnancy</Option_PregnancyFromBiotech_Label>
 | 
					  <Option_PregnancyFromBiotech_Label>Use Biotech pregnancy</Option_PregnancyFromBiotech_Label>
 | 
				
			||||||
 | 
					  <Option_EnableBiotechTwins_Label>(EXPERIMENTAL) Enable multiple babies/twins in a single Biotech pregnancy.</Option_EnableBiotechTwins_Label>
 | 
				
			||||||
 | 
					  <Option_EnableBiotechTwins_Desc>Enabling this option will allow identical and hetero ovular twins with Biotech.
Also allows the hybrid system, but two humanlikes cannot produce an animal.</Option_EnableBiotechTwins_Desc>
 | 
				
			||||||
  <Option_EnableDraftedIcon_Label>Show womb status when drafted</Option_EnableDraftedIcon_Label>
 | 
					  <Option_EnableDraftedIcon_Label>Show womb status when drafted</Option_EnableDraftedIcon_Label>
 | 
				
			||||||
  <Option_EnableDraftedIcon_Desc>Draw womb icon for drafted pawns</Option_EnableDraftedIcon_Desc>
 | 
					  <Option_EnableDraftedIcon_Desc>Draw womb icon for drafted pawns</Option_EnableDraftedIcon_Desc>
 | 
				
			||||||
  <Button_ResetToDefault>Reset to default</Button_ResetToDefault>
 | 
					  <Button_ResetToDefault>Reset to default</Button_ResetToDefault>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										16
									
								
								1.4/Patches/Pregenerated_Babies.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								1.4/Patches/Pregenerated_Babies.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<Patch>
 | 
				
			||||||
 | 
						<Operation Class="PatchOperationFindMod">
 | 
				
			||||||
 | 
							<mods>
 | 
				
			||||||
 | 
								<li>Biotech</li>
 | 
				
			||||||
 | 
							</mods>
 | 
				
			||||||
 | 
							<match Class="PatchOperationAdd">
 | 
				
			||||||
 | 
								<xpath>/Defs/HediffDef[defName="PregnantHuman" or defName="PregnancyLabor" or defName="PregnancyLaborPushing"]/comps</xpath>
 | 
				
			||||||
 | 
								<value>
 | 
				
			||||||
 | 
									<li>
 | 
				
			||||||
 | 
										<compClass>RJW_Menstruation.HediffComp_PregeneratedBabies</compClass>
 | 
				
			||||||
 | 
									</li>
 | 
				
			||||||
 | 
								</value>
 | 
				
			||||||
 | 
							</match>
 | 
				
			||||||
 | 
						</Operation>
 | 
				
			||||||
 | 
					</Patch>
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 6.6 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 7.4 KiB  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 9.7 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								1.4/Textures/UI/Genes/Placeholder.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								1.4/Textures/UI/Genes/Placeholder.png
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 5.1 KiB  | 
| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
using AlienRace;
 | 
					using AlienRace;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using UnityEngine;
 | 
					using UnityEngine;
 | 
				
			||||||
using Verse;
 | 
					using Verse;
 | 
				
			||||||
| 
						 | 
					@ -11,7 +12,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public static bool IsHAR(this Pawn pawn)
 | 
					        public static bool IsHAR(this Pawn pawn)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!Configurations.HARActivated) return false;
 | 
					            if (!Configurations.HARActivated) return false;
 | 
				
			||||||
            return pawn?.def is ThingDef_AlienRace;
 | 
					            return GenTypes.GetTypeInAnyAssembly("AlienRace.ThingDef_AlienRace").IsInstanceOfType(pawn?.def);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static void CopyHARProperties(Pawn baby, Pawn original)
 | 
					        public static void CopyHARProperties(Pawn baby, Pawn original)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,6 +55,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public static float EstrusAttractivenessToHookup = RJWHookupSettings.MinimumAttractivenessToHookup;
 | 
					        public static float EstrusAttractivenessToHookup = RJWHookupSettings.MinimumAttractivenessToHookup;
 | 
				
			||||||
        public static float EstrusRelationshipToHookup = RJWHookupSettings.MinimumRelationshipToHookup;
 | 
					        public static float EstrusRelationshipToHookup = RJWHookupSettings.MinimumRelationshipToHookup;
 | 
				
			||||||
        public static PregnancyType PregnancySource = PregnancyType.MultiplePregnancy;
 | 
					        public static PregnancyType PregnancySource = PregnancyType.MultiplePregnancy;
 | 
				
			||||||
 | 
					        public static bool EnableBiotechTwins = false;
 | 
				
			||||||
        public static bool EnableHeteroOvularTwins = true;
 | 
					        public static bool EnableHeteroOvularTwins = true;
 | 
				
			||||||
        public static bool EnableEnzygoticTwins = true;
 | 
					        public static bool EnableEnzygoticTwins = true;
 | 
				
			||||||
        public static float EnzygoticTwinsChance = EnzygoticTwinsChanceDefault;
 | 
					        public static float EnzygoticTwinsChance = EnzygoticTwinsChanceDefault;
 | 
				
			||||||
| 
						 | 
					@ -89,6 +90,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
            EstrusAttractivenessToHookup = RJWHookupSettings.MinimumAttractivenessToHookup;
 | 
					            EstrusAttractivenessToHookup = RJWHookupSettings.MinimumAttractivenessToHookup;
 | 
				
			||||||
            EstrusRelationshipToHookup = RJWHookupSettings.MinimumRelationshipToHookup;
 | 
					            EstrusRelationshipToHookup = RJWHookupSettings.MinimumRelationshipToHookup;
 | 
				
			||||||
            EnzygoticTwinsChanceAdjust = EnzygoticTwinsChanceAdjustDefault;
 | 
					            EnzygoticTwinsChanceAdjust = EnzygoticTwinsChanceAdjustDefault;
 | 
				
			||||||
 | 
					            EnableBiotechTwins = false;
 | 
				
			||||||
            EnableEnzygoticTwins = true;
 | 
					            EnableEnzygoticTwins = true;
 | 
				
			||||||
            EnableHeteroOvularTwins = true;
 | 
					            EnableHeteroOvularTwins = true;
 | 
				
			||||||
            PregnancySource = PregnancyType.MultiplePregnancy;
 | 
					            PregnancySource = PregnancyType.MultiplePregnancy;
 | 
				
			||||||
| 
						 | 
					@ -200,6 +202,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
            Scribe_Values.Look(ref EstrusAttractivenessToHookup, "EstrusAttractivenessToHookup", EstrusAttractivenessToHookup, true);
 | 
					            Scribe_Values.Look(ref EstrusAttractivenessToHookup, "EstrusAttractivenessToHookup", EstrusAttractivenessToHookup, true);
 | 
				
			||||||
            Scribe_Values.Look(ref EstrusRelationshipToHookup, "EstrusRelationshipToHookup", EstrusRelationshipToHookup, true);
 | 
					            Scribe_Values.Look(ref EstrusRelationshipToHookup, "EstrusRelationshipToHookup", EstrusRelationshipToHookup, true);
 | 
				
			||||||
            Scribe_Values.Look(ref PregnancySource, "PregnancySource", PregnancySource, true);
 | 
					            Scribe_Values.Look(ref PregnancySource, "PregnancySource", PregnancySource, true);
 | 
				
			||||||
 | 
					            Scribe_Values.Look(ref EnableBiotechTwins, "EnableBiotechTwins", EnableBiotechTwins, true);
 | 
				
			||||||
            Scribe_Values.Look(ref EnableHeteroOvularTwins, "EnableHeteroOvularTwins", EnableHeteroOvularTwins, true);
 | 
					            Scribe_Values.Look(ref EnableHeteroOvularTwins, "EnableHeteroOvularTwins", EnableHeteroOvularTwins, true);
 | 
				
			||||||
            Scribe_Values.Look(ref EnableEnzygoticTwins, "EnableEnzygoticTwins", EnableEnzygoticTwins, true);
 | 
					            Scribe_Values.Look(ref EnableEnzygoticTwins, "EnableEnzygoticTwins", EnableEnzygoticTwins, true);
 | 
				
			||||||
            Scribe_Values.Look(ref EnzygoticTwinsChance, "EnzygoticTwinsChance", EnzygoticTwinsChance, true);
 | 
					            Scribe_Values.Look(ref EnzygoticTwinsChance, "EnzygoticTwinsChance", EnzygoticTwinsChance, true);
 | 
				
			||||||
| 
						 | 
					@ -271,11 +274,12 @@ 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 = -3f +
 | 
					            float mainRectHeight = 30f +
 | 
				
			||||||
                (Configurations.EnableWombIcon || Configurations.EnableButtonInHT ? 400f : 0f) +
 | 
					                (Configurations.EnableWombIcon || Configurations.EnableButtonInHT ? 400f : 0f) +
 | 
				
			||||||
                (Configurations.EstrusOverridesHookupSettings ? 144f : 0f) +
 | 
					                (Configurations.EstrusOverridesHookupSettings ? 144f : 0f) +
 | 
				
			||||||
                // TODO: Also for modified Biotech pregnancies
 | 
					 | 
				
			||||||
                (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 ? (Configurations.EnableBiotechTwins ? 175f : 75f) : 0f) +
 | 
				
			||||||
                (Configurations.EnableBirthVaginaMorph ? 48f : 0f);
 | 
					                (Configurations.EnableBirthVaginaMorph ? 48f : 0f);
 | 
				
			||||||
            Rect mainRect = new Rect(0f, 0f, inRect.width - 30f, Math.Max(inRect.height + mainRectHeight, 1f));
 | 
					            Rect mainRect = new Rect(0f, 0f, inRect.width - 30f, Math.Max(inRect.height + mainRectHeight, 1f));
 | 
				
			||||||
            int Adjust;
 | 
					            int Adjust;
 | 
				
			||||||
| 
						 | 
					@ -434,9 +438,11 @@ namespace RJW_Menstruation
 | 
				
			||||||
            if (listmain.RadioButton(Translations.Option_PregnancyFromMultiplePregnancy_Label, Configurations.PregnancySource == Configurations.PregnancyType.MultiplePregnancy))
 | 
					            if (listmain.RadioButton(Translations.Option_PregnancyFromMultiplePregnancy_Label, Configurations.PregnancySource == Configurations.PregnancyType.MultiplePregnancy))
 | 
				
			||||||
                Configurations.PregnancySource = Configurations.PregnancyType.MultiplePregnancy;
 | 
					                Configurations.PregnancySource = Configurations.PregnancyType.MultiplePregnancy;
 | 
				
			||||||
            if (ModsConfig.BiotechActive && listmain.RadioButton(Translations.Option_PregnancyFromBiotech_Label, Configurations.PregnancySource == Configurations.PregnancyType.Biotech))
 | 
					            if (ModsConfig.BiotechActive && listmain.RadioButton(Translations.Option_PregnancyFromBiotech_Label, Configurations.PregnancySource == Configurations.PregnancyType.Biotech))
 | 
				
			||||||
                    Configurations.PregnancySource = Configurations.PregnancyType.Biotech;
 | 
					                Configurations.PregnancySource = Configurations.PregnancyType.Biotech;
 | 
				
			||||||
            // TODO: Also for modified Biotech pregnancy
 | 
					            if (Configurations.PregnancySource == Configurations.PregnancyType.Biotech)
 | 
				
			||||||
            if (Configurations.PregnancySource == Configurations.PregnancyType.MultiplePregnancy)
 | 
					                listmain.CheckboxLabeled(Translations.Option_EnableBiotechTwins_Label, ref Configurations.EnableBiotechTwins, Translations.Option_EnableBiotechTwins_Desc);
 | 
				
			||||||
 | 
					            if (Configurations.PregnancySource == Configurations.PregnancyType.MultiplePregnancy ||
 | 
				
			||||||
 | 
					                (Configurations.PregnancySource == Configurations.PregnancyType.Biotech && Configurations.EnableBiotechTwins))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                float sectionheight = 75f;
 | 
					                float sectionheight = 75f;
 | 
				
			||||||
                if (Configurations.EnableEnzygoticTwins) sectionheight += 100;
 | 
					                if (Configurations.EnableEnzygoticTwins) sectionheight += 100;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -365,7 +365,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
            cachedNipple = baseNipple + nippleProgress * nippleChange;
 | 
					            cachedNipple = baseNipple + nippleProgress * nippleChange;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // For some reason, Props can go null when RJW relocates the chest (e.g. some animals), so catch that
 | 
					            // For some reason, Props can go null when RJW relocates the chest (e.g. some animals), so catch that
 | 
				
			||||||
            cachedColor = Colors.CMYKLerp(Pawn.story?.SkinColor ?? Color.white, (Props?.BlackNippleColor ?? CompProperties_Breast.DefaultBlacknippleColor.ToColor), Alpha);
 | 
					            cachedColor = Colors.CMYKLerp(Utility.SafeSkinColor(Pawn), (Props?.BlackNippleColor ?? CompProperties_Breast.DefaultBlacknippleColor.ToColor), Alpha);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void CopyBreastProperties(HediffComp_Breast original)
 | 
					        public void CopyBreastProperties(HediffComp_Breast original)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                    case Stage.Ovulatory:
 | 
					                    case Stage.Ovulatory:
 | 
				
			||||||
                        return true;
 | 
					                        return true;
 | 
				
			||||||
                    case Stage.Luteal:
 | 
					                    case Stage.Luteal:
 | 
				
			||||||
                        return IsEggExist && curStageHrs < Props.eggLifespanDays * 24;
 | 
					                        return IsEggExist && curStageHrs < EggLifespanHours * 24;
 | 
				
			||||||
                    default:
 | 
					                    default:
 | 
				
			||||||
                        return false;
 | 
					                        return false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -93,7 +93,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                case Stage.Ovulatory:
 | 
					                case Stage.Ovulatory:
 | 
				
			||||||
                    return true;
 | 
					                    return true;
 | 
				
			||||||
                case Stage.Luteal:
 | 
					                case Stage.Luteal:
 | 
				
			||||||
                    return IsEggExist && curStageHrs < Props.eggLifespanDays * 24;
 | 
					                    return IsEggExist && curStageHrs < EggLifespanHours * 24;
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -126,6 +126,11 @@ 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 EstrusLevel estrusLevel = EstrusLevel.Visible;
 | 
				
			||||||
 | 
					        protected float ovulationFactor = 1f;
 | 
				
			||||||
 | 
					        protected bool noBleeding = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private static readonly SimpleCurve SexFrequencyCurve = new SimpleCurve()
 | 
					        private static readonly SimpleCurve SexFrequencyCurve = new SimpleCurve()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            new CurvePoint(0.4f,0.05f),
 | 
					            new CurvePoint(0.4f,0.05f),
 | 
				
			||||||
| 
						 | 
					@ -179,6 +184,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                    // Any exceptions in that will have been reported elsewhere in the code by now
 | 
					                    // Any exceptions in that will have been reported elsewhere in the code by now
 | 
				
			||||||
                    avglittersize = 1.0f;
 | 
					                    avglittersize = 1.0f;
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					                avglittersize *= ovulationFactor;
 | 
				
			||||||
                const float yearsBeforeMenopause = 6.0f;
 | 
					                const float yearsBeforeMenopause = 6.0f;
 | 
				
			||||||
                opcache = (int)(RaceCyclesPerYear() *
 | 
					                opcache = (int)(RaceCyclesPerYear() *
 | 
				
			||||||
                    avglittersize *
 | 
					                    avglittersize *
 | 
				
			||||||
| 
						 | 
					@ -470,6 +476,15 @@ namespace RJW_Menstruation
 | 
				
			||||||
                return !eggs.NullOrEmpty();
 | 
					                return !eggs.NullOrEmpty();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public int EggLifespanHours
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return eggLifeSpanHours;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public virtual bool IsDangerDay
 | 
					        public virtual bool IsDangerDay
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
| 
						 | 
					@ -483,7 +498,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                    case Stage.Ovulatory:
 | 
					                    case Stage.Ovulatory:
 | 
				
			||||||
                        return true;
 | 
					                        return true;
 | 
				
			||||||
                    case Stage.Luteal:
 | 
					                    case Stage.Luteal:
 | 
				
			||||||
                        return curStageHrs < Props.eggLifespanDays * 24;
 | 
					                        return curStageHrs < EggLifespanHours * 24;
 | 
				
			||||||
                    default:
 | 
					                    default:
 | 
				
			||||||
                        return false;
 | 
					                        return false;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -606,6 +621,28 @@ namespace RJW_Menstruation
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Notify_UpdatedGenes()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            eggLifeSpanHours = Props.eggLifespanDays * 24;
 | 
				
			||||||
 | 
					            estrusLevel = Props.concealedEstrus ? EstrusLevel.Concealed : EstrusLevel.Visible;
 | 
				
			||||||
 | 
					            ovulationFactor = 1f;
 | 
				
			||||||
 | 
					            noBleeding = false;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if (Pawn.genes == null || !ModsConfig.BiotechActive) return;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if (Pawn.genes.HasGene(VariousDefOf.ShortEggLifetime)) eggLifeSpanHours = eggLifeSpanHours * 3 / 4;
 | 
				
			||||||
 | 
					            else if (Pawn.genes.HasGene(VariousDefOf.DoubleEggLifetime)) eggLifeSpanHours *= 2;
 | 
				
			||||||
 | 
					            else if (Pawn.genes.HasGene(VariousDefOf.QuadEggLifetime)) eggLifeSpanHours *= 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (Pawn.genes.HasGene(VariousDefOf.NeverEstrus)) estrusLevel = EstrusLevel.None;
 | 
				
			||||||
 | 
					            else if (Pawn.genes.HasGene(VariousDefOf.FullEstrus)) estrusLevel = EstrusLevel.Visible;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (Pawn.genes.HasGene(VariousDefOf.DoubleOvulation)) ovulationFactor = 2f;
 | 
				
			||||||
 | 
					            else if (Pawn.genes.HasGene(VariousDefOf.QuadOvulation)) ovulationFactor = 4f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            noBleeding = Pawn.genes.HasGene(VariousDefOf.NoBleeding);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public bool ShouldSimulate()
 | 
					        public bool ShouldSimulate()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!Configurations.EnableAnimalCycle && Pawn.IsAnimal()) return false;
 | 
					            if (!Configurations.EnableAnimalCycle && Pawn.IsAnimal()) return false;
 | 
				
			||||||
| 
						 | 
					@ -636,12 +673,12 @@ namespace RJW_Menstruation
 | 
				
			||||||
                if (Pregnancy != null && curStage != Stage.Pregnant)
 | 
					                if (Pregnancy != null && curStage != Stage.Pregnant)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    Log.Warning($"{Pawn}'s womb has a pregnancy, but was not in the pregnant stage");
 | 
					                    Log.Warning($"{Pawn}'s womb has a pregnancy, but was not in the pregnant stage");
 | 
				
			||||||
                    curStage = Stage.Pregnant;
 | 
					                    GoNextStage(Stage.Pregnant);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                BeforeSimulator();
 | 
					                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())) GoNextStage(Stage.Infertile);
 | 
				
			||||||
                switch (curStage)
 | 
					                switch (curStage)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    case Stage.Follicular:
 | 
					                    case Stage.Follicular:
 | 
				
			||||||
| 
						 | 
					@ -1029,6 +1066,8 @@ namespace RJW_Menstruation
 | 
				
			||||||
            initError = true;
 | 
					            initError = true;
 | 
				
			||||||
            Props = (CompProperties_Menstruation)props;
 | 
					            Props = (CompProperties_Menstruation)props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Notify_UpdatedGenes();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (Props.infertile)
 | 
					            if (Props.infertile)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (cums == null) cums = new List<Cum>();
 | 
					                if (cums == null) cums = new List<Cum>();
 | 
				
			||||||
| 
						 | 
					@ -1101,6 +1140,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                avglittersize = 1.0f;
 | 
					                avglittersize = 1.0f;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            avglittersize *= ovulationFactor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            float fertStartAge = Pawn.RaceProps.lifeStageAges?.Find(stage => stage.def.reproductive)?.minAge ?? 0.0f;
 | 
					            float fertStartAge = Pawn.RaceProps.lifeStageAges?.Find(stage => stage.def.reproductive)?.minAge ?? 0.0f;
 | 
				
			||||||
            float fertEndAge = Pawn.RaceProps.lifeExpectancy * (Pawn.IsAnimal() ? RJWPregnancySettings.fertility_endage_female_animal : RJWPregnancySettings.fertility_endage_female_humanlike);
 | 
					            float fertEndAge = Pawn.RaceProps.lifeExpectancy * (Pawn.IsAnimal() ? RJWPregnancySettings.fertility_endage_female_animal : RJWPregnancySettings.fertility_endage_female_humanlike);
 | 
				
			||||||
| 
						 | 
					@ -1160,7 +1200,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                case Stage.Ovulatory:
 | 
					                case Stage.Ovulatory:
 | 
				
			||||||
                    return true;
 | 
					                    return true;
 | 
				
			||||||
                case Stage.Luteal:
 | 
					                case Stage.Luteal:
 | 
				
			||||||
                    return curStageHrs < Props.eggLifespanDays * 24;
 | 
					                    return curStageHrs < EggLifespanHours * 24;
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1169,12 +1209,13 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public EstrusLevel GetEstrusLevel()
 | 
					        public EstrusLevel GetEstrusLevel()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!ShouldBeInEstrus()) return EstrusLevel.None;
 | 
					            if (!ShouldBeInEstrus()) return EstrusLevel.None;
 | 
				
			||||||
            else return Props.concealedEstrus ? EstrusLevel.Concealed : EstrusLevel.Visible;
 | 
					            else return estrusLevel;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void SetEstrus()
 | 
					        public void SetEstrus()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Hediff hediff = HediffMaker.MakeHediff(Props.concealedEstrus ? VariousDefOf.Hediff_Estrus_Concealed : VariousDefOf.Hediff_Estrus, Pawn);
 | 
					            if (estrusLevel == EstrusLevel.None) return;
 | 
				
			||||||
 | 
					            Hediff hediff = HediffMaker.MakeHediff(estrusLevel == EstrusLevel.Concealed ? VariousDefOf.Hediff_Estrus_Concealed : VariousDefOf.Hediff_Estrus, Pawn);
 | 
				
			||||||
            Pawn.health.AddHediff(hediff);
 | 
					            Pawn.health.AddHediff(hediff);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1256,8 +1297,19 @@ namespace RJW_Menstruation
 | 
				
			||||||
                    if (Configurations.Debug) Log.Message($"Implanting fertilized egg of {Pawn} into {parent}, father {egg.fertilizer}");
 | 
					                    if (Configurations.Debug) Log.Message($"Implanting fertilized egg of {Pawn} into {parent}, father {egg.fertilizer}");
 | 
				
			||||||
                    if (pregnancy != null)
 | 
					                    if (pregnancy != null)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        // TODO: Modified Biotech pregnancy
 | 
					                        if (Configurations.PregnancySource == Configurations.PregnancyType.Biotech && Configurations.EnableBiotechTwins && Configurations.EnableHeteroOvularTwins)
 | 
				
			||||||
                        if (Configurations.PregnancySource == Configurations.PregnancyType.MultiplePregnancy && Configurations.EnableHeteroOvularTwins)
 | 
					                        {
 | 
				
			||||||
 | 
					                            if (Configurations.Debug) Log.Message($"Adding to existing Biotech pregnancy {pregnancy}");
 | 
				
			||||||
 | 
					                            HediffComp_PregeneratedBabies comp = pregnancy.TryGetComp<HediffComp_PregeneratedBabies>();
 | 
				
			||||||
 | 
					                            if (comp == null) Log.Warning($"Trying to add Biotech egg to {Pawn}'s pregnancy without a pregenerated baby comp: {pregnancy}");
 | 
				
			||||||
 | 
					                            else
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                comp.AddNewBaby(Pawn, egg.fertilizer);
 | 
				
			||||||
 | 
					                                pregnant = true;
 | 
				
			||||||
 | 
					                                deadeggs.Add(egg);
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        else if (Configurations.PregnancySource == Configurations.PregnancyType.MultiplePregnancy && Configurations.EnableHeteroOvularTwins)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            if (pregnancy is Hediff_MultiplePregnancy h)
 | 
					                            if (pregnancy is Hediff_MultiplePregnancy h)
 | 
				
			||||||
                            {
 | 
					                            {
 | 
				
			||||||
| 
						 | 
					@ -1299,8 +1351,12 @@ namespace RJW_Menstruation
 | 
				
			||||||
                            case Configurations.PregnancyType.Biotech:
 | 
					                            case Configurations.PregnancyType.Biotech:
 | 
				
			||||||
                                if (Configurations.Debug) Log.Message($"Creating new biotech pregnancy");
 | 
					                                if (Configurations.Debug) Log.Message($"Creating new biotech pregnancy");
 | 
				
			||||||
                                pregnancy = HediffMaker.MakeHediff(HediffDefOf.PregnantHuman, Pawn);
 | 
					                                pregnancy = HediffMaker.MakeHediff(HediffDefOf.PregnantHuman, Pawn);
 | 
				
			||||||
 | 
					                                if(Configurations.EnableBiotechTwins)
 | 
				
			||||||
 | 
					                                    pregnancy.TryGetComp<HediffComp_PregeneratedBabies>().AddNewBaby(Pawn, egg.fertilizer);
 | 
				
			||||||
                                ((Hediff_Pregnant)pregnancy).SetParents(Pawn, egg.fertilizer, PregnancyUtility.GetInheritedGeneSet(egg.fertilizer, Pawn));
 | 
					                                ((Hediff_Pregnant)pregnancy).SetParents(Pawn, egg.fertilizer, PregnancyUtility.GetInheritedGeneSet(egg.fertilizer, Pawn));
 | 
				
			||||||
                                Pawn.health.AddHediff(pregnancy);
 | 
					                                Pawn.health.AddHediff(pregnancy);
 | 
				
			||||||
 | 
					                                pregnant = true;
 | 
				
			||||||
 | 
					                                deadeggs.Add(egg);
 | 
				
			||||||
                                break;
 | 
					                                break;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        if (pregnancy is Hediff_BasePregnancy rjw_preg)
 | 
					                        if (pregnancy is Hediff_BasePregnancy rjw_preg)
 | 
				
			||||||
| 
						 | 
					@ -1320,7 +1376,9 @@ namespace RJW_Menstruation
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (pregnant && (Configurations.PregnancySource != Configurations.PregnancyType.MultiplePregnancy || !Configurations.EnableHeteroOvularTwins))
 | 
					            if (pregnant &&
 | 
				
			||||||
 | 
					                (Configurations.PregnancySource != Configurations.PregnancyType.MultiplePregnancy || !Configurations.EnableHeteroOvularTwins) &&
 | 
				
			||||||
 | 
					                (Configurations.PregnancySource != Configurations.PregnancyType.Biotech || !Configurations.EnableBiotechTwins || !Configurations.EnableHeteroOvularTwins))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                eggs.Clear();
 | 
					                eggs.Clear();
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
| 
						 | 
					@ -1454,25 +1512,27 @@ namespace RJW_Menstruation
 | 
				
			||||||
        protected virtual void OvulatoryAction()
 | 
					        protected virtual void OvulatoryAction()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            estrusflag = false;
 | 
					            estrusflag = false;
 | 
				
			||||||
            int eggnum;
 | 
					            float eggnum;
 | 
				
			||||||
 | 
					            int ovulated;
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                eggnum = Math.Max((int)Rand.ByCurve(Pawn.def.race.litterSizeCurve), 1);
 | 
					                eggnum = Math.Max(Rand.ByCurve(Pawn.def.race.litterSizeCurve), 1f);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            catch (NullReferenceException)
 | 
					            catch (NullReferenceException)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                eggnum = 1;
 | 
					                eggnum = 1f;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            catch (ArgumentException e)
 | 
					            catch (ArgumentException e)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Log.Warning($"Invalid litterSizeCurve for {Pawn.def}: {e}");
 | 
					                Log.Warning($"Invalid litterSizeCurve for {Pawn.def}: {e}");
 | 
				
			||||||
                eggnum = 1;
 | 
					                eggnum = 1f;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            eggnum += eggstack;
 | 
					            eggnum *= ovulationFactor;
 | 
				
			||||||
 | 
					            ovulated = (int)eggnum + eggstack;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for (int i = 0; i < eggnum; i++)
 | 
					            for (int i = 0; i < ovulated; i++)
 | 
				
			||||||
                eggs.Add(new Egg((int)(Props.eggLifespanDays * 24 / CycleFactor)));
 | 
					                eggs.Add(new Egg((int)(EggLifespanHours * 24 / CycleFactor)));
 | 
				
			||||||
            ovarypower -= eggnum;
 | 
					            ovarypower -= ovulated;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            eggstack = 0;
 | 
					            eggstack = 0;
 | 
				
			||||||
            if (EggHealth <= 0)
 | 
					            if (EggHealth <= 0)
 | 
				
			||||||
| 
						 | 
					@ -1709,7 +1769,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected void GoFollicularOrBleeding()
 | 
					        protected void GoFollicularOrBleeding()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (Props.bleedingIntervalDays == 0)
 | 
					            if (Props.bleedingIntervalDays == 0 || noBleeding)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                GoNextStage(Stage.Follicular);
 | 
					                GoNextStage(Stage.Follicular);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1739,7 +1799,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                    return (int)(Props.recoveryIntervalDays * 24 * Rand.Range(0.95f, 1.05f));
 | 
					                    return (int)(Props.recoveryIntervalDays * 24 * Rand.Range(0.95f, 1.05f));
 | 
				
			||||||
                case Stage.Pregnant:
 | 
					                case Stage.Pregnant:
 | 
				
			||||||
                    return (int)MenstruationUtility.GestationHours(pregnancy);
 | 
					                    return (int)MenstruationUtility.GestationHours(pregnancy);
 | 
				
			||||||
                default:    // Often unused
 | 
					                default:
 | 
				
			||||||
                    return 1;
 | 
					                    return 1;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                // 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)
 | 
					                    && (averageCycleIntervalHours - hoursToNextCycle) / 2 >= 24 * (Props.follicularIntervalDays + Props.lutealIntervalDays) / cycleSpeed)
 | 
				
			||||||
                    curStage = Stage.Anestrus;
 | 
					                    GoNextStage(Stage.Anestrus);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,14 +75,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 * Rand.Range(-cycleVariability, cycleVariability)) / 2;
 | 
					                hoursToNextCycle = (int)(averageCycleIntervalHours * (1 + Rand.Range(-cycleVariability, cycleVariability))) / 2;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected override void AnestrusAction()
 | 
					        protected override void AnestrusAction()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (hoursToNextCycle <= 0)
 | 
					            if (hoursToNextCycle <= 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                hoursToNextCycle = (int)(averageCycleIntervalHours * Rand.Range(-cycleVariability, cycleVariability));
 | 
					                hoursToNextCycle = (int)(averageCycleIntervalHours * (1 + Rand.Range(-cycleVariability, cycleVariability)));
 | 
				
			||||||
                if (IsBreedingSeason()) GoNextStage(Stage.Follicular);
 | 
					                if (IsBreedingSeason()) GoNextStage(Stage.Follicular);
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,300 @@
 | 
				
			||||||
 | 
					using HarmonyLib;
 | 
				
			||||||
 | 
					using Mono.Cecil.Cil;
 | 
				
			||||||
 | 
					using RimWorld;
 | 
				
			||||||
 | 
					using rjw;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Reflection;
 | 
				
			||||||
 | 
					using System.Reflection.Emit;
 | 
				
			||||||
 | 
					using Verse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace RJW_Menstruation
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class HediffComp_PregeneratedBabies : HediffComp
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public List<Pawn> babies;
 | 
				
			||||||
 | 
					        // Unused, but can't hurt to track
 | 
				
			||||||
 | 
					        protected Dictionary<Pawn, Pawn> enzygoticSiblings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected static readonly MethodInfo RandomLastName = typeof(PregnancyUtility).GetMethod("RandomLastName", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(Pawn), typeof(Pawn), typeof(Pawn) }, null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool HasBaby
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get => !babies.NullOrEmpty();            
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Pawn PopBaby()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (babies.NullOrEmpty()) return null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Pawn firstBaby = babies.First();
 | 
				
			||||||
 | 
					            babies.Remove(firstBaby);
 | 
				
			||||||
 | 
					            return firstBaby;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public override void CompPostPostRemoved()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // At this point in the hediff removal process, the new hediff is already on the pawn
 | 
				
			||||||
 | 
					            // But it is possible that there is no new hediff (be it a birth, miscarrage, or dev edit)
 | 
				
			||||||
 | 
					            base.CompPostPostRemoved();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Send the babies from this comp to the new one
 | 
				
			||||||
 | 
					            switch (parent)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                case Hediff_Pregnant hediff_Pregnant:
 | 
				
			||||||
 | 
					                    Hediff_Labor labor = (Hediff_Labor)Pawn.health.hediffSet.hediffs.Where(hediff => hediff is Hediff_Labor).MaxByWithFallback(hediff => hediff.loadID);
 | 
				
			||||||
 | 
					                    HediffComp_PregeneratedBabies laborcomp = labor?.TryGetComp<HediffComp_PregeneratedBabies>();
 | 
				
			||||||
 | 
					                    if (laborcomp == null) return;
 | 
				
			||||||
 | 
					                    laborcomp.babies = this.babies;
 | 
				
			||||||
 | 
					                    laborcomp.enzygoticSiblings = this.enzygoticSiblings;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case Hediff_Labor hediff_Labor:
 | 
				
			||||||
 | 
					                    Hediff_LaborPushing pushing = (Hediff_LaborPushing)Pawn.health.hediffSet.hediffs.Where(hediff => hediff is Hediff_LaborPushing).MaxByWithFallback(hediff => hediff.loadID);
 | 
				
			||||||
 | 
					                    HediffComp_PregeneratedBabies pushingcomp = pushing?.TryGetComp<HediffComp_PregeneratedBabies>();
 | 
				
			||||||
 | 
					                    if (pushingcomp == null) return;
 | 
				
			||||||
 | 
					                    pushingcomp.babies = this.babies;
 | 
				
			||||||
 | 
					                    pushingcomp.enzygoticSiblings = this.enzygoticSiblings;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case Hediff_LaborPushing hediff_LaborPushing:
 | 
				
			||||||
 | 
					                    // Nothing to do, the laborpushing transpiler will pick it up
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public override void CompExposeData()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            base.CompExposeData();
 | 
				
			||||||
 | 
					            Scribe_Collections.Look(ref babies, "babies", LookMode.Deep);
 | 
				
			||||||
 | 
					            Scribe_Collections.Look(ref enzygoticSiblings, "enzygoticSiblings", keyLookMode: LookMode.Reference, valueLookMode: LookMode.Reference);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void AddNewBaby(Pawn mother, Pawn father)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (babies == null) babies = new List<Pawn>();
 | 
				
			||||||
 | 
					            PawnKindDef babyPawnKind = PregnancyCommon.BabyPawnKindDecider(mother, father, true);
 | 
				
			||||||
 | 
					            PawnGenerationRequest request = new PawnGenerationRequest
 | 
				
			||||||
 | 
					                (
 | 
				
			||||||
 | 
					                    kind: babyPawnKind,
 | 
				
			||||||
 | 
					                    faction: mother.Faction,
 | 
				
			||||||
 | 
					                    allowDowned: true,
 | 
				
			||||||
 | 
					                    fixedLastName: (string)RandomLastName.Invoke(null, new object[] { mother, mother, xxx.is_human(father) ? father : null }),
 | 
				
			||||||
 | 
					                    forceNoIdeo: true,
 | 
				
			||||||
 | 
					                    forcedEndogenes: PregnancyUtility.GetInheritedGenes(father, mother),
 | 
				
			||||||
 | 
					                    forcedXenotype: XenotypeDefOf.Baseliner,
 | 
				
			||||||
 | 
					                    developmentalStages: DevelopmentalStage.Newborn
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            int division = 1;
 | 
				
			||||||
 | 
					            Pawn firstbaby = null;
 | 
				
			||||||
 | 
					            while (Rand.Chance(Configurations.EnzygoticTwinsChance) && division < Configurations.MaxEnzygoticTwins) division++;
 | 
				
			||||||
 | 
					            if (division > 1 && enzygoticSiblings == null) enzygoticSiblings = new Dictionary<Pawn, Pawn>();
 | 
				
			||||||
 | 
					            for (int i = 0; i < division; i++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Pawn baby = PawnGenerator.GeneratePawn(request);
 | 
				
			||||||
 | 
					                if (baby == null) break;
 | 
				
			||||||
 | 
					                PregnancyCommon.SetupBabyXenotype(mother, father, baby);    // Probably redundant with Biotech post-birth xenotyping
 | 
				
			||||||
 | 
					                baby.Drawer.renderer.graphics.ResolveAllGraphics();
 | 
				
			||||||
 | 
					                if (division > 1)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    if (i == 0)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        firstbaby = baby;
 | 
				
			||||||
 | 
					                        request.FixedGender = baby.gender;
 | 
				
			||||||
 | 
					                        request.ForcedEndogenes = baby.genes?.Endogenes.Select(gene => gene.def).ToList();
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        enzygoticSiblings.Add(baby, firstbaby);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if (baby.story != null)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            baby.story.headType = firstbaby.story.headType;
 | 
				
			||||||
 | 
					                            baby.story.hairDef = firstbaby.story.hairDef;
 | 
				
			||||||
 | 
					                            baby.story.HairColor = firstbaby.story.HairColor;
 | 
				
			||||||
 | 
					                            baby.story.bodyType = firstbaby.story.bodyType;
 | 
				
			||||||
 | 
					                            baby.story.furDef = firstbaby.story.furDef;
 | 
				
			||||||
 | 
					                            baby.story.skinColorOverride = firstbaby.story.skinColorOverride;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if (baby.genes != null)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            baby.genes.SetXenotypeDirect(firstbaby.genes.Xenotype);
 | 
				
			||||||
 | 
					                            baby.genes.xenotypeName = firstbaby.genes.xenotypeName;
 | 
				
			||||||
 | 
					                            baby.genes.iconDef = firstbaby.genes.iconDef;
 | 
				
			||||||
 | 
					                            baby.genes.hybrid = firstbaby.genes.hybrid;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if (baby.IsHAR())
 | 
				
			||||||
 | 
					                            HARCompatibility.CopyHARProperties(baby, firstbaby);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // MultiplePregnancy calls this post-birth because RJW resets private parts
 | 
				
			||||||
 | 
					                        // So xenotype things shouldn't be shared
 | 
				
			||||||
 | 
					                        PregnancyCommon.ProcessIdenticalSibling(baby, firstbaby);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                babies.Add(baby);
 | 
				
			||||||
 | 
					                // These get cleared out later, but setting the relations now will help keep track of things.
 | 
				
			||||||
 | 
					                baby.SetMother(mother);
 | 
				
			||||||
 | 
					                if (mother != father)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    if (father.gender != Gender.Female) baby.SetFather(father);
 | 
				
			||||||
 | 
					                    else baby.relations.AddDirectRelation(PawnRelationDefOf.Parent, father);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [HarmonyPatch(typeof(PregnancyUtility), nameof(PregnancyUtility.ApplyBirthOutcome))]
 | 
				
			||||||
 | 
					    public static class ApplyBirthOutcome_PregeneratedBabies_Patch
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private static Pawn GetPregeneratedBaby(PawnGenerationRequest request, Thing birtherThing)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Don't test for the config set here. We can do it at the functions that call ApplyBirthOutcome
 | 
				
			||||||
 | 
					            // Easier to work out twins that way
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // From e.g. a vat
 | 
				
			||||||
 | 
					            if (!(birtherThing is Pawn mother) || !xxx.is_human(mother))
 | 
				
			||||||
 | 
					                return PawnGenerator.GeneratePawn(request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // No babies found. Could be an unmodified pregnancy
 | 
				
			||||||
 | 
					            HediffComp_PregeneratedBabies comp = mother.health.hediffSet.GetFirstHediff<Hediff_LaborPushing>()?.TryGetComp<HediffComp_PregeneratedBabies>();
 | 
				
			||||||
 | 
					            if (comp == null || !comp.HasBaby)
 | 
				
			||||||
 | 
					                return PawnGenerator.GeneratePawn(request);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Pawn baby = comp.PopBaby();
 | 
				
			||||||
 | 
					            if (baby == null) return PawnGenerator.GeneratePawn(request);   // Shouldn't happen
 | 
				
			||||||
 | 
					            baby.ageTracker.AgeBiologicalTicks = 0;
 | 
				
			||||||
 | 
					            baby.ageTracker.AgeChronologicalTicks = 0;
 | 
				
			||||||
 | 
					            baby.babyNamingDeadline = Find.TickManager.TicksGame + GenDate.TicksPerDay;
 | 
				
			||||||
 | 
					            if (request.ForceDead) baby.Kill(null, null);
 | 
				
			||||||
 | 
					            return baby;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private static readonly MethodInfo ApplyBirthOutcome = typeof(PregnancyUtility).GetMethod(nameof(PregnancyUtility.ApplyBirthOutcome));
 | 
				
			||||||
 | 
					        private static readonly int birtherThing = ApplyBirthOutcome.GetParameters().FirstIndexOf(parameter => parameter.Name == "birtherThing" && parameter.ParameterType == typeof(Thing));
 | 
				
			||||||
 | 
					        private static readonly MethodInfo GeneratePawn = typeof(PawnGenerator).GetMethod(nameof(PawnGenerator.GeneratePawn), new Type[] {typeof (PawnGenerationRequest)});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (birtherThing < 0) throw new InvalidOperationException("Could not locate index of birtherThing");
 | 
				
			||||||
 | 
					            if (GeneratePawn == null || GeneratePawn.ReturnType != typeof(Pawn)) throw new InvalidOperationException("GeneratePawn not found");
 | 
				
			||||||
 | 
					            foreach (CodeInstruction instruction in instructions)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (instruction.Calls(GeneratePawn))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    yield return new CodeInstruction(OpCodes.Ldarg, birtherThing);
 | 
				
			||||||
 | 
					                    yield return CodeInstruction.Call(typeof(ApplyBirthOutcome_PregeneratedBabies_Patch), nameof(GetPregeneratedBaby));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else yield return instruction;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [HarmonyPatch(typeof(Hediff_LaborPushing), nameof(Hediff_LaborPushing.PreRemoved))]
 | 
				
			||||||
 | 
					    public static class Hediff_LaborPushing_PreRemoved_Patch
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private static Thing ApplyBirthLoop(OutcomeChance outcome, float quality, Precept_Ritual ritual, List<GeneDef> genes, Pawn geneticMother, Thing birtherThing, Pawn father, Pawn doctor, LordJob_Ritual lordJobRitual, RitualRoleAssignments assignments)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (birtherThing is Pawn mother)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                HediffComp_PregeneratedBabies comp = mother.health.hediffSet.GetFirstHediff<Hediff_LaborPushing>().TryGetComp<HediffComp_PregeneratedBabies>();
 | 
				
			||||||
 | 
					                if (comp?.HasBaby ?? false)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    OutcomeChance thisOutcome = outcome;
 | 
				
			||||||
 | 
					                    Precept_Ritual precept_Ritual = (Precept_Ritual)comp.Pawn.Ideo.GetPrecept(PreceptDefOf.ChildBirth);
 | 
				
			||||||
 | 
					                    float birthQuality = PregnancyUtility.GetBirthQualityFor(mother);
 | 
				
			||||||
 | 
					                    do
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        Pawn baby = comp.babies[0];
 | 
				
			||||||
 | 
					                        Pawn thisFather = baby.GetFather();
 | 
				
			||||||
 | 
					                        if (thisFather == null) thisFather = father;
 | 
				
			||||||
 | 
					                        baby.relations.ClearAllRelations();   // To keep ApplyBirthOutcome from erroring when it tries to set up relations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        PregnancyUtility.ApplyBirthOutcome(thisOutcome, quality, ritual, genes, geneticMother, birtherThing, thisFather, doctor, lordJobRitual, assignments);
 | 
				
			||||||
 | 
					                        // No more babies if mom dies halfway through. Unrealistic maybe, but saves a lot of headache in ApplyBirthOutcome
 | 
				
			||||||
 | 
					                        if (mother.health.Dead) break;
 | 
				
			||||||
 | 
					                        thisOutcome = ((RitualOutcomeEffectWorker_ChildBirth)precept_Ritual.outcomeEffect).GetOutcome(birthQuality, null);
 | 
				
			||||||
 | 
					                    } while (comp.HasBaby);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // PreRemoved doesn't use the return value
 | 
				
			||||||
 | 
					                    return null;
 | 
				
			||||||
 | 
					                }    
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return PregnancyUtility.ApplyBirthOutcome(outcome, quality, ritual, genes, geneticMother, birtherThing, father, doctor, lordJobRitual, assignments);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private static readonly MethodInfo ApplyBirthOutcome = typeof(PregnancyUtility).GetMethod(nameof(PregnancyUtility.ApplyBirthOutcome),
 | 
				
			||||||
 | 
					            new Type[] {typeof(OutcomeChance), typeof(float), typeof(Precept_Ritual), typeof(List<GeneDef>), typeof(Pawn), typeof(Thing), typeof(Pawn), typeof(Pawn), typeof(LordJob_Ritual), typeof(RitualRoleAssignments)});
 | 
				
			||||||
 | 
					        public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (ApplyBirthOutcome == null || ApplyBirthOutcome.ReturnType != typeof(Thing)) throw new InvalidOperationException("ApplyBirthOutcome not found");
 | 
				
			||||||
 | 
					            foreach (CodeInstruction instruction in instructions)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (instruction.Calls(ApplyBirthOutcome))
 | 
				
			||||||
 | 
					                    yield return CodeInstruction.Call(typeof(Hediff_LaborPushing_PreRemoved_Patch), nameof(Hediff_LaborPushing_PreRemoved_Patch.ApplyBirthLoop));
 | 
				
			||||||
 | 
					                else yield return instruction;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [HarmonyPatch(typeof(RitualOutcomeEffectWorker_ChildBirth), nameof (RitualOutcomeEffectWorker_ChildBirth.Apply))]
 | 
				
			||||||
 | 
					    public static class Ritual_ChildBirth_Apply_Patch
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private static Thing ApplyBirthLoop(OutcomeChance outcome, float quality, Precept_Ritual ritual, List<GeneDef> genes, Pawn geneticMother, Thing birtherThing, Pawn father, Pawn doctor, LordJob_Ritual lordJobRitual, RitualRoleAssignments assignments)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (birtherThing is Pawn mother)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                HediffComp_PregeneratedBabies comp = mother.health.hediffSet.GetFirstHediff<Hediff_LaborPushing>().TryGetComp<HediffComp_PregeneratedBabies>();
 | 
				
			||||||
 | 
					                if (comp?.HasBaby ?? false)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // Much the same as the other one
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // Don't reroll the outcome every time, I think
 | 
				
			||||||
 | 
					                    // This is all one ritual, so every baby has the same ritual outcome
 | 
				
			||||||
 | 
					                    // I don't think this will add the ritual memory every time?
 | 
				
			||||||
 | 
					                    // Though even if it does, that's probably okay. More babies more memories after all
 | 
				
			||||||
 | 
					                    do
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        Pawn baby = comp.babies[0];
 | 
				
			||||||
 | 
					                        Pawn thisFather = baby.GetFather();
 | 
				
			||||||
 | 
					                        if (thisFather == null) thisFather = father;
 | 
				
			||||||
 | 
					                        baby.relations.ClearAllRelations();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        PregnancyUtility.ApplyBirthOutcome(outcome, quality, ritual, genes, geneticMother, birtherThing, thisFather, doctor, lordJobRitual, assignments);
 | 
				
			||||||
 | 
					                        if (mother.health.Dead) break;
 | 
				
			||||||
 | 
					                    } while (comp.HasBaby);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // The ritual version doesn't use the return value, either
 | 
				
			||||||
 | 
					                    return null;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return PregnancyUtility.ApplyBirthOutcome(outcome, quality, ritual, genes, geneticMother, birtherThing, father, doctor, lordJobRitual, assignments);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        private static readonly MethodInfo ApplyBirthOutcome = typeof(PregnancyUtility).GetMethod(nameof(PregnancyUtility.ApplyBirthOutcome),
 | 
				
			||||||
 | 
					            new Type[] { typeof(OutcomeChance), typeof(float), typeof(Precept_Ritual), typeof(List<GeneDef>), typeof(Pawn), typeof(Thing), typeof(Pawn), typeof(Pawn), typeof(LordJob_Ritual), typeof(RitualRoleAssignments) });
 | 
				
			||||||
 | 
					        public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (ApplyBirthOutcome == null || ApplyBirthOutcome.ReturnType != typeof(Thing)) throw new InvalidOperationException("ApplyBirthOutcome not found");
 | 
				
			||||||
 | 
					            foreach (var instruction in instructions)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (instruction.Calls(ApplyBirthOutcome))
 | 
				
			||||||
 | 
					                    yield return CodeInstruction.Call(typeof(Ritual_ChildBirth_Apply_Patch), nameof(Ritual_ChildBirth_Apply_Patch.ApplyBirthLoop));
 | 
				
			||||||
 | 
					                else yield return instruction;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // HAR patches ApplyBirthOutcome to produce multiple babies based on the mother's littersize. But the pregenerated babies system already makes multiple babies
 | 
				
			||||||
 | 
					    // So make it always consider the mother to have one baby
 | 
				
			||||||
 | 
					    public static class HAR_LitterSize_Undo
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static void Postfix(ref int __result, Pawn mother)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (Configurations.PregnancySource != Configurations.PregnancyType.Biotech || !Configurations.EnableBiotechTwins) return;
 | 
				
			||||||
 | 
					            __result = 0;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -73,6 +73,29 @@ namespace RJW_Menstruation
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Obsolete("This method is obsolete and can cause ambiguity. Use GetMenstruationCompFromVagina or GetMenstruationCompFromPregnancy instead.", true)]
 | 
				
			||||||
 | 
					        public static HediffComp_Menstruation GetMenstruationComp(Hediff hediff)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            switch (hediff)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                case Hediff_BasePregnancy rjwPreg:
 | 
				
			||||||
 | 
					                    return rjwPreg.GetMenstruationCompFromPregnancy();
 | 
				
			||||||
 | 
					                case Hediff_Pregnant vanillaPreg:
 | 
				
			||||||
 | 
					                    return vanillaPreg.GetMenstruationCompFromPregnancy();
 | 
				
			||||||
 | 
					                case Hediff_Labor vanillaLabor:
 | 
				
			||||||
 | 
					                    return vanillaLabor.GetMenstruationCompFromPregnancy();
 | 
				
			||||||
 | 
					                case Hediff_LaborPushing vanillaLaborPushing:
 | 
				
			||||||
 | 
					                    return vanillaLaborPushing.GetMenstruationCompFromPregnancy();
 | 
				
			||||||
 | 
					                case Hediff_PartBaseNatural rjwNatrual:
 | 
				
			||||||
 | 
					                    return rjwNatrual.GetMenstruationCompFromVagina();
 | 
				
			||||||
 | 
					                case Hediff_PartBaseArtifical rjwArtificial:
 | 
				
			||||||
 | 
					                    return rjwArtificial.GetMenstruationCompFromVagina();
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    Log.Warning("Obsolete GetMenstruationComp called with unknown hediff. Ensure your submods are up to date.");
 | 
				
			||||||
 | 
					                    return null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static HediffComp_Anus GetAnusComp(this Hediff hediff)
 | 
					        public static HediffComp_Anus GetAnusComp(this Hediff hediff)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (hediff is Hediff_PartBaseNatural || hediff is Hediff_PartBaseArtifical)
 | 
					            if (hediff is Hediff_PartBaseNatural || hediff is Hediff_PartBaseArtifical)
 | 
				
			||||||
| 
						 | 
					@ -92,13 +115,25 @@ namespace RJW_Menstruation
 | 
				
			||||||
            if (hediff is Hediff_MechanoidPregnancy)
 | 
					            if (hediff is Hediff_MechanoidPregnancy)
 | 
				
			||||||
                return ContentFinder<Texture2D>.Get(("Womb/Mechanoid_Fluid"), true);
 | 
					                return ContentFinder<Texture2D>.Get(("Womb/Mechanoid_Fluid"), true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ThingDef babydef = comp.Pawn.def;   // TODO: Pregenerated babies
 | 
					 | 
				
			||||||
            float gestationProgress = comp.StageProgress;
 | 
					            float gestationProgress = comp.StageProgress;
 | 
				
			||||||
            int babycount = hediff is Hediff_BasePregnancy preg ? preg.babies.Count : 1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (hediff is Hediff_BasePregnancy h)
 | 
					            ThingDef babydef;
 | 
				
			||||||
 | 
					            int babycount;
 | 
				
			||||||
 | 
					            HediffComp_PregeneratedBabies babiescomp = hediff?.TryGetComp<HediffComp_PregeneratedBabies>();
 | 
				
			||||||
 | 
					            if (hediff is Hediff_BasePregnancy preg)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                babydef = h.babies?.FirstOrDefault()?.def ?? ThingDefOf.Human;
 | 
					                babydef = preg.babies?.FirstOrDefault()?.def ?? ThingDefOf.Human;
 | 
				
			||||||
 | 
					                babycount = preg.babies?.Count ?? 1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if (babiescomp?.HasBaby ?? false)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                babydef = babiescomp.babies.First().def;
 | 
				
			||||||
 | 
					                babycount = babiescomp.babies.Count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                babydef = comp.Pawn.def;
 | 
				
			||||||
 | 
					                babycount = 1;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            string fetustex = babydef.GetModExtension<PawnDNAModExtension>()?.fetusTexPath ?? "Fetus/Fetus_Default";
 | 
					            string fetustex = babydef.GetModExtension<PawnDNAModExtension>()?.fetusTexPath ?? "Fetus/Fetus_Default";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,9 +13,6 @@ 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();
 | 
				
			||||||
| 
						 | 
					@ -82,48 +79,6 @@ namespace RJW_Menstruation
 | 
				
			||||||
            breastcomp?.GaveBirth();
 | 
					            breastcomp?.GaveBirth();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string GetBabyInfo()
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (babies.NullOrEmpty())
 | 
					 | 
				
			||||||
                return "Null";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            StringBuilder res = new StringBuilder();
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            IEnumerable<Pawn> babiesdistinct = babies.Distinct(new RaceComparer());
 | 
					 | 
				
			||||||
            int iteration = 0;
 | 
					 | 
				
			||||||
            foreach (Pawn baby in babiesdistinct)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                int num = babies.Where(x => x.def.Equals(baby.def)).Count();
 | 
					 | 
				
			||||||
                if (iteration > 0) res.Append(", ");
 | 
					 | 
				
			||||||
                res.AppendFormat("{0} {1}", num, baby.def.label);
 | 
					 | 
				
			||||||
                iteration++;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            res.AppendFormat(" {0}", Translations.Dialog_WombInfo02);
 | 
					 | 
				
			||||||
            return res.ToString();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public string GetFatherInfo()
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (babies.NullOrEmpty())
 | 
					 | 
				
			||||||
                return "Null";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            StringBuilder res = new StringBuilder();
 | 
					 | 
				
			||||||
            res.AppendFormat("{0}: ", Translations.Dialog_WombInfo03);
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            if (!is_parent_known && Configurations.InfoDetail != Configurations.DetailLevel.All)
 | 
					 | 
				
			||||||
                return res.Append(Translations.Dialog_FatherUnknown).ToString();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            IEnumerable<Pawn> babiesdistinct = babies.Distinct(new FatherComparer(pawn));
 | 
					 | 
				
			||||||
            int iteration = 0;
 | 
					 | 
				
			||||||
            foreach (Pawn baby in babiesdistinct)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (iteration > 0) res.Append(", ");
 | 
					 | 
				
			||||||
                res.Append(Utility.GetFather(baby, pawn)?.LabelShort ?? Translations.Dialog_FatherUnknown);
 | 
					 | 
				
			||||||
                iteration++;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return res.ToString();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private void HumanlikeBirth(Pawn baby)
 | 
					        private void HumanlikeBirth(Pawn baby)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Pawn mother = pawn; Pawn father = Utility.GetFather(baby, pawn);
 | 
					            Pawn mother = pawn; Pawn father = Utility.GetFather(baby, pawn);
 | 
				
			||||||
| 
						 | 
					@ -167,11 +122,12 @@ namespace RJW_Menstruation
 | 
				
			||||||
            if (ModsConfig.BiotechActive)
 | 
					            if (ModsConfig.BiotechActive)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Ugly, but it'll have to do
 | 
					                // Ugly, but it'll have to do
 | 
				
			||||||
                OutcomeChance bestOutcome = RitualOutcomeEffectDefOf.ChildBirth.outcomeChances.Find(chance => chance.positivityIndex == 1);
 | 
					                OutcomeChance bestOutcome = RitualOutcomeEffectDefOf.ChildBirth.BestOutcome;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                string label = bestOutcome.label;
 | 
					                string label = bestOutcome.label;
 | 
				
			||||||
                string description = bestOutcome.description.Formatted(mother.Named("MOTHER"));
 | 
					                string description = bestOutcome.description.Formatted(mother.Named("MOTHER"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                baby.babyNamingDeadline = Find.TickManager.TicksGame + GenDate.TicksPerDay;
 | 
				
			||||||
                ChoiceLetter_BabyBirth choiceLetter_BabyBirth = (ChoiceLetter_BabyBirth)LetterMaker.MakeLetter(
 | 
					                ChoiceLetter_BabyBirth choiceLetter_BabyBirth = (ChoiceLetter_BabyBirth)LetterMaker.MakeLetter(
 | 
				
			||||||
                    label, description, LetterDefOf.BabyBirth, baby
 | 
					                    label, description, LetterDefOf.BabyBirth, baby
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
| 
						 | 
					@ -212,65 +168,12 @@ namespace RJW_Menstruation
 | 
				
			||||||
            //baby.story.birthLastName = last_name;
 | 
					            //baby.story.birthLastName = last_name;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
         protected void CopyBodyPartProperties(Hediff part, Hediff originalPart)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            CompHediffBodyPart comp = part.TryGetComp<CompHediffBodyPart>();
 | 
					 | 
				
			||||||
            CompHediffBodyPart originalComp = originalPart.TryGetComp<CompHediffBodyPart>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (comp != null && originalComp != null)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                // the string properties should be the same between both pawns anyways, besides the name of the owner
 | 
					 | 
				
			||||||
                part.Severity = originalPart.Severity;
 | 
					 | 
				
			||||||
                comp.SizeBase = originalComp.SizeBase;
 | 
					 | 
				
			||||||
                comp.SizeOwner = originalComp.SizeOwner;
 | 
					 | 
				
			||||||
                comp.EffSize = originalComp.EffSize;
 | 
					 | 
				
			||||||
                comp.FluidAmmount = originalComp.FluidAmmount;
 | 
					 | 
				
			||||||
                comp.FluidModifier = originalComp.FluidModifier;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            HediffComp_Menstruation originalMenstruationComp = originalPart.GetMenstruationCompFromVagina();
 | 
					 | 
				
			||||||
            if (originalMenstruationComp != null)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                part.GetMenstruationCompFromVagina()?.CopyCycleProperties(originalMenstruationComp);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            HediffComp_Breast originalBreastComp = originalPart.GetBreastComp();
 | 
					 | 
				
			||||||
            if (originalBreastComp != null)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                part.GetBreastComp()?.CopyBreastProperties(originalBreastComp);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        protected void CopyBodyPartRecord(Pawn baby, Pawn original, BodyPartRecord babyBPR, BodyPartRecord originalBPR)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (babyBPR == null || originalBPR == null) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            RemoveBabyParts(baby, Genital_Helper.get_PartsHediffList(baby, babyBPR));
 | 
					 | 
				
			||||||
            foreach (Hediff originalPart in Genital_Helper.get_PartsHediffList(original, originalBPR))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                Hediff part = SexPartAdder.MakePart(originalPart.def, baby, babyBPR);
 | 
					 | 
				
			||||||
                CopyBodyPartProperties(part, originalPart);
 | 
					 | 
				
			||||||
                baby.health.AddHediff(part, babyBPR);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Baby is the sibling to be changed, original is the first of the set and the one to copy to the rest.
 | 
					 | 
				
			||||||
        public virtual void ProcessIdenticalSibling(Pawn baby, Pawn original)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            // They'll be the same pawnkind, which lets us make a lot of useful assumptions
 | 
					 | 
				
			||||||
            // However, some RNG might still be involved in genital generation (e.g. futas), so the easiest method is to clear out and re-generate
 | 
					 | 
				
			||||||
            // A bit wasteful since Hediff_BasePregnancy.PostBirth already redid the genitals
 | 
					 | 
				
			||||||
            CopyBodyPartRecord(baby, original, Genital_Helper.get_genitalsBPR(baby), Genital_Helper.get_genitalsBPR(original));
 | 
					 | 
				
			||||||
            CopyBodyPartRecord(baby, original, Genital_Helper.get_breastsBPR(baby), Genital_Helper.get_breastsBPR(original));
 | 
					 | 
				
			||||||
            CopyBodyPartRecord(baby, original, Genital_Helper.get_uddersBPR(baby), Genital_Helper.get_uddersBPR(original));
 | 
					 | 
				
			||||||
            CopyBodyPartRecord(baby, original, Genital_Helper.get_anusBPR(baby), Genital_Helper.get_anusBPR(original));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public override void PostBirth(Pawn mother, Pawn father, Pawn baby)
 | 
					        public override void PostBirth(Pawn mother, Pawn father, Pawn baby)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            base.PostBirth(mother, father, baby);
 | 
					            base.PostBirth(mother, father, baby);
 | 
				
			||||||
            // Has to happen on birth since RJW redoes the genitals at birth
 | 
					            // Has to happen on birth since RJW redoes the genitals at birth
 | 
				
			||||||
            if (!enzygoticSiblings.NullOrEmpty() && enzygoticSiblings.TryGetValue(baby, out Pawn original) && baby != original)
 | 
					            if (!enzygoticSiblings.NullOrEmpty() && enzygoticSiblings.TryGetValue(baby, out Pawn original) && baby != original)
 | 
				
			||||||
                ProcessIdenticalSibling(baby, original);
 | 
					                PregnancyCommon.ProcessIdenticalSibling(baby, original);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // From RJW's trait code
 | 
					        // From RJW's trait code
 | 
				
			||||||
| 
						 | 
					@ -411,7 +314,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                allowAddictions: false,
 | 
					                allowAddictions: false,
 | 
				
			||||||
                relationWithExtraPawnChanceFactor: 0,
 | 
					                relationWithExtraPawnChanceFactor: 0,
 | 
				
			||||||
                fixedLastName: lastname,
 | 
					                fixedLastName: lastname,
 | 
				
			||||||
                kind: BabyPawnKindDecider(mother, father),
 | 
					                kind: PregnancyCommon.BabyPawnKindDecider(mother, father, false),
 | 
				
			||||||
                //fixedIdeo: mother.Ideo,
 | 
					                //fixedIdeo: mother.Ideo,
 | 
				
			||||||
                forbidAnyTitle: true,
 | 
					                forbidAnyTitle: true,
 | 
				
			||||||
                forceNoBackstory: true,
 | 
					                forceNoBackstory: true,
 | 
				
			||||||
| 
						 | 
					@ -428,31 +331,15 @@ namespace RJW_Menstruation
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Pawn baby = GenerateBaby(request, mother, father, parentTraits, traitSeed);
 | 
					                Pawn baby = GenerateBaby(request, mother, father, parentTraits, traitSeed);
 | 
				
			||||||
                if (baby == null) break;
 | 
					                if (baby == null) break;
 | 
				
			||||||
                if (baby.genes != null && ModsConfig.BiotechActive)
 | 
					                PregnancyCommon.SetupBabyXenotype(mother, father, baby);
 | 
				
			||||||
                {
 | 
					                // HAR and some xenotype mods don't randomize graphics until it's rendered
 | 
				
			||||||
                    if (GeneUtility.SameHeritableXenotype(mother, father) && mother.genes.UniqueXenotype)
 | 
					                // So poke it early
 | 
				
			||||||
                    {
 | 
					                baby.Drawer.renderer.graphics.ResolveAllGraphics();
 | 
				
			||||||
                        baby.genes.xenotypeName = mother.genes.xenotypeName;
 | 
					 | 
				
			||||||
                        baby.genes.iconDef = mother.genes.iconDef;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    object[] args = new object[] { mother, father, null };
 | 
					 | 
				
			||||||
                    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.xenotypeName = "Hybrid".Translate();
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                if (division > 1)
 | 
					                if (division > 1)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    if (i == 0)
 | 
					                    if (i == 0)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        if (baby.IsHAR())   // Have HAR determine the first baby's properties
 | 
					
 | 
				
			||||||
                            baby.Drawer.renderer.graphics.ResolveAllGraphics();
 | 
					 | 
				
			||||||
                        firstbaby = baby;
 | 
					                        firstbaby = baby;
 | 
				
			||||||
                        request.FixedGender = baby.gender;
 | 
					                        request.FixedGender = baby.gender;
 | 
				
			||||||
                        request.ForcedEndogenes = baby.genes?.Endogenes.Select(gene => gene.def).ToList();                        
 | 
					                        request.ForcedEndogenes = baby.genes?.Endogenes.Select(gene => gene.def).ToList();                        
 | 
				
			||||||
| 
						 | 
					@ -465,7 +352,10 @@ namespace RJW_Menstruation
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            baby.story.headType = firstbaby.story.headType;
 | 
					                            baby.story.headType = firstbaby.story.headType;
 | 
				
			||||||
                            baby.story.hairDef = firstbaby.story.hairDef;
 | 
					                            baby.story.hairDef = firstbaby.story.hairDef;
 | 
				
			||||||
 | 
					                            baby.story.HairColor = firstbaby.story.HairColor;
 | 
				
			||||||
                            baby.story.bodyType = firstbaby.story.bodyType;
 | 
					                            baby.story.bodyType = firstbaby.story.bodyType;
 | 
				
			||||||
 | 
					                            baby.story.furDef = firstbaby.story.furDef;
 | 
				
			||||||
 | 
					                            baby.story.skinColorOverride = firstbaby.story.skinColorOverride;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (baby.genes != null && ModsConfig.BiotechActive)
 | 
					                        if (baby.genes != null && ModsConfig.BiotechActive)
 | 
				
			||||||
| 
						 | 
					@ -519,174 +409,6 @@ namespace RJW_Menstruation
 | 
				
			||||||
            return baby;
 | 
					            return baby;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        /// Decide pawnkind from mother and father <para/>
 | 
					 | 
				
			||||||
        /// Come from RJW
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        /// <param name="mother"></param>
 | 
					 | 
				
			||||||
        /// <param name="father"></param>
 | 
					 | 
				
			||||||
        /// <returns></returns>
 | 
					 | 
				
			||||||
        public PawnKindDef BabyPawnKindDecider(Pawn mother, Pawn father)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            PawnKindDef motherKindDef = Utility.GetRacesPawnKind(mother);
 | 
					 | 
				
			||||||
            PawnKindDef fatherKindDef = Utility.GetRacesPawnKind(father);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            PawnKindDef spawn_kind_def = motherKindDef;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            int flag = 0;
 | 
					 | 
				
			||||||
            if (xxx.is_human(mother)) flag += 2;
 | 
					 | 
				
			||||||
            if (xxx.is_human(father)) flag += 1;
 | 
					 | 
				
			||||||
            //Mother - Father = Flag
 | 
					 | 
				
			||||||
            //Human  - Human  =  3
 | 
					 | 
				
			||||||
            //Human  - Animal =  2
 | 
					 | 
				
			||||||
            //Animal - Human  =  1
 | 
					 | 
				
			||||||
            //Animal - Animal =  0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            switch (flag)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                case 3:
 | 
					 | 
				
			||||||
                    if (!Rand.Chance(RJWPregnancySettings.humanlike_DNA_from_mother)) spawn_kind_def = fatherKindDef;
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                case 2:
 | 
					 | 
				
			||||||
                    if (RJWPregnancySettings.bestiality_DNA_inheritance == 0f) spawn_kind_def = fatherKindDef;
 | 
					 | 
				
			||||||
                    else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                case 1:
 | 
					 | 
				
			||||||
                    if (RJWPregnancySettings.bestiality_DNA_inheritance == 1f) spawn_kind_def = fatherKindDef;
 | 
					 | 
				
			||||||
                    else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                case 0:
 | 
					 | 
				
			||||||
                    if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            bool IsAndroidmother = AndroidsCompatibility.IsAndroid(mother);
 | 
					 | 
				
			||||||
            bool IsAndroidfather = AndroidsCompatibility.IsAndroid(father);
 | 
					 | 
				
			||||||
            if (IsAndroidmother && !IsAndroidfather)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                spawn_kind_def = fatherKindDef;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (!IsAndroidmother && IsAndroidfather)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                spawn_kind_def = motherKindDef;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            string MotherRaceName = "";
 | 
					 | 
				
			||||||
            string FatherRaceName = "";
 | 
					 | 
				
			||||||
            MotherRaceName = motherKindDef?.race?.defName;
 | 
					 | 
				
			||||||
            PawnKindDef non_hybrid_kind_def = spawn_kind_def;
 | 
					 | 
				
			||||||
            if (father != null)
 | 
					 | 
				
			||||||
                FatherRaceName = fatherKindDef?.race?.defName;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (FatherRaceName != "" && Configurations.UseHybridExtention)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                spawn_kind_def = GetHybrid(father, mother);
 | 
					 | 
				
			||||||
                //Log.Message("pawnkind: " + spawn_kind_def?.defName);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (MotherRaceName != FatherRaceName && FatherRaceName != "")
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (!Configurations.UseHybridExtention || spawn_kind_def == null)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    spawn_kind_def = non_hybrid_kind_def;
 | 
					 | 
				
			||||||
                    IEnumerable<RaceGroupDef> groups = DefDatabase<RaceGroupDef>.AllDefs.Where(x => !(x.hybridRaceParents.NullOrEmpty() || x.hybridChildKindDef.NullOrEmpty()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    //ModLog.Message(" found custom RaceGroupDefs " + groups.Count());
 | 
					 | 
				
			||||||
                    foreach (RaceGroupDef t in groups)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        if ((t.hybridRaceParents.Contains(MotherRaceName) && t.hybridRaceParents.Contains(FatherRaceName))
 | 
					 | 
				
			||||||
                            || (t.hybridRaceParents.Contains("Any") && (t.hybridRaceParents.Contains(MotherRaceName) || t.hybridRaceParents.Contains(FatherRaceName))))
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            //ModLog.Message(" has hybridRaceParents");
 | 
					 | 
				
			||||||
                            if (t.hybridChildKindDef.Contains("MotherKindDef"))
 | 
					 | 
				
			||||||
                                spawn_kind_def = motherKindDef;
 | 
					 | 
				
			||||||
                            else if (t.hybridChildKindDef.Contains("FatherKindDef") && father != null)
 | 
					 | 
				
			||||||
                                spawn_kind_def = fatherKindDef;
 | 
					 | 
				
			||||||
                            else
 | 
					 | 
				
			||||||
                            {
 | 
					 | 
				
			||||||
                                //ModLog.Message(" trying hybridChildKindDef " + t.defName);
 | 
					 | 
				
			||||||
                                List<PawnKindDef> child_kind_def_list = new List<PawnKindDef>();
 | 
					 | 
				
			||||||
                                child_kind_def_list.AddRange(DefDatabase<PawnKindDef>.AllDefs.Where(x => t.hybridChildKindDef.Contains(x.defName)));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                //ModLog.Message(" found custom hybridChildKindDefs " + t.hybridChildKindDef.Count);
 | 
					 | 
				
			||||||
                                if (!child_kind_def_list.NullOrEmpty())
 | 
					 | 
				
			||||||
                                    spawn_kind_def = child_kind_def_list.RandomElement();
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (!Configurations.UseHybridExtention || spawn_kind_def == null)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                spawn_kind_def = mother.RaceProps?.AnyPawnKind ?? motherKindDef;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (spawn_kind_def.defName.Contains("Nymph"))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                //child is nymph, try to find other PawnKindDef
 | 
					 | 
				
			||||||
                List<PawnKindDef> spawn_kind_def_list = new List<PawnKindDef>();
 | 
					 | 
				
			||||||
                spawn_kind_def_list.AddRange(DefDatabase<PawnKindDef>.AllDefs.Where(x => x.race == spawn_kind_def.race && !x.defName.Contains("Nymph")));
 | 
					 | 
				
			||||||
                //no other PawnKindDef found try mother
 | 
					 | 
				
			||||||
                if (spawn_kind_def_list.NullOrEmpty())
 | 
					 | 
				
			||||||
                    spawn_kind_def_list.AddRange(DefDatabase<PawnKindDef>.AllDefs.Where(x => x.race == motherKindDef.race && !x.defName.Contains("Nymph")));
 | 
					 | 
				
			||||||
                //no other PawnKindDef found try father
 | 
					 | 
				
			||||||
                if (spawn_kind_def_list.NullOrEmpty() && father != null)
 | 
					 | 
				
			||||||
                    spawn_kind_def_list.AddRange(DefDatabase<PawnKindDef>.AllDefs.Where(x => x.race == fatherKindDef.race && !x.defName.Contains("Nymph")));
 | 
					 | 
				
			||||||
                //no other PawnKindDef found fallback to generic colonist
 | 
					 | 
				
			||||||
                if (spawn_kind_def_list.NullOrEmpty())
 | 
					 | 
				
			||||||
                    spawn_kind_def = PawnKindDefOf.Colonist;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (!spawn_kind_def_list.NullOrEmpty()) spawn_kind_def = spawn_kind_def_list.RandomElement();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return spawn_kind_def;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public PawnKindDef GetHybrid(Pawn first, Pawn second)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            PawnKindDef res = null;
 | 
					 | 
				
			||||||
            Pawn opposite = second;
 | 
					 | 
				
			||||||
            HybridInformations info = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (!Configurations.HybridOverride.NullOrEmpty())
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                info = Configurations.HybridOverride.FirstOrDefault(x => x.DefName == first.def?.defName && (x.hybridExtension?.Exists(y => y.DefName == second.def?.defName) ?? false));
 | 
					 | 
				
			||||||
                if (info == null)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    info = Configurations.HybridOverride.FirstOrDefault(x => x.DefName == second.def?.defName && (x.hybridExtension?.Exists(y => y.DefName == first.def?.defName) ?? false));
 | 
					 | 
				
			||||||
                    opposite = first;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (info != null)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                res = info.GetHybridWith(opposite.def.defName) ?? null;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (res != null) return res;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            PawnDNAModExtension dna;
 | 
					 | 
				
			||||||
            dna = first.def.GetModExtension<PawnDNAModExtension>();
 | 
					 | 
				
			||||||
            if (dna != null)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                res = dna.GetHybridWith(second.def.defName) ?? null;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                dna = second.def.GetModExtension<PawnDNAModExtension>();
 | 
					 | 
				
			||||||
                if (dna != null)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    res = dna.GetHybridWith(first.def.defName) ?? null;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return res;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Copy from RJW
 | 
					        /// Copy from RJW
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
| 
						 | 
					@ -746,12 +468,6 @@ namespace RJW_Menstruation
 | 
				
			||||||
            pawn.story.traits.allTraits = selectedTraits;
 | 
					            pawn.story.traits.allTraits = selectedTraits;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string DueDate()
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (pawn.Tile == -1) return "";
 | 
					 | 
				
			||||||
            return GenDate.DateFullStringWithHourAt(GenDate.TickGameToAbs((int)p_end_tick), Find.WorldGrid.LongLatOf(pawn.Tile));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public override bool TryMergeWith(Hediff other)
 | 
					        public override bool TryMergeWith(Hediff other)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,8 @@ using RimWorld;
 | 
				
			||||||
using Verse;
 | 
					using Verse;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Reflection;
 | 
					using System.Reflection;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Reflection.Emit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace RJW_Menstruation
 | 
					namespace RJW_Menstruation
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -24,8 +26,10 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public static void Postfix(Hediff_Pregnant __instance)
 | 
					        public static void Postfix(Hediff_Pregnant __instance)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            HediffComp_Menstruation comp = __instance.GetMenstruationCompFromPregnancy();
 | 
					            HediffComp_Menstruation comp = __instance.GetMenstruationCompFromPregnancy();
 | 
				
			||||||
 | 
					            if (Configurations.Debug) Log.Message($"{comp.Pawn}'s labor starting, menstruation comp is {comp}");
 | 
				
			||||||
            if (comp == null) return;
 | 
					            if (comp == null) return;
 | 
				
			||||||
            comp.Pregnancy = __instance.pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.PregnancyLabor);
 | 
					            comp.Pregnancy = __instance.pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.PregnancyLabor);
 | 
				
			||||||
 | 
					            if (Configurations.Debug) Log.Message($"New pregnancy Hediff is {comp.Pregnancy}");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,8 +39,10 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public static void PostFix(Hediff_Labor __instance)
 | 
					        public static void PostFix(Hediff_Labor __instance)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            HediffComp_Menstruation comp = __instance.GetMenstruationCompFromPregnancy();
 | 
					            HediffComp_Menstruation comp = __instance.GetMenstruationCompFromPregnancy();
 | 
				
			||||||
 | 
					            if (Configurations.Debug) Log.Message($"{comp.Pawn}'s initial labor ending, menstruation comp is {comp}");
 | 
				
			||||||
            if (comp == null) return;
 | 
					            if (comp == null) return;
 | 
				
			||||||
            comp.Pregnancy = __instance.pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.PregnancyLaborPushing);
 | 
					            comp.Pregnancy = __instance.pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.PregnancyLaborPushing);
 | 
				
			||||||
 | 
					            if (Configurations.Debug) Log.Message($"New pregnancy Hediff is {comp.Pregnancy}");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,6 +52,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public static void PostFix(Hediff_LaborPushing __instance)
 | 
					        public static void PostFix(Hediff_LaborPushing __instance)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            HediffComp_Menstruation comp = __instance.GetMenstruationCompFromPregnancy();
 | 
					            HediffComp_Menstruation comp = __instance.GetMenstruationCompFromPregnancy();
 | 
				
			||||||
 | 
					            if (Configurations.Debug) Log.Message($"{comp.Pawn}'s labor pushing ending, menstruation comp is {comp}");
 | 
				
			||||||
            if (comp == null) return;
 | 
					            if (comp == null) return;
 | 
				
			||||||
            comp.Pregnancy = null;
 | 
					            comp.Pregnancy = null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -111,7 +118,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [HarmonyPatch(typeof(PregnancyUtility), nameof(PregnancyUtility.ApplyBirthOutcome))]
 | 
					    [HarmonyPatch(typeof(PregnancyUtility), nameof(PregnancyUtility.ApplyBirthOutcome))]
 | 
				
			||||||
    public class ApplyBirthOutcome_Patch
 | 
					    public class ApplyBirthOutcome_Breast_Patch
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static void PostFix(Thing birtherThing)
 | 
					        public static void PostFix(Thing birtherThing)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
| 
						 | 
					@ -120,9 +127,21 @@ namespace RJW_Menstruation
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [HarmonyPatch(typeof(PregnancyUtility), nameof(PregnancyUtility.TryTerminatePregnancy))]
 | 
					    [HarmonyPatch]
 | 
				
			||||||
    public class TryTerminatePregnancy_Patch
 | 
					    public class TerminatePregnancy_Patch
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        public static IEnumerable<MethodBase> TargetMethods()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            yield return AccessTools.Method(typeof(PregnancyUtility), nameof(PregnancyUtility.TryTerminatePregnancy));
 | 
				
			||||||
 | 
					            yield return AccessTools.Method(typeof(Recipe_TerminatePregnancy), nameof(Recipe_TerminatePregnancy.ApplyOnPawn));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private static PregnancyAttitude? GetAttitude(Hediff pregnancy)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (pregnancy is Hediff_Pregnant preg) return preg.Attitude;
 | 
				
			||||||
 | 
					            else return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private static Hediff GetEarliestPregnancy(Pawn pawn)
 | 
					        private static Hediff GetEarliestPregnancy(Pawn pawn)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Hediff Earliest_Pregnancy = PregnancyUtility.GetPregnancyHediff(pawn);
 | 
					            Hediff Earliest_Pregnancy = PregnancyUtility.GetPregnancyHediff(pawn);
 | 
				
			||||||
| 
						 | 
					@ -136,20 +155,30 @@ namespace RJW_Menstruation
 | 
				
			||||||
            return Earliest_Pregnancy;
 | 
					            return Earliest_Pregnancy;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private static readonly MethodInfo GetPregnancyHediff = AccessTools.Method(typeof(PregnancyUtility), nameof(PregnancyUtility.GetPregnancyHediff), new System.Type[] { typeof(Pawn) });
 | 
					        private static readonly MethodInfo GetPregnancyHediff = AccessTools.Method(typeof(PregnancyUtility), nameof(PregnancyUtility.GetPregnancyHediff), new Type[] { typeof(Pawn) });
 | 
				
			||||||
 | 
					        private static readonly MethodInfo Get_Attitude = AccessTools.DeclaredPropertyGetter(typeof(Hediff_Pregnant), nameof(Hediff_Pregnant.Attitude));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Also called for Recipe_TerminatePregnancy.ApplyOnPawn
 | 
					 | 
				
			||||||
        public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
 | 
					        public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (GetPregnancyHediff == null || GetPregnancyHediff.ReturnType != typeof(Hediff)) throw new System.InvalidOperationException("GetPregnancyHediff not found");
 | 
					            if (GetPregnancyHediff == null || GetPregnancyHediff.ReturnType != typeof(Hediff)) throw new InvalidOperationException("GetPregnancyHediff not found");
 | 
				
			||||||
 | 
					            if (Get_Attitude == null || Nullable.GetUnderlyingType(Get_Attitude.ReturnType) != typeof(PregnancyAttitude)) throw new InvalidOperationException("get_Attitude not found");
 | 
				
			||||||
            foreach (CodeInstruction instruction in instructions)
 | 
					            foreach (CodeInstruction instruction in instructions)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (instruction.Calls(GetPregnancyHediff))
 | 
					                if (instruction.Calls(GetPregnancyHediff))
 | 
				
			||||||
                    yield return CodeInstruction.Call(typeof(TryTerminatePregnancy_Patch), nameof(TryTerminatePregnancy_Patch.GetEarliestPregnancy));
 | 
					                    yield return CodeInstruction.Call(typeof(TerminatePregnancy_Patch), nameof(TerminatePregnancy_Patch.GetEarliestPregnancy));
 | 
				
			||||||
 | 
					                // Menstruation pregnancies don't have an attitude, so skip the cast to Hediff_Pregnant and call a version that handles it
 | 
				
			||||||
 | 
					                else if (instruction.opcode == OpCodes.Castclass && (Type)instruction.operand == typeof(Hediff_Pregnant))
 | 
				
			||||||
 | 
					                    yield return new CodeInstruction(OpCodes.Nop);
 | 
				
			||||||
 | 
					                else if (instruction.Calls(Get_Attitude))
 | 
				
			||||||
 | 
					                    yield return CodeInstruction.Call(typeof(TerminatePregnancy_Patch), nameof(TerminatePregnancy_Patch.GetAttitude));
 | 
				
			||||||
                else yield return instruction;
 | 
					                else yield return instruction;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [HarmonyPatch(typeof(PregnancyUtility), nameof(PregnancyUtility.TryTerminatePregnancy))]
 | 
				
			||||||
 | 
					    public class PregnancyUtility_TryTerminatePregnancy_Patch
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
        public static void Postfix(bool __result, Pawn pawn)
 | 
					        public static void Postfix(bool __result, Pawn pawn)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (__result)
 | 
					            if (__result)
 | 
				
			||||||
| 
						 | 
					@ -168,13 +197,51 @@ namespace RJW_Menstruation
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [HarmonyPatch(typeof(Recipe_TerminatePregnancy), nameof(Recipe_TerminatePregnancy.ApplyOnPawn))]
 | 
					    [HarmonyPatch(typeof(Pawn_GeneTracker), "AddGene", new Type[] {typeof(Gene), typeof(bool)})]
 | 
				
			||||||
    public class TerminatePregnancy_ApplyOnPawn_Patch
 | 
					    public class AddGene_Patch
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
 | 
					        public static bool Prefix(ref Gene __result, Gene gene, Pawn ___pawn)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            return TryTerminatePregnancy_Patch.Transpiler(instructions);
 | 
					            if(VariousDefOf.WombGenes.Contains(gene.def) && !___pawn.GetMenstruationComps().Any())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                __result = null;
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [HarmonyPatch(typeof(Pawn_GeneTracker), "Notify_GenesChanged")]
 | 
				
			||||||
 | 
					    public class Notify_GenesChanged_Patch
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static void Postfix(Pawn_GeneTracker __instance)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            foreach (HediffComp_Menstruation comp in __instance.pawn.GetMenstruationComps())
 | 
				
			||||||
 | 
					                comp.Notify_UpdatedGenes();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //[HarmonyPatch(typeof(ChildcareUtility), nameof(ChildcareUtility.SuckleFromLactatingPawn))]
 | 
				
			||||||
 | 
					    //public class GreedyConsume_Patch
 | 
				
			||||||
 | 
					    //{
 | 
				
			||||||
 | 
					    //    private static float ConsumeAndAdjustNipples(HediffComp_Chargeable instance, float desiredCharge)
 | 
				
			||||||
 | 
					    //    {
 | 
				
			||||||
 | 
					    //          // Pulling breast comp every tick might be too much for performance.
 | 
				
			||||||
 | 
					    //        const float averageNippleChangePerTick = 0.0025f / 50000f;
 | 
				
			||||||
 | 
					    //        instance.Pawn.GetBreastComp()?.AdjustNippleProgress(Rand.Range(0.0f, averageNippleChangePerTick * 2) * Configurations.MaxBreastIncrementFactor);
 | 
				
			||||||
 | 
					    //        return instance.GreedyConsume(desiredCharge);
 | 
				
			||||||
 | 
					    //    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //    private static readonly MethodInfo GreedyConsume = AccessTools.Method(typeof(HediffComp_Chargeable), nameof(HediffComp_Chargeable.GreedyConsume), new Type[] { typeof(HediffComp_Chargeable), typeof(float) });
 | 
				
			||||||
 | 
					    //    public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
 | 
				
			||||||
 | 
					    //    {
 | 
				
			||||||
 | 
					    //        if(GreedyConsume == null) throw new InvalidOperationException("GreedyConsume not found");
 | 
				
			||||||
 | 
					    //        foreach (var instruction in instructions)
 | 
				
			||||||
 | 
					    //        {
 | 
				
			||||||
 | 
					    //            if (instruction.Calls(GreedyConsume))
 | 
				
			||||||
 | 
					    //                yield return CodeInstruction.Call(typeof(GreedyConsume_Patch), nameof(GreedyConsume_Patch.ConsumeAndAdjustNipples));
 | 
				
			||||||
 | 
					    //            yield return instruction;
 | 
				
			||||||
 | 
					    //        }
 | 
				
			||||||
 | 
					    //    }
 | 
				
			||||||
 | 
					    //}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -48,8 +48,10 @@ namespace RJW_Menstruation
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                description
 | 
					                description
 | 
				
			||||||
                    .AppendFormat("{0}: {1}\n", comp.curStage, comp.curStageHrs);
 | 
					                    .AppendFormat("{0}: {1}\n", comp.curStage, comp.curStageHrs);
 | 
				
			||||||
                if (comp.Pregnancy is Hediff_MultiplePregnancy preg) description
 | 
					                if (comp.Pregnancy is Hediff_BasePregnancy rjwpreg) description
 | 
				
			||||||
                    .AppendFormat("due: {0}\n", preg.DueDate());
 | 
					                    .AppendFormat("due: {0}\n", rjwpreg.DueDate());
 | 
				
			||||||
 | 
					                else if (comp.Pregnancy is Hediff_Pregnant biopreg) description
 | 
				
			||||||
 | 
					                    .AppendFormat("due: {0}\n", biopreg.DueDate());
 | 
				
			||||||
                description
 | 
					                description
 | 
				
			||||||
                    .AppendFormat("fertcums: {0}\n" +
 | 
					                    .AppendFormat("fertcums: {0}\n" +
 | 
				
			||||||
                                  "ovarypower: {1}\n" +
 | 
					                                  "ovarypower: {1}\n" +
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,5 @@
 | 
				
			||||||
using HarmonyLib;
 | 
					using AlienRace;
 | 
				
			||||||
 | 
					using HarmonyLib;
 | 
				
			||||||
using rjw;
 | 
					using rjw;
 | 
				
			||||||
using rjw.Modules.Interactions.Internals.Implementation;
 | 
					using rjw.Modules.Interactions.Internals.Implementation;
 | 
				
			||||||
using rjw.Modules.Interactions.Rules.PartKindUsageRules;
 | 
					using rjw.Modules.Interactions.Rules.PartKindUsageRules;
 | 
				
			||||||
| 
						 | 
					@ -16,6 +17,11 @@ namespace RJW_Menstruation
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Harmony har = new Harmony("RJW_Menstruation");
 | 
					            Harmony har = new Harmony("RJW_Menstruation");
 | 
				
			||||||
            har.PatchAll(Assembly.GetExecutingAssembly());
 | 
					            har.PatchAll(Assembly.GetExecutingAssembly());
 | 
				
			||||||
 | 
					            if (ModsConfig.IsActive("erdelf.HumanoidAlienRaces"))   // Don't use the cached in Configurations, it isn't initialized yet
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                har.Patch(GenTypes.GetTypeInAnyAssembly("AlienRace.HarmonyPatches").GetMethod(nameof(AlienRace.HarmonyPatches.BirthOutcomeMultiplier)),
 | 
				
			||||||
 | 
					                    postfix: new HarmonyMethod(typeof(HAR_LitterSize_Undo).GetMethod(nameof(HAR_LitterSize_Undo.Postfix))));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            InjectIntoRjwInteractionServices();
 | 
					            InjectIntoRjwInteractionServices();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										322
									
								
								1.4/source/RJW_Menstruation/RJW_Menstruation/PregnancyCommon.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										322
									
								
								1.4/source/RJW_Menstruation/RJW_Menstruation/PregnancyCommon.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,322 @@
 | 
				
			||||||
 | 
					using RimWorld;
 | 
				
			||||||
 | 
					using rjw;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Reflection;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using Verse;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace RJW_Menstruation
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public static class PregnancyCommon
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private static readonly MethodInfo TryGetInheritedXenotype = typeof(PregnancyUtility).GetMethod("TryGetInheritedXenotype", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(Pawn), typeof(Pawn), typeof(XenotypeDef).MakeByRefType() }, null);
 | 
				
			||||||
 | 
					        private static readonly MethodInfo ShouldByHybrid = typeof(PregnancyUtility).GetMethod("ShouldByHybrid", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(Pawn), typeof(Pawn) }, null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static string GetBabyInfo(IEnumerable<Pawn> babies)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (babies == null || !babies.Any()) return "Null";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            StringBuilder res = new StringBuilder();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            IEnumerable<Pawn> babiesdistinct = babies.Distinct(new RaceComparer());
 | 
				
			||||||
 | 
					            int iteration = 0;
 | 
				
			||||||
 | 
					            foreach (Pawn baby in babiesdistinct)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                int num = babies.Where(x => x.def.Equals(baby.def)).Count();
 | 
				
			||||||
 | 
					                if (iteration > 0) res.Append(", ");
 | 
				
			||||||
 | 
					                res.AppendFormat("{0} {1}", num, baby.def.label);
 | 
				
			||||||
 | 
					                iteration++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            res.AppendFormat(" {0}", Translations.Dialog_WombInfo02);
 | 
				
			||||||
 | 
					            return res.ToString();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static string GetFatherInfo(IEnumerable<Pawn> babies, Pawn mother, bool is_parent_known)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (babies == null || !babies.Any()) return "Null";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            StringBuilder res = new StringBuilder();
 | 
				
			||||||
 | 
					            res.AppendFormat("{0}: ", Translations.Dialog_WombInfo03);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!is_parent_known && Configurations.InfoDetail != Configurations.DetailLevel.All)
 | 
				
			||||||
 | 
					                return res.Append(Translations.Dialog_FatherUnknown).ToString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            IEnumerable<Pawn> babiesdistinct = babies.Distinct(new FatherComparer(mother));
 | 
				
			||||||
 | 
					            int iteration = 0;
 | 
				
			||||||
 | 
					            foreach (Pawn baby in babiesdistinct)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (iteration > 0) res.Append(", ");
 | 
				
			||||||
 | 
					                res.Append(Utility.GetFather(baby, mother)?.LabelShort ?? Translations.Dialog_FatherUnknown);
 | 
				
			||||||
 | 
					                iteration++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return res.ToString();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Decide pawnkind from mother and father <para/>
 | 
				
			||||||
 | 
					        /// Come from RJW
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="mother"></param>
 | 
				
			||||||
 | 
					        /// <param name="father"></param>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <param name="noAnimalsFromHumanlikes"></param>
 | 
				
			||||||
 | 
					        public static PawnKindDef BabyPawnKindDecider(Pawn mother, Pawn father, bool noAnimalsFromHumanlikes)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            PawnKindDef motherKindDef = Utility.GetRacesPawnKind(mother);
 | 
				
			||||||
 | 
					            PawnKindDef fatherKindDef = Utility.GetRacesPawnKind(father);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            PawnKindDef spawn_kind_def = motherKindDef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            int flag = 0;
 | 
				
			||||||
 | 
					            if (xxx.is_human(mother)) flag += 2;
 | 
				
			||||||
 | 
					            if (xxx.is_human(father)) flag += 1;
 | 
				
			||||||
 | 
					            //Mother - Father = Flag
 | 
				
			||||||
 | 
					            //Human  - Human  =  3
 | 
				
			||||||
 | 
					            //Human  - Animal =  2
 | 
				
			||||||
 | 
					            //Animal - Human  =  1
 | 
				
			||||||
 | 
					            //Animal - Animal =  0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            switch (flag)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                case 3:
 | 
				
			||||||
 | 
					                    if (!Rand.Chance(RJWPregnancySettings.humanlike_DNA_from_mother)) spawn_kind_def = fatherKindDef;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case 2:
 | 
				
			||||||
 | 
					                    if (RJWPregnancySettings.bestiality_DNA_inheritance == 0f) spawn_kind_def = fatherKindDef;
 | 
				
			||||||
 | 
					                    else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case 1:
 | 
				
			||||||
 | 
					                    if (RJWPregnancySettings.bestiality_DNA_inheritance == 1f) spawn_kind_def = fatherKindDef;
 | 
				
			||||||
 | 
					                    else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case 0:
 | 
				
			||||||
 | 
					                    if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            bool IsAndroidmother = AndroidsCompatibility.IsAndroid(mother);
 | 
				
			||||||
 | 
					            bool IsAndroidfather = AndroidsCompatibility.IsAndroid(father);
 | 
				
			||||||
 | 
					            if (IsAndroidmother && !IsAndroidfather)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                spawn_kind_def = fatherKindDef;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if (!IsAndroidmother && IsAndroidfather)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                spawn_kind_def = motherKindDef;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            string MotherRaceName = "";
 | 
				
			||||||
 | 
					            string FatherRaceName = "";
 | 
				
			||||||
 | 
					            MotherRaceName = motherKindDef?.race?.defName;
 | 
				
			||||||
 | 
					            PawnKindDef non_hybrid_kind_def = spawn_kind_def;
 | 
				
			||||||
 | 
					            if (father != null)
 | 
				
			||||||
 | 
					                FatherRaceName = fatherKindDef?.race?.defName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (FatherRaceName != "" && Configurations.UseHybridExtention)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                spawn_kind_def = GetHybrid(father, mother);
 | 
				
			||||||
 | 
					                //Log.Message("pawnkind: " + spawn_kind_def?.defName);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (MotherRaceName != FatherRaceName && FatherRaceName != "")
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (!Configurations.UseHybridExtention || spawn_kind_def == null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    spawn_kind_def = non_hybrid_kind_def;
 | 
				
			||||||
 | 
					                    IEnumerable<RaceGroupDef> groups = DefDatabase<RaceGroupDef>.AllDefs.Where(x => !(x.hybridRaceParents.NullOrEmpty() || x.hybridChildKindDef.NullOrEmpty()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    //ModLog.Message(" found custom RaceGroupDefs " + groups.Count());
 | 
				
			||||||
 | 
					                    foreach (RaceGroupDef t in groups)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        if ((t.hybridRaceParents.Contains(MotherRaceName) && t.hybridRaceParents.Contains(FatherRaceName))
 | 
				
			||||||
 | 
					                            || (t.hybridRaceParents.Contains("Any") && (t.hybridRaceParents.Contains(MotherRaceName) || t.hybridRaceParents.Contains(FatherRaceName))))
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            //ModLog.Message(" has hybridRaceParents");
 | 
				
			||||||
 | 
					                            if (t.hybridChildKindDef.Contains("MotherKindDef"))
 | 
				
			||||||
 | 
					                                spawn_kind_def = motherKindDef;
 | 
				
			||||||
 | 
					                            else if (t.hybridChildKindDef.Contains("FatherKindDef") && father != null)
 | 
				
			||||||
 | 
					                                spawn_kind_def = fatherKindDef;
 | 
				
			||||||
 | 
					                            else
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                //ModLog.Message(" trying hybridChildKindDef " + t.defName);
 | 
				
			||||||
 | 
					                                List<PawnKindDef> child_kind_def_list = new List<PawnKindDef>();
 | 
				
			||||||
 | 
					                                child_kind_def_list.AddRange(DefDatabase<PawnKindDef>.AllDefs.Where(x => t.hybridChildKindDef.Contains(x.defName)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                //ModLog.Message(" found custom hybridChildKindDefs " + t.hybridChildKindDef.Count);
 | 
				
			||||||
 | 
					                                if (!child_kind_def_list.NullOrEmpty())
 | 
				
			||||||
 | 
					                                    spawn_kind_def = child_kind_def_list.RandomElement();
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else if (!Configurations.UseHybridExtention || spawn_kind_def == null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                spawn_kind_def = mother.RaceProps?.AnyPawnKind ?? motherKindDef;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (spawn_kind_def.defName.Contains("Nymph"))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                //child is nymph, try to find other PawnKindDef
 | 
				
			||||||
 | 
					                List<PawnKindDef> spawn_kind_def_list = new List<PawnKindDef>();
 | 
				
			||||||
 | 
					                spawn_kind_def_list.AddRange(DefDatabase<PawnKindDef>.AllDefs.Where(x => x.race == spawn_kind_def.race && !x.defName.Contains("Nymph")));
 | 
				
			||||||
 | 
					                //no other PawnKindDef found try mother
 | 
				
			||||||
 | 
					                if (spawn_kind_def_list.NullOrEmpty())
 | 
				
			||||||
 | 
					                    spawn_kind_def_list.AddRange(DefDatabase<PawnKindDef>.AllDefs.Where(x => x.race == motherKindDef.race && !x.defName.Contains("Nymph")));
 | 
				
			||||||
 | 
					                //no other PawnKindDef found try father
 | 
				
			||||||
 | 
					                if (spawn_kind_def_list.NullOrEmpty() && father != null)
 | 
				
			||||||
 | 
					                    spawn_kind_def_list.AddRange(DefDatabase<PawnKindDef>.AllDefs.Where(x => x.race == fatherKindDef.race && !x.defName.Contains("Nymph")));
 | 
				
			||||||
 | 
					                //no other PawnKindDef found fallback to generic colonist
 | 
				
			||||||
 | 
					                if (spawn_kind_def_list.NullOrEmpty())
 | 
				
			||||||
 | 
					                    spawn_kind_def = PawnKindDefOf.Colonist;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (!spawn_kind_def_list.NullOrEmpty()) spawn_kind_def = spawn_kind_def_list.RandomElement();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // If both parents are humanlike, Biotech will attempt to assign genes to the child
 | 
				
			||||||
 | 
					            // Normally not a problem, but with the hybrid system, two humanlikes might produce an animal
 | 
				
			||||||
 | 
					            // So override it and force the child to be human
 | 
				
			||||||
 | 
					            if (noAnimalsFromHumanlikes && mother.genes != null && father?.genes != null && !spawn_kind_def.race.race.Humanlike)
 | 
				
			||||||
 | 
					                spawn_kind_def = Rand.Chance(RJWPregnancySettings.humanlike_DNA_from_mother) ? motherKindDef : fatherKindDef;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            return spawn_kind_def;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static void SetupBabyXenotype(Pawn mother, Pawn father, Pawn baby)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (baby.genes == null || !ModsConfig.BiotechActive) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (GeneUtility.SameHeritableXenotype(mother, father) && mother.genes.UniqueXenotype)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                baby.genes.xenotypeName = mother.genes.xenotypeName;
 | 
				
			||||||
 | 
					                baby.genes.iconDef = mother.genes.iconDef;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            object[] args = new object[] { mother, father, null };
 | 
				
			||||||
 | 
					            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.xenotypeName = "Hybrid".Translate();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static PawnKindDef GetHybrid(Pawn first, Pawn second)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            PawnKindDef res = null;
 | 
				
			||||||
 | 
					            Pawn opposite = second;
 | 
				
			||||||
 | 
					            HybridInformations info = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!Configurations.HybridOverride.NullOrEmpty())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                info = Configurations.HybridOverride.FirstOrDefault(x => x.DefName == first.def?.defName && (x.hybridExtension?.Exists(y => y.DefName == second.def?.defName) ?? false));
 | 
				
			||||||
 | 
					                if (info == null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    info = Configurations.HybridOverride.FirstOrDefault(x => x.DefName == second.def?.defName && (x.hybridExtension?.Exists(y => y.DefName == first.def?.defName) ?? false));
 | 
				
			||||||
 | 
					                    opposite = first;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (info != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                res = info.GetHybridWith(opposite.def.defName) ?? null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (res != null) return res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            PawnDNAModExtension dna;
 | 
				
			||||||
 | 
					            dna = first.def.GetModExtension<PawnDNAModExtension>();
 | 
				
			||||||
 | 
					            if (dna != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                res = dna.GetHybridWith(second.def.defName) ?? null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                dna = second.def.GetModExtension<PawnDNAModExtension>();
 | 
				
			||||||
 | 
					                if (dna != null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    res = dna.GetHybridWith(first.def.defName) ?? null;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return res;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private static void CopyBodyPartProperties(Hediff part, Hediff originalPart)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            CompHediffBodyPart comp = part.TryGetComp<CompHediffBodyPart>();
 | 
				
			||||||
 | 
					            CompHediffBodyPart originalComp = originalPart.TryGetComp<CompHediffBodyPart>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (comp != null && originalComp != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // the string properties should be the same between both pawns anyways, besides the name of the owner
 | 
				
			||||||
 | 
					                part.Severity = originalPart.Severity;
 | 
				
			||||||
 | 
					                comp.SizeBase = originalComp.SizeBase;
 | 
				
			||||||
 | 
					                comp.SizeOwner = originalComp.SizeOwner;
 | 
				
			||||||
 | 
					                comp.EffSize = originalComp.EffSize;
 | 
				
			||||||
 | 
					                comp.FluidAmmount = originalComp.FluidAmmount;
 | 
				
			||||||
 | 
					                comp.FluidModifier = originalComp.FluidModifier;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            HediffComp_Menstruation originalMenstruationComp = originalPart.GetMenstruationCompFromVagina();
 | 
				
			||||||
 | 
					            if (originalMenstruationComp != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                part.GetMenstruationCompFromVagina()?.CopyCycleProperties(originalMenstruationComp);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            HediffComp_Breast originalBreastComp = originalPart.GetBreastComp();
 | 
				
			||||||
 | 
					            if (originalBreastComp != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                part.GetBreastComp()?.CopyBreastProperties(originalBreastComp);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private static void CopyBodyPartRecord(Pawn baby, Pawn original, BodyPartRecord babyBPR, BodyPartRecord originalBPR)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (babyBPR == null || originalBPR == null) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Hediff_BasePregnancy.RemoveBabyParts(baby, Genital_Helper.get_PartsHediffList(baby, babyBPR));
 | 
				
			||||||
 | 
					            foreach (Hediff originalPart in Genital_Helper.get_PartsHediffList(original, originalBPR))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Hediff part = SexPartAdder.MakePart(originalPart.def, baby, babyBPR);
 | 
				
			||||||
 | 
					                CopyBodyPartProperties(part, originalPart);
 | 
				
			||||||
 | 
					                baby.health.AddHediff(part, babyBPR);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Baby is the sibling to be changed, original is the first of the set and the one to copy to the rest.
 | 
				
			||||||
 | 
					        public static void ProcessIdenticalSibling(Pawn baby, Pawn original)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // They'll be the same pawnkind, which lets us make a lot of useful assumptions
 | 
				
			||||||
 | 
					            // However, some RNG might still be involved in genital generation (e.g. futas), so the easiest method is to clear out and re-generate
 | 
				
			||||||
 | 
					            // A bit wasteful since Hediff_BasePregnancy.PostBirth already redid the genitals
 | 
				
			||||||
 | 
					            CopyBodyPartRecord(baby, original, Genital_Helper.get_genitalsBPR(baby), Genital_Helper.get_genitalsBPR(original));
 | 
				
			||||||
 | 
					            CopyBodyPartRecord(baby, original, Genital_Helper.get_breastsBPR(baby), Genital_Helper.get_breastsBPR(original));
 | 
				
			||||||
 | 
					            CopyBodyPartRecord(baby, original, Genital_Helper.get_uddersBPR(baby), Genital_Helper.get_uddersBPR(original));
 | 
				
			||||||
 | 
					            CopyBodyPartRecord(baby, original, Genital_Helper.get_anusBPR(baby), Genital_Helper.get_anusBPR(original));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static string DueDate(this Hediff_BasePregnancy preg)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (preg.pawn.Tile == -1) return "";
 | 
				
			||||||
 | 
					            return GenDate.DateFullStringWithHourAt(GenDate.TickGameToAbs((int)preg.p_end_tick), Find.WorldGrid.LongLatOf(preg.pawn.Tile));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static string DueDate(this Hediff_Pregnant preg)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (preg.pawn.Tile == -1) return "";
 | 
				
			||||||
 | 
					            int ticksRemaining = (int)((1f - preg.GestationProgress) * preg.pawn.RaceProps.gestationPeriodDays * GenDate.TicksPerDay);
 | 
				
			||||||
 | 
					            int dueTickAbs = GenTicks.TicksAbs + ticksRemaining;
 | 
				
			||||||
 | 
					            return GenDate.DateFullStringWithHourAt(dueTickAbs, Find.WorldGrid.LongLatOf(preg.pawn.Tile));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -69,12 +69,14 @@
 | 
				
			||||||
    <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\HediffComp_PeriodicOvulator.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="HediffComps\HediffComp_PregeneratedBabies.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" />
 | 
				
			||||||
    <Compile Include="Patch\Biotech_Patch.cs" />
 | 
					    <Compile Include="Patch\Biotech_Patch.cs" />
 | 
				
			||||||
    <Compile Include="Patch\GC_Patch.cs" />
 | 
					    <Compile Include="Patch\GC_Patch.cs" />
 | 
				
			||||||
    <Compile Include="Patch\Gizmo_Patch.cs" />
 | 
					    <Compile Include="Patch\Gizmo_Patch.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="PregnancyCommon.cs" />
 | 
				
			||||||
    <Compile Include="Recipe_Surgery.cs" />
 | 
					    <Compile Include="Recipe_Surgery.cs" />
 | 
				
			||||||
    <Compile Include="StatParts.cs" />
 | 
					    <Compile Include="StatParts.cs" />
 | 
				
			||||||
    <Compile Include="UI\Dialog_HybridCustom.cs" />
 | 
					    <Compile Include="UI\Dialog_HybridCustom.cs" />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -125,6 +125,8 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public static readonly string Option_PregnancyFromBaseRJW_Label = "Option_PregnancyFromBaseRJW_Label".Translate();
 | 
					        public static readonly string Option_PregnancyFromBaseRJW_Label = "Option_PregnancyFromBaseRJW_Label".Translate();
 | 
				
			||||||
        public static readonly string Option_PregnancyFromMultiplePregnancy_Label = "Option_PregnancyFromMultiplePregnancy_Label".Translate();
 | 
					        public static readonly string Option_PregnancyFromMultiplePregnancy_Label = "Option_PregnancyFromMultiplePregnancy_Label".Translate();
 | 
				
			||||||
        public static readonly string Option_PregnancyFromBiotech_Label = "Option_PregnancyFromBiotech_Label".Translate();
 | 
					        public static readonly string Option_PregnancyFromBiotech_Label = "Option_PregnancyFromBiotech_Label".Translate();
 | 
				
			||||||
 | 
					        public static readonly string Option_EnableBiotechTwins_Label = "Option_EnableBiotechTwins_Label".Translate();
 | 
				
			||||||
 | 
					        public static readonly string Option_EnableBiotechTwins_Desc = "Option_EnableBiotechTwins_Desc".Translate();
 | 
				
			||||||
        public static readonly string Option_EnableDraftedIcon_Label = "Option_EnableDraftedIcon_Label".Translate();
 | 
					        public static readonly string Option_EnableDraftedIcon_Label = "Option_EnableDraftedIcon_Label".Translate();
 | 
				
			||||||
        public static readonly string Option_EnableDraftedIcon_Desc = "Option_EnableDraftedIcon_Desc".Translate();
 | 
					        public static readonly string Option_EnableDraftedIcon_Desc = "Option_EnableDraftedIcon_Desc".Translate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -172,8 +172,8 @@ namespace RJW_Menstruation
 | 
				
			||||||
                    Pawn fetus = comp.GetFetus();
 | 
					                    Pawn fetus = comp.GetFetus();
 | 
				
			||||||
                    if (fetus != null && Utility.ShowFetusInfo())
 | 
					                    if (fetus != null && Utility.ShowFetusInfo())
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        string feinfo = m.GetBabyInfo();
 | 
					                        string feinfo = PregnancyCommon.GetBabyInfo(m.babies);
 | 
				
			||||||
                        string fainfo = m.GetFatherInfo() + "  ";
 | 
					                        string fainfo = PregnancyCommon.GetFatherInfo(m.babies, m.pawn, m.is_parent_known) + "  ";
 | 
				
			||||||
                        if (feinfo.Length + fainfo.Length > 45)
 | 
					                        if (feinfo.Length + fainfo.Length > 45)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            preginfoheight = fontheight + 2;
 | 
					                            preginfoheight = fontheight + 2;
 | 
				
			||||||
| 
						 | 
					@ -221,19 +221,36 @@ namespace RJW_Menstruation
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    if (p is Hediff_Pregnant hp && hp.Severity < 0.2f) cum = comp.GetCumIcon();
 | 
					                    if (p is Hediff_Pregnant hp && hp.Severity < 0.2f) cum = comp.GetCumIcon();
 | 
				
			||||||
                    else cum = ContentFinder<Texture2D>.Get("Womb/Empty", true);
 | 
					                    else cum = ContentFinder<Texture2D>.Get("Womb/Empty", true);
 | 
				
			||||||
                    // TODO: Pregenerated babies (base on multiplepregnancy)
 | 
					                    HediffComp_PregeneratedBabies babiescomp = p.TryGetComp<HediffComp_PregeneratedBabies>();
 | 
				
			||||||
                    if (Utility.ShowFetusInfo())
 | 
					                    if (Utility.ShowFetusInfo())
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        preginfoheight = fontheight;
 | 
					                        string feinfo = PregnancyCommon.GetBabyInfo(babiescomp?.babies);
 | 
				
			||||||
 | 
					                        string fainfo = PregnancyCommon.GetFatherInfo(babiescomp?.babies, babiescomp.Pawn, true) + "  ";    // Keep all parents known, for now
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if (feinfo == "Null") feinfo = "1 " + p.Mother.def.label + " " + Translations.Dialog_WombInfo02;
 | 
				
			||||||
 | 
					                        if (fainfo == "Null")
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            string father = p.Father?.LabelShort ?? Translations.Dialog_FatherUnknown;
 | 
				
			||||||
 | 
					                            fainfo = Translations.Dialog_WombInfo03 + ": " + father + "  ";
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        if (feinfo.Length + fainfo.Length > 45)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            preginfoheight = fontheight + 2;
 | 
				
			||||||
 | 
					                            buttonstyle.alignment = TextAnchor.UpperLeft;
 | 
				
			||||||
 | 
					                            fontstyleright.alignment = TextAnchor.LowerRight;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        else
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            preginfoheight = fontheight;
 | 
				
			||||||
 | 
					                            buttonstyle.alignment = TextAnchor.MiddleLeft;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        Rect preginfo = new Rect(0f, mainRect.yMax - wombRectHeight - 2, wombRectWidth, preginfoheight);
 | 
					                        Rect preginfo = new Rect(0f, mainRect.yMax - wombRectHeight - 2, wombRectWidth, preginfoheight);
 | 
				
			||||||
                        fontstyleright.normal.textColor = Color.white;
 | 
					                        fontstyleright.normal.textColor = Color.white;
 | 
				
			||||||
                        fontstyleright.alignment = TextAnchor.MiddleRight;
 | 
					                        GUI.Box(preginfo, feinfo, buttonstyle);
 | 
				
			||||||
                        buttonstyle.alignment = TextAnchor.MiddleLeft;
 | 
					                        GUI.Label(preginfo, fainfo, fontstyleright);
 | 
				
			||||||
 | 
					 | 
				
			||||||
                        string father = p.Father?.LabelShort ?? Translations.Dialog_FatherUnknown;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        GUI.Box(preginfo, "1 " + p.Mother.def.label + " " + Translations.Dialog_WombInfo02, buttonstyle);
 | 
					 | 
				
			||||||
                        GUI.Label(preginfo, Translations.Dialog_WombInfo03 + ": " + father + "  ", fontstyleright);
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else cum = ContentFinder<Texture2D>.Get(("Womb/Empty"), true);
 | 
					                else cum = ContentFinder<Texture2D>.Get(("Womb/Empty"), true);
 | 
				
			||||||
| 
						 | 
					@ -377,7 +394,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
            anal = pawn.GetAnalIcon(showOrigin);
 | 
					            anal = pawn.GetAnalIcon(showOrigin);
 | 
				
			||||||
            GUI.color = new Color(1.00f, 0.47f, 0.47f, 1);
 | 
					            GUI.color = new Color(1.00f, 0.47f, 0.47f, 1);
 | 
				
			||||||
            GUI.Box(rect, "", boxstyle);
 | 
					            GUI.Box(rect, "", boxstyle);
 | 
				
			||||||
            GUI.color = pawn.story.SkinColor;
 | 
					            GUI.color = Utility.SafeSkinColor(pawn);
 | 
				
			||||||
            //Widgets.DrawTextureFitted(genitalIconRect, anal, 1.0f);
 | 
					            //Widgets.DrawTextureFitted(genitalIconRect, anal, 1.0f);
 | 
				
			||||||
            //Widgets.DrawTextureFitted(genitalIconRect, vagina, 1.0f);
 | 
					            //Widgets.DrawTextureFitted(genitalIconRect, vagina, 1.0f);
 | 
				
			||||||
            GUI.DrawTexture(genitalIconRect, anal, ScaleMode.ScaleToFit);
 | 
					            GUI.DrawTexture(genitalIconRect, anal, ScaleMode.ScaleToFit);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -188,8 +188,8 @@ namespace RJW_Menstruation
 | 
				
			||||||
                    return null;
 | 
					                    return null;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            // TODO: Biotech pregenerated babies
 | 
					            HediffComp_PregeneratedBabies babiescomp = comp.Pregnancy.TryGetComp<HediffComp_PregeneratedBabies>();
 | 
				
			||||||
            return null;
 | 
					            return babiescomp?.babies?.FirstOrDefault();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static void DrawBreastIcon(this Pawn pawn, Rect rect)
 | 
					        public static void DrawBreastIcon(this Pawn pawn, Rect rect)
 | 
				
			||||||
| 
						 | 
					@ -209,7 +209,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                    nipple = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00_Nipple00", false);
 | 
					                    nipple = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00_Nipple00", false);
 | 
				
			||||||
                    areola = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00_Areola00", false);
 | 
					                    areola = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00_Areola00", false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    GUI.color = pawn.story?.SkinColor ?? Color.white;
 | 
					                    GUI.color = SafeSkinColor(pawn);
 | 
				
			||||||
                    GUI.DrawTexture(rect, breast, ScaleMode.ScaleToFit);
 | 
					                    GUI.DrawTexture(rect, breast, ScaleMode.ScaleToFit);
 | 
				
			||||||
                    GUI.color = Color.white;
 | 
					                    GUI.color = Color.white;
 | 
				
			||||||
                    GUI.DrawTexture(rect, areola, ScaleMode.ScaleToFit);
 | 
					                    GUI.DrawTexture(rect, areola, ScaleMode.ScaleToFit);
 | 
				
			||||||
| 
						 | 
					@ -236,7 +236,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                breast = ContentFinder<Texture2D>.Get(icon, false);
 | 
					                breast = ContentFinder<Texture2D>.Get(icon, false);
 | 
				
			||||||
                areola = ContentFinder<Texture2D>.Get(areolaicon, false);
 | 
					                areola = ContentFinder<Texture2D>.Get(areolaicon, false);
 | 
				
			||||||
                nipple = ContentFinder<Texture2D>.Get(nippleicon, false);
 | 
					                nipple = ContentFinder<Texture2D>.Get(nippleicon, false);
 | 
				
			||||||
                GUI.color = pawn.story.SkinColor;
 | 
					                GUI.color = SafeSkinColor(pawn);
 | 
				
			||||||
                GUI.DrawTexture(rect, breast, ScaleMode.ScaleToFit);
 | 
					                GUI.DrawTexture(rect, breast, ScaleMode.ScaleToFit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                GUI.color = comp.NippleColor;
 | 
					                GUI.color = comp.NippleColor;
 | 
				
			||||||
| 
						 | 
					@ -255,7 +255,7 @@ namespace RJW_Menstruation
 | 
				
			||||||
                nipple = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00_Nipple00", false);
 | 
					                nipple = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00_Nipple00", false);
 | 
				
			||||||
                areola = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00_Areola00", false);
 | 
					                areola = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00_Areola00", false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                GUI.color = pawn.story.SkinColor;
 | 
					                GUI.color = SafeSkinColor(pawn);
 | 
				
			||||||
                GUI.DrawTexture(rect, breast, ScaleMode.ScaleToFit);
 | 
					                GUI.DrawTexture(rect, breast, ScaleMode.ScaleToFit);
 | 
				
			||||||
                GUI.color = Color.white;
 | 
					                GUI.color = Color.white;
 | 
				
			||||||
                GUI.DrawTexture(rect, areola, ScaleMode.ScaleToFit);
 | 
					                GUI.DrawTexture(rect, areola, ScaleMode.ScaleToFit);
 | 
				
			||||||
| 
						 | 
					@ -454,5 +454,18 @@ namespace RJW_Menstruation
 | 
				
			||||||
            if (pawn.IsAnimal() && !Configurations.EnableAnimalCycle) return false;
 | 
					            if (pawn.IsAnimal() && !Configurations.EnableAnimalCycle) return false;
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Apparently with some mods, even doing pawn.story?.SkinColor can throw a null reference, so we're stuck doing this
 | 
				
			||||||
 | 
					        public static Color SafeSkinColor(Pawn pawn)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return pawn.story?.SkinColor ?? Color.white;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (NullReferenceException)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return Color.white;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,8 +44,24 @@ namespace RJW_Menstruation
 | 
				
			||||||
        public static readonly RecordDef AmountofCreampied = DefDatabase<RecordDef>.GetNamed("AmountofCreampied");
 | 
					        public static readonly RecordDef AmountofCreampied = DefDatabase<RecordDef>.GetNamed("AmountofCreampied");
 | 
				
			||||||
        public static readonly RecordDef AmountofFertilizedEggs = DefDatabase<RecordDef>.GetNamed("AmountofFertilizedEggs");
 | 
					        public static readonly RecordDef AmountofFertilizedEggs = DefDatabase<RecordDef>.GetNamed("AmountofFertilizedEggs");
 | 
				
			||||||
        public static readonly TaleDef TaleCameInside = DefDatabase<TaleDef>.GetNamed("CameInside");
 | 
					        public static readonly TaleDef TaleCameInside = DefDatabase<TaleDef>.GetNamed("CameInside");
 | 
				
			||||||
 | 
					        public static readonly GeneDef ShortEggLifetime = DefDatabase<GeneDef>.GetNamed("Menstruation_ShortEggLifetime");
 | 
				
			||||||
 | 
					        public static readonly GeneDef DoubleEggLifetime = DefDatabase<GeneDef>.GetNamed("Menstruation_DoubleEggLifetime");
 | 
				
			||||||
 | 
					        public static readonly GeneDef QuadEggLifetime = DefDatabase<GeneDef>.GetNamed("Menstruation_QuadEggLifetime");
 | 
				
			||||||
 | 
					        public static readonly GeneDef NeverEstrus = DefDatabase<GeneDef>.GetNamed("Menstruation_NeverEstrus");
 | 
				
			||||||
 | 
					        public static readonly GeneDef FullEstrus = DefDatabase<GeneDef>.GetNamed("Menstruation_FullEstrus");
 | 
				
			||||||
 | 
					        public static readonly GeneDef DoubleOvulation = DefDatabase<GeneDef>.GetNamed("Menstruation_DoubleOvulation");
 | 
				
			||||||
 | 
					        public static readonly GeneDef QuadOvulation = DefDatabase<GeneDef>.GetNamed("Menstruation_QuadOvulation");
 | 
				
			||||||
 | 
					        public static readonly GeneDef NoBleeding = DefDatabase<GeneDef>.GetNamed("Menstruation_NoBleeding");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static readonly HashSet<GeneDef> WombGenes = new HashSet<GeneDef>() {
 | 
				
			||||||
 | 
					            ShortEggLifetime,
 | 
				
			||||||
 | 
					            DoubleEggLifetime,
 | 
				
			||||||
 | 
					            QuadEggLifetime,
 | 
				
			||||||
 | 
					            NeverEstrus,
 | 
				
			||||||
 | 
					            FullEstrus,
 | 
				
			||||||
 | 
					            DoubleOvulation,
 | 
				
			||||||
 | 
					            QuadOvulation,
 | 
				
			||||||
 | 
					            NoBleeding };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private static List<ThingDef> allraces = null;
 | 
					        private static List<ThingDef> allraces = null;
 | 
				
			||||||
        private static List<PawnKindDef> allkinds = null;
 | 
					        private static List<PawnKindDef> allkinds = null;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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.5</version>
 | 
						<version>1.0.8.6</version>
 | 
				
			||||||
	<dependencies>
 | 
						<dependencies>
 | 
				
			||||||
	</dependencies>
 | 
						</dependencies>
 | 
				
			||||||
	<incompatibleWith />
 | 
						<incompatibleWith />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,10 @@
 | 
				
			||||||
 | 
					Version 1.0.8.6
 | 
				
			||||||
 | 
					 - Updated Traditional Chinese translation by Hydrogen.
 | 
				
			||||||
 | 
					 - Fix error when trying to terminate a non-Biotech pregnancy.
 | 
				
			||||||
 | 
					 - Properly give the opportunity to name a newborn with Biotech and multiple pregnancy.
 | 
				
			||||||
 | 
					 - Added several menstruation-related genes, with a placeholder graphic for now.
 | 
				
			||||||
 | 
					 - Added experimental support for twins and hybrids with Biotech pregnancies, disabled by default.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Version 1.0.8.5
 | 
					Version 1.0.8.5
 | 
				
			||||||
 - Added biosculpter recipe to restore 1 year's worth of eggs, with icon by DestinyPlayer.
 | 
					 - 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.
 | 
					 - Vaginal sex with the "avoid pregnancy" relation will (usually) pull out prevent cum from entering the womb if there's a risk of pregnancy.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue