diff --git a/1.4/Assemblies/RJW_Menstruation.dll b/1.4/Assemblies/RJW_Menstruation.dll index 97337d7..2ac459a 100644 Binary files a/1.4/Assemblies/RJW_Menstruation.dll and b/1.4/Assemblies/RJW_Menstruation.dll differ diff --git a/1.4/Languages/ChineseTraditional/Keyed/RJW_Menstruation.xml b/1.4/Languages/ChineseTraditional/Keyed/RJW_Menstruation.xml index c436751..9e5a55e 100644 --- a/1.4/Languages/ChineseTraditional/Keyed/RJW_Menstruation.xml +++ b/1.4/Languages/ChineseTraditional/Keyed/RJW_Menstruation.xml @@ -37,7 +37,8 @@ 月經加速 加快月經週期 除錯 - 顯示除錯資訊 啟用時會令「胎兒信息級別」選項調至「全部細節」。 + 顯示除錯資訊 +啟用時會令「胎兒信息級別」選項調至「全部細節」。 子宮狀態 在狀態窗口中繪製子宮圖標 陰道狀態 @@ -147,4 +148,10 @@ 沒有卵細胞 必須擁有子宮 {PAWN_labelShort}完成了{PAWN_possessive}卵母細胞再生術(cycle) + + 排卵機率:{0} + 排卵期內每個卵子的獨立排卵機率。 + (測試中!) 允許在「生機」(Biotech)追加的懷孕機制中出現多胞胎。 + 啟用這個選項將允許同卵或異卵雙胞胎出現在「生機」(Biotech)追加的懷孕機制中。 +一併將啟用雜交系統;然而兩個類人(humanlikes)生物絕不可能生出動物。 diff --git a/1.4/Languages/English/Keyed/RJW_Menstruation.xml b/1.4/Languages/English/Keyed/RJW_Menstruation.xml index a1c65b3..18611bd 100644 --- a/1.4/Languages/English/Keyed/RJW_Menstruation.xml +++ b/1.4/Languages/English/Keyed/RJW_Menstruation.xml @@ -56,6 +56,12 @@ Cum will lose fertility by this amount every hour This value affects fertilization chance indirectly. Cycle acceleration Accelerate menstruation cycle This can cause early menopause and infertility. Setting this lower than x12 is recommended. Rimworld's timescale: x6(default) + Colonist update interval + How often the womb of each of your colonists, prisoners, and slaves update. Lowering this will improve accuracy, increasing this can improve performance. + Non-colonist update interval + How often the womb of humans you don't control update. Lowering this will improve accuracy, increasing this can improve performance. + Animal update interval + How often the womb of animals update. Lowering this will improve accuracy, increasing this can improve performance. Debug Show debug information. Womb status diff --git a/1.4/Languages/Russian/Keyed/RJW_Menstruation.xml b/1.4/Languages/Russian/Keyed/RJW_Menstruation.xml new file mode 100644 index 0000000..dd7f41f --- /dev/null +++ b/1.4/Languages/Russian/Keyed/RJW_Menstruation.xml @@ -0,0 +1,140 @@ + + + RJW обновление беремености + + менструальная кровь + Пусто + фолликул + Овуляция + Лютеиновая + В период + Беременная + Восстановление после рождения + Нету + Климакс + Менопауза + Анэструс + Яичники готовятся выпустить яйцеклетку. Овуляция произойдет в конце этой фазы. + Яичники готовятся выпустить яйцеклетку. Овуляция произойдет, если сперма попадает в матку. + Яичники выпускают яйцеклетку в матку. + Матка готова принять оплодотворенную яйцеклетку. Беременность наступит, если кто-то оплодотворит до окончания этапа. + Матка сбрасывает свою слизистую оболочку вместе с любыми яйцеклетками, которые не смогли имплантироваться. + Ребенок растет в утробе матери. Со временем и заботой он станет новым жителем этого мира. + Матка восстанавливается после недавней беременности. + Матка не является фертильной и не может забеременеть. + Яичники близки к истощению, и менструальный цикл стал нерегулярным. + Яичники истощены, и матка больше не может производить яйцеклетки. + У матки закончился цикл. Цикл возобновится, как только будут выполнены условия. + Статус + Лактация + Состояние + Зародыш + Отец + Список спермы + Оплодотворенная + оплодотворение + Овулирование + + + Соберите сперму в ведро + Хранить сперму в утробе матери + Неизвестно + + + + Включить значок матки + Кнопка включения вкладки здоровье + Включить животный цикл + Имитировать циклы животных. Не рекомендуется. + Шанс имплантации + Базовый шанс имплантации оплодотворенной яйцеклетки Это значение влияет на вероятность оплодотворения. + Шанс оплодотворения + Вероятность оплодотворения на мл сперматозоидов в час Это значение влияет на вероятность оплодотворения. + Коэффициент распада спермы в час + Количество спермы в матке будет уменьшаться на эту величину каждый час Это значение влияет на вероятность оплодотворения. + Коэффициент распада фертильности спермы в час + Сперма будет терять фертильность на это количество каждый час Это значение косвенно влияет на вероятность оплодотворения. + Ускорение цикла + Ускорить менструальный цикл Это может привести к ранней менопаузе и бесплодию. Рекомендуется установить значение ниже x12. Временная шкала Rimworld: x6(по умолчанию) + Debug + Показывать отладочную информацию. Также переопределяет "Уровень информации о зародыше" для всех. + Статус матки + Нарисовать значок матки в окне состояния. + Состояние влагалища и груди + Нарисовать значки влагалища, ануса и груди в окне состояния. + Уровень информации о плоде + Показать всю информацию о плоде. + Показать всю информацию о плоде после обнаруженной беременности. + Показывать только изображение плода после обнаруженной беременности. + Не показывайть никакой информации о плоде. + Включить менопаузу + Включите эффект менопаузы, который делает пешку бесплодной с течением времени Если у вас есть проблемы с гонками на долгую жизнь, отключите эту опцию. + Использовать многоплодную беременность + Использовать многоплодную беременность вместо беременности RJW по умолчанию Отключите эту опцию, если у вас проблемы с оплодотворением Беременность RJW должна быть включена. + Включить Разнояйцевых близнецов + Допускать беременность от нескольких яйцеклеток одновременно. + Включить Монозиготных близнецов + Дайть возможность одной яйцеклетке привести к появлению нескольких идентичных потомков. + Шанс монозиготных близнецов + Вероятность появления идентичных близнецов. + Макс монозиготных близнецов + Максимальное количество идентичных братьев и сестер. + Включить наложение яиц + Включить наложение яйца на значок матки. + Количество кровотечения + Предполагаемое общее количество кровотечения + Приблизительное количество кровотечения. Нормальное количество кровотечения у человека составляет около 20 ~ 80 мл за цикл. + Колонист + Пленник + Союзная фракция + Нейтральная + Вражеская Фракция + Помеченые пешки: + Для этих пешек появятся штуковина и кнопка + Использовать гибридное расширение + Переопределяет гибридное определение RJW и RaceSupport. Доминирующее гибридное расширение определяет, чье определение используется первым. Не рекомендуется изменять это. + Доминирующее гибридное расширение + Мать + Отец + Рост груди во время беременности + Изменить, насколько вырастет грудь беременной пешки во время беременности. Некоторые пешки будут расти больше, чем другие. + Изменение сосков во время беременности + Изменить, насколько сильно изменятся соски беременной пешки в процессе. + Постоянное изменение сосков после беременности + Приблизительно определяет, какая часть сосков беременной пешки останется измененной после окончания беременности. + Настройка гибридов + Откройте пользовательский гибридный редактор. Это переопределит гибридные определения XML-файлов. + Разрешить сжатие значка + Значок станет меньше, если это необходимо. + Множитель продолжительности жизни яйца + Увеличить продолжительность жизни яйцеклетки. Все неимплантированные яйцеклетки погибнут в конце лютеиновой стадии, независимо от этого параметра. + Включить трансформацию влагалища после рождения + Включить постоянное растяжение влагалища после родов. Если вы используете другой мод, обрабатывающий это, отключите эту опцию. + Сила превращения + Установить силу превращения. + Включить сбор спермы gizmo + Течка переопределяет настройки подключения RJW + Если включено, пешка с видимой течкой будет использовать эти настройки для потенциальных подключений к оплодотворению вместо настроек RJW. Все настройки по умолчанию соответствуют их аналогам RJW. + Минимальная возможность перепихнуться во время течки + Подключение минимальная привлекательность во время течки + Минимальное мнение о перепихоне во время течки + Расчетная продолжительность жизни спермотозоидов + Предполагаемый срок жизни яйца + Вероятность имплантации оплодотворенных яйцеклеток. Вероятность оплодотворения в этот час: {0}% + Использовать базовый RJW pregnancy + Использовать менструацию при многоплодной беременности + Использовать систему беремености из biotech + Показывать статус матки при призыве + Нарисуйте значок матки для набранных пешек + Вернусть всё по умолчанию + + Собрать сперму + Вагинальное мытье + + Пользовательский гибридный редактор + Гибриды из {0} + Когда {0} скрещивается с {1}, {2} родится с вероятностью {3}. Если обе расы имеют гибридные определения друг для друга, будет использоваться определение отца. + + Никаких яиц + + diff --git a/1.4/MilkModule/Assemblies/MilkModule.dll b/1.4/MilkModule/Assemblies/MilkModule.dll index 1881466..d34b673 100644 Binary files a/1.4/MilkModule/Assemblies/MilkModule.dll and b/1.4/MilkModule/Assemblies/MilkModule.dll differ diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/Configurations.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/Configurations.cs index d450c4d..07fd58f 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/Configurations.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/Configurations.cs @@ -1,4 +1,5 @@ -using rjw; +using RimWorld; +using rjw; using System; using System.Collections.Generic; using UnityEngine; @@ -17,6 +18,10 @@ namespace RJW_Menstruation public const float CumFertilityDecayRatioDefault = 0.05f; public const int CumFertilityDecayRatioAdjustDefault = 50; public const int CycleAccelerationDefault = 6; + public const int ColonistTickIntervalDefault = 2500; // 1 hour + public const int NonColonistTickIntervalDefault = 2500; + public const int AnimalTickIntervalDefault = 2500; + public const int TickIntervalMinimum = 20; public const float EnzygoticTwinsChanceDefault = 0.002f; public const int EnzygoticTwinsChanceAdjustDefault = 2; public const int MaxEnzygoticTwinsDefault = 9; @@ -41,6 +46,9 @@ namespace RJW_Menstruation public static float CumFertilityDecayRatio = CumFertilityDecayRatioDefault; public static int CumFertilityDecayRatioAdjust = CumFertilityDecayRatioAdjustDefault; public static int CycleAcceleration = CycleAccelerationDefault; + public static int ColonistTickInterval = ColonistTickIntervalDefault; + public static int NonColonistTickInterval = NonColonistTickIntervalDefault; + public static int AnimalTickInterval = AnimalTickIntervalDefault; public static bool EnableWombIcon = true; public static bool EnableDraftedIcon = true; public static bool EnableAnimalCycle = false; @@ -85,6 +93,9 @@ namespace RJW_Menstruation EnableGatherCumGizmo = true; EnableAnimalCycle = false; CycleAcceleration = CycleAccelerationDefault; + ColonistTickInterval = ColonistTickIntervalDefault; + NonColonistTickInterval = NonColonistTickIntervalDefault; + AnimalTickInterval = AnimalTickIntervalDefault; EstrusOverridesHookupSettings = false; EstrusFuckabilityToHookup = RJWHookupSettings.MinimumFuckabilityToHookup; EstrusAttractivenessToHookup = RJWHookupSettings.MinimumAttractivenessToHookup; @@ -179,48 +190,51 @@ namespace RJW_Menstruation public override void ExposeData() { - Scribe_Values.Look(ref ImplantationChanceAdjust, "ImplantationChanceAdjust", ImplantationChanceAdjust, true); - Scribe_Values.Look(ref ImplantationChance, "ImplantationChance", ImplantationChance, true); - Scribe_Values.Look(ref FertilizeChanceAdjust, "FertilizeChanceAdjust", FertilizeChanceAdjust, true); - Scribe_Values.Look(ref FertilizeChance, "FertilizeChance", FertilizeChance, true); - Scribe_Values.Look(ref CumDecayRatioAdjust, "CumDecayRatioAdjust", CumDecayRatioAdjust, true); - Scribe_Values.Look(ref CumDecayRatio, "CumDecayRatio", CumDecayRatio, true); - Scribe_Values.Look(ref CumFertilityDecayRatioAdjust, "CumFertilityDecayRatioAdjust", CumFertilityDecayRatioAdjust, true); - Scribe_Values.Look(ref CumFertilityDecayRatio, "CumFertilityDecayRatio", CumFertilityDecayRatio, true); - Scribe_Values.Look(ref CycleAcceleration, "CycleAcceleration", CycleAcceleration, true); - Scribe_Values.Look(ref EnableWombIcon, "EnableWombIcon", EnableWombIcon, true); - Scribe_Values.Look(ref EnableDraftedIcon, "EnableDraftedIcon", EnableDraftedIcon, true); - Scribe_Values.Look(ref EnableAnimalCycle, "EnableAnimalCycle", EnableAnimalCycle, true); - Scribe_Values.Look(ref DrawWombStatus, "DrawWombStatus", DrawWombStatus, true); - Scribe_Values.Look(ref DrawVaginaStatus, "DrawVaginaStatus", DrawVaginaStatus, true); - Scribe_Values.Look(ref DrawEggOverlay, "DrawEggOvray", DrawEggOverlay, true); - Scribe_Values.Look(ref Debug, "Debug", Debug, true); - Scribe_Values.Look(ref infoDetail, "InfoDetail", infoDetail, true); - Scribe_Values.Look(ref EnableMenopause, "EnableMenopause", EnableMenopause, true); - Scribe_Values.Look(ref EstrusOverridesHookupSettings, "EstrusOverridesHookupSettings", EstrusOverridesHookupSettings, true); + Scribe_Values.Look(ref ImplantationChanceAdjust, "ImplantationChanceAdjust", ImplantationChanceAdjustDefault); + Scribe_Values.Look(ref ImplantationChance, "ImplantationChance", ImplantationChanceDefault); + Scribe_Values.Look(ref FertilizeChanceAdjust, "FertilizeChanceAdjust", FertilizeChanceAdjustDefault); + Scribe_Values.Look(ref FertilizeChance, "FertilizeChance", FertilizeChanceDefault); + Scribe_Values.Look(ref CumDecayRatioAdjust, "CumDecayRatioAdjust", CumDecayRatioAdjustDefault); + Scribe_Values.Look(ref CumDecayRatio, "CumDecayRatio", CumDecayRatioDefault); + Scribe_Values.Look(ref CumFertilityDecayRatioAdjust, "CumFertilityDecayRatioAdjust", CumFertilityDecayRatioAdjustDefault); + Scribe_Values.Look(ref CumFertilityDecayRatio, "CumFertilityDecayRatio", CumFertilityDecayRatioDefault); + Scribe_Values.Look(ref CycleAcceleration, "CycleAcceleration", CycleAccelerationDefault); + Scribe_Values.Look(ref ColonistTickInterval, "ColonistTickInterval", ColonistTickIntervalDefault); + Scribe_Values.Look(ref NonColonistTickInterval, "NonColonistTickInterval", NonColonistTickIntervalDefault); + Scribe_Values.Look(ref AnimalTickInterval, "AnimalTickInterval", AnimalTickIntervalDefault); + Scribe_Values.Look(ref EnableWombIcon, "EnableWombIcon", true); + Scribe_Values.Look(ref EnableDraftedIcon, "EnableDraftedIcon", true); + Scribe_Values.Look(ref EnableAnimalCycle, "EnableAnimalCycle", false); + Scribe_Values.Look(ref DrawWombStatus, "DrawWombStatus", true); + Scribe_Values.Look(ref DrawVaginaStatus, "DrawVaginaStatus", true); + Scribe_Values.Look(ref DrawEggOverlay, "DrawEggOvray", true); + Scribe_Values.Look(ref Debug, "Debug", false); + Scribe_Values.Look(ref infoDetail, "InfoDetail", DetailLevel.All); + Scribe_Values.Look(ref EnableMenopause, "EnableMenopause", true); + Scribe_Values.Look(ref EstrusOverridesHookupSettings, "EstrusOverridesHookupSettings", false); Scribe_Values.Look(ref EstrusFuckabilityToHookup, "EstrusFuckabilityToHookup", EstrusFuckabilityToHookup, true); Scribe_Values.Look(ref EstrusAttractivenessToHookup, "EstrusAttractivenessToHookup", EstrusAttractivenessToHookup, true); Scribe_Values.Look(ref EstrusRelationshipToHookup, "EstrusRelationshipToHookup", EstrusRelationshipToHookup, 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 EnableEnzygoticTwins, "EnableEnzygoticTwins", EnableEnzygoticTwins, true); - Scribe_Values.Look(ref EnzygoticTwinsChance, "EnzygoticTwinsChance", EnzygoticTwinsChance, true); - Scribe_Values.Look(ref EnzygoticTwinsChanceAdjust, "EnzygoticTwinsChanceAdjust", EnzygoticTwinsChanceAdjust, true); - Scribe_Values.Look(ref MaxEnzygoticTwins, "MaxEnzygoticTwins", MaxEnzygoticTwins, true); - Scribe_Values.Look(ref BleedingAmount, "BleedingAmount", BleedingAmount, true); - Scribe_Values.Look(ref EnableButtonInHT, "EnableButtonInHT", EnableButtonInHT, true); - Scribe_Values.Look(ref EnableGatherCumGizmo, "EnableGatherCumGizmo", true, true); - Scribe_Values.Look(ref ShowFlag, "ShowFlag", ShowFlag, true); - Scribe_Values.Look(ref UseHybridExtention, "UseHybridExtention", UseHybridExtention, true); - Scribe_Values.Look(ref MotherFirst, "MotherFirst", MotherFirst, true); - Scribe_Values.Look(ref MaxBreastIncrementFactor, "MaxBreastIncrementFactor", MaxBreastIncrementFactor, true); - Scribe_Values.Look(ref MaxNippleIncrementFactor, "MaxNippleIncrementFactor", MaxNippleIncrementFactor, true); - Scribe_Values.Look(ref PermanentNippleChange, "PermanentNippleChange", PermanentNippleChange, true); - Scribe_Values.Look(ref AllowShrinkIcon, "AllowShrinkIcon", AllowShrinkIcon, true); - Scribe_Values.Look(ref EggLifespanMultiplier, "EggLifespanMultiplier", EggLifespanMultiplier, true); - Scribe_Values.Look(ref EnableBirthVaginaMorph, "EnableBirthVaginaMorph", EnableBirthVaginaMorph, true); - Scribe_Values.Look(ref VaginaMorphPower, "VaginaMorphPower", VaginaMorphPower, true); + Scribe_Values.Look(ref PregnancySource, "PregnancySource", PregnancyType.MultiplePregnancy); + Scribe_Values.Look(ref EnableBiotechTwins, "EnableBiotechTwins", false); + Scribe_Values.Look(ref EnableHeteroOvularTwins, "EnableHeteroOvularTwins", true); + Scribe_Values.Look(ref EnableEnzygoticTwins, "EnableEnzygoticTwins", true); + Scribe_Values.Look(ref EnzygoticTwinsChance, "EnzygoticTwinsChance", EnzygoticTwinsChanceDefault); + Scribe_Values.Look(ref EnzygoticTwinsChanceAdjust, "EnzygoticTwinsChanceAdjust", EnzygoticTwinsChanceAdjustDefault); + Scribe_Values.Look(ref MaxEnzygoticTwins, "MaxEnzygoticTwins", MaxEnzygoticTwinsDefault); + Scribe_Values.Look(ref BleedingAmount, "BleedingAmount", BleedingAmountDefault); + Scribe_Values.Look(ref EnableButtonInHT, "EnableButtonInHT", false); + Scribe_Values.Look(ref EnableGatherCumGizmo, "EnableGatherCumGizmo", true); + Scribe_Values.Look(ref ShowFlag, "ShowFlag", PawnFlags.Colonist | PawnFlags.Prisoner); + Scribe_Values.Look(ref UseHybridExtention, "UseHybridExtention", true); + Scribe_Values.Look(ref MotherFirst, "MotherFirst", false); + Scribe_Values.Look(ref MaxBreastIncrementFactor, "MaxBreastIncrementFactor", MaxBreastIncrementFactorDefault); + Scribe_Values.Look(ref MaxNippleIncrementFactor, "MaxNippleIncrementFactor", MaxNippleIncrementFactorDefault); + Scribe_Values.Look(ref PermanentNippleChange, "PermanentNippleChange", PermanentNippleChangeDefault); + Scribe_Values.Look(ref AllowShrinkIcon, "AllowShrinkIcon", false); + Scribe_Values.Look(ref EggLifespanMultiplier, "EggLifespanMultiplier", EggLifespanMultiplierDefault); + Scribe_Values.Look(ref EnableBirthVaginaMorph, "EnableBirthVaginaMorph", false); + Scribe_Values.Look(ref VaginaMorphPower, "VaginaMorphPower", VaginaMorphPowerDefault); Scribe_Collections.Look(ref HybridOverride, saveDestroyedThings: true, label: "HybridOverride", lookMode: LookMode.Deep, ctorArgs: new object[0]); base.ExposeData(); } @@ -274,8 +288,9 @@ namespace RJW_Menstruation public override void DoSettingsWindowContents(Rect inRect) { Rect outRect = new Rect(0f, 30f, inRect.width, inRect.height - 30f); - float mainRectHeight = 30f + + float mainRectHeight = 126f + (Configurations.EnableWombIcon || Configurations.EnableButtonInHT ? 400f : 0f) + + (Configurations.EnableAnimalCycle ? 48f : 0f) + (Configurations.EstrusOverridesHookupSettings ? 144f : 0f) + (Configurations.PregnancySource == Configurations.PregnancyType.MultiplePregnancy ? (Configurations.EnableEnzygoticTwins ? 175f : 75f) : 0f) + (Configurations.PregnancySource == Configurations.PregnancyType.Biotech ? 75f : 0f) + @@ -403,11 +418,11 @@ namespace RJW_Menstruation string estimatedlifespan; if (semenlifespan < 0) { - estimatedlifespan = String.Format(": Infinite", semenlifespan); + estimatedlifespan = string.Format(": Infinite", semenlifespan); } else { - estimatedlifespan = String.Format(": {0:0}h", semenlifespan); + estimatedlifespan = string.Format(": {0:0}h", semenlifespan); } listmain.LabelDouble(Translations.Option6_Label + " " + Configurations.CumFertilityDecayRatio * 100 + "%", Translations.EstimatedCumLifespan + estimatedlifespan, Translations.Option6_Desc); Configurations.CumFertilityDecayRatioAdjust = (int)listmain.Slider(Configurations.CumFertilityDecayRatioAdjust, 0, 1000); @@ -416,6 +431,17 @@ namespace RJW_Menstruation listmain.Label(Translations.Option7_Label + " x" + Configurations.CycleAcceleration, -1, Translations.Option7_Desc); Configurations.CycleAcceleration = (int)listmain.Slider(Configurations.CycleAcceleration, 1, 50); + listmain.LabelDouble(Translations.Option_ColonistUpdateInterval_Label, GenDate.ToStringTicksToPeriod(Configurations.ColonistTickInterval), Translations.Option_ColonistUpdateInterval_Desc); + Configurations.ColonistTickInterval = (int)Mathf.Exp(listmain.Slider(Mathf.Log(Configurations.ColonistTickInterval), Mathf.Log(Configurations.TickIntervalMinimum), Mathf.Log(4 * GenDate.TicksPerHour))); + + listmain.LabelDouble(Translations.Option_NonColonistUpdateInterval_Label, GenDate.ToStringTicksToPeriod(Configurations.NonColonistTickInterval), Translations.Option_NonColonistUpdateInterval_Desc); + Configurations.NonColonistTickInterval = (int)Mathf.Exp(listmain.Slider(Mathf.Log(Configurations.NonColonistTickInterval), Mathf.Log(Configurations.TickIntervalMinimum), Mathf.Log(4 * GenDate.TicksPerHour))); + + if(Configurations.EnableAnimalCycle) + { + listmain.LabelDouble(Translations.Option_AnimalUpdateInterval_Label, GenDate.ToStringTicksToPeriod(Configurations.AnimalTickInterval), Translations.Option_AnimalUpdateInterval_Desc); + Configurations.AnimalTickInterval = (int)Mathf.Exp(listmain.Slider(Mathf.Log(Configurations.AnimalTickInterval), Mathf.Log(Configurations.TickIntervalMinimum), Mathf.Log(4 * GenDate.TicksPerHour))); + } float var2 = EstimatedBleedingAmountPerHour; float var1 = Math.Max(EstimatedBleedingAmount, var2); diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/Cum.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/Cum.cs index c1f9931..3f112d3 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/Cum.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/Cum.cs @@ -165,16 +165,15 @@ namespace RJW_Menstruation Scribe_References.Look(ref pawn, "pawn", true); Scribe_Values.Look(ref volume, "volume", volume, true); Scribe_Values.Look(ref fertility, "fertility", fertility, true); - Scribe_Values.Look(ref notcumthickness, "notcumthickness", notcumthickness, true); - Scribe_Values.Look(ref notcum, "notcum", notcum, true); - Scribe_Values.Look(ref notcumLabel, "notcumLabel", notcumLabel, true); - Scribe_Values.Look(ref useCustomColor, "useCustomColor", useCustomColor, true); - Scribe_Values.Look(ref customColor, "customColor", customColor, true); + Scribe_Values.Look(ref notcumthickness, "notcumthickness", 0); + Scribe_Values.Look(ref notcum, "notcum", false); + Scribe_Values.Look(ref notcumLabel, "notcumLabel", ""); + Scribe_Values.Look(ref useCustomColor, "useCustomColor", false); + Scribe_Values.Look(ref customColor, "customColor", default); Scribe_Defs.Look(ref filthDef, "filthDef"); - } - public void MakeThinner(int speed) + public void MakeThinner(float speed) { cumthickness = cumthickness.LerpMultiple(DecayResist, 0.3f, speed); } @@ -205,8 +204,11 @@ namespace RJW_Menstruation { // comp is used for Hydrogen's RJW Muscle Injury float totalleak = volume; - volume *= Math.Max(0, (1 - (Configurations.CumDecayRatio * (1 - DecayResist)) * leakfactor)); - fertility *= Math.Max(0, 1 - (Configurations.CumFertilityDecayRatio * (1 - DecayResist) + antisperm)); + float decayPerInterval = 1 - Mathf.Pow(1 - Configurations.CumDecayRatio, comp.SimulationsPerHour); + float fertilityDecayPerInterval = 1 - Mathf.Pow(1 - Configurations.CumFertilityDecayRatio, comp.SimulationsPerHour); + antisperm *= comp.SimulationsPerHour; + volume *= Math.Max(0, 1 - decayPerInterval * (1 - DecayResist) * leakfactor); + fertility *= Math.Max(0, 1 - (fertilityDecayPerInterval * (1 - DecayResist) + antisperm)); CutMinor(); totalleak -= volume; return totalleak; diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/DebugActions.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/DebugActions.cs index fe98f5a..55f34db 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/DebugActions.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/DebugActions.cs @@ -10,7 +10,10 @@ namespace RJW_Menstruation private static void SetFollicular(Pawn p) { foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) + { comp.GoNextStage(HediffComp_Menstruation.Stage.Follicular); + comp.RemoveAllEggs(); + } Messages.Message($"{p} is now follicular", p, MessageTypeDefOf.NeutralEvent, false); } @@ -34,7 +37,10 @@ namespace RJW_Menstruation private static void SetBleeding(Pawn p) { foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) + { comp.GoNextStage(HediffComp_Menstruation.Stage.Bleeding); + comp.RemoveAllEggs(); + } Messages.Message($"{p} is now bleeding", p, MessageTypeDefOf.NeutralEvent, false); } /* @@ -57,6 +63,13 @@ namespace RJW_Menstruation comp.RemoveAllCums(); Messages.Message($"All cum removed from {p}'s womb", p, MessageTypeDefOf.NeutralEvent, false); } + [DebugAction("RJW Menstruation", "Remove all eggs from pawn's womb", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] + private static void RemoveEggs(Pawn p) + { + foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) + comp.RemoveAllEggs(); + Messages.Message($"All eggs removed from {p}'s womb", p, MessageTypeDefOf.NeutralEvent, false); + } [DebugAction("RJW Menstruation", "Add egg to pawn's next ovulation", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] private static void AddEgg(Pawn p) { diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/DrugOutcomeDoers.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/DrugOutcomeDoers.cs index 2b51556..b618abe 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/DrugOutcomeDoers.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/DrugOutcomeDoers.cs @@ -89,7 +89,7 @@ namespace RJW_Menstruation else m.moodPowerFactor = 0.3f; } - if (pawn.HasQuirk(QuirkUtility.Quirks.Breeder)) pawn.needs.mood.thoughts.memories.TryGainMemoryFast(VariousDefOf.HateTookContraceptivePill); + if (pawn.IsProPregnancy()) pawn.needs.mood.thoughts.memories.TryGainMemoryFast(VariousDefOf.HateTookContraceptivePill); else pawn.needs.mood.thoughts.memories.TryGainMemoryFast(VariousDefOf.TookContraceptivePill); } } diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Breast.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Breast.cs index 71e930c..558031d 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Breast.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Breast.cs @@ -69,15 +69,12 @@ namespace RJW_Menstruation get { if (babyHalfAge > 0f) return babyHalfAge; - List ages = Pawn.def.race.lifeStageAges; + List ages = Pawn.RaceProps.lifeStageAges; if (ages?.Count > 1) babyHalfAge = ages[1].minAge / 2; if (babyHalfAge <= 0) babyHalfAge = 1.2f / 2; // Default to human - if (RJWPregnancySettings.phantasy_pregnancy) - babyHalfAge /= GenDate.DaysPerYear; - return babyHalfAge; } } @@ -140,10 +137,10 @@ namespace RJW_Menstruation { base.CompExposeData(); - Scribe_Values.Look(ref ageOfLastBirth, "ageOfLastBirth", ageOfLastBirth, true); + Scribe_Values.Look(ref ageOfLastBirth, "ageOfLastBirth", -1); Scribe_Values.Look(ref maxBreastIncrement, "maxBreastIncrement", maxBreastIncrement, true); - Scribe_Values.Look(ref breastSizeIncreased, "breastSizeIncreased", breastSizeIncreased, true); - Scribe_Values.Look(ref nippleProgress, "nippleProgress", nippleProgress, true); + Scribe_Values.Look(ref breastSizeIncreased, "breastSizeIncreased", 0.0f); + Scribe_Values.Look(ref nippleProgress, "nippleProgress", 0.0f); Scribe_Values.Look(ref baseAlpha, "baseAlpha", baseAlpha, true); Scribe_Values.Look(ref baseAreola, "baseAreola", baseAreola, true); Scribe_Values.Look(ref baseNipple, "baseNipple", baseNipple, true); @@ -152,7 +149,7 @@ namespace RJW_Menstruation public bool ShouldSimulate() { if (!Configurations.EnableAnimalCycle && Pawn.IsAnimal()) return false; - if (Pawn.Spawned || Pawn.IsCaravanMember() || PawnUtility.IsTravelingInTransportPodWorldObject(Pawn)) return true; + if (Pawn.SpawnedOrAnyParentSpawned || Pawn.IsCaravanMember() || PawnUtility.IsTravelingInTransportPodWorldObject(Pawn)) return true; return false; } @@ -199,19 +196,19 @@ namespace RJW_Menstruation protected long CalculateLastBirth() { - long youngestAge = (long)(BabyHalfAge * GenDate.TicksPerYear) * -2; // So a newborn isn't considered a new mother, either + long youngestAge = -1; if ((Pawn.relations == null)) return youngestAge; - List pregnancies = new List(); - Pawn.health.hediffSet.GetHediffs(ref pregnancies); + List rjwPregnancies = new List(); + Pawn.health.hediffSet.GetHediffs(ref rjwPregnancies); bool hasChild = Pawn.relations.Children. - Where(child => !pregnancies.Any(preg => preg.babies.Contains(child))). // no fetuses + Where(child => !rjwPregnancies.Any(preg => preg.babies.Contains(child))). // no fetuses Where(child => child.GetMother() == Pawn). // not Dad TryMinBy(child => child.ageTracker.AgeBiologicalTicks, out Pawn youngest); - if (hasChild) youngestAge = Pawn.ageTracker.AgeBiologicalTicks - youngest.ageTracker.AgeBiologicalTicks; + if (hasChild) youngestAge = Math.Max(Pawn.ageTracker.AgeBiologicalTicks - youngest.ageTracker.AgeBiologicalTicks, -1); return youngestAge; } @@ -224,7 +221,7 @@ namespace RJW_Menstruation { maxBreastIncrement = Utility.RandGaussianLike(0.088f, 0.202f); } - if (ageOfLastBirth == 0) + if (ageOfLastBirth == 0 || ageOfLastBirth < -1) { ageOfLastBirth = CalculateLastBirth(); } @@ -253,7 +250,7 @@ namespace RJW_Menstruation debugGrowthStatus = "Base size (ageless)"; } // The youngest child is less than halfway into babyhood: Full size - else if (ageOfLastBirth + BabyHalfAge * GenDate.TicksPerYear > Pawn.ageTracker.AgeBiologicalTicks) + else if (ageOfLastBirth > 0 && ageOfLastBirth + BabyHalfAge * GenDate.TicksPerYear > Pawn.ageTracker.AgeBiologicalTicks) { debugGrowthStatus = "Full size due to young child"; if (breastSizeIncreased < MaxBreastIncrement) @@ -299,7 +296,7 @@ namespace RJW_Menstruation float newNippleProgress; if (Pawn.ageTracker.BiologicalTicksPerTick <= 0f) newNippleProgress = 0f; - else if (ageOfLastBirth + BabyHalfAge * GenDate.TicksPerYear > Pawn.ageTracker.AgeBiologicalTicks) + else if (ageOfLastBirth > 0 && ageOfLastBirth + BabyHalfAge * GenDate.TicksPerYear > Pawn.ageTracker.AgeBiologicalTicks) newNippleProgress = 1f; else if (Pawn.IsRJWPregnant() || Pawn.IsBiotechPregnant()) newNippleProgress = nippleTransitions.Evaluate(Pawn.GetFarthestPregnancyProgress()); diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_InducedOvulator.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_InducedOvulator.cs index d069069..a32969c 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_InducedOvulator.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_InducedOvulator.cs @@ -15,6 +15,14 @@ namespace RJW_Menstruation public class HediffComp_InducedOvulator : HediffComp_Menstruation { + protected bool hadOvulatoryStage = false; // Regardless of whether an egg was actually produced + + protected override void InitializeExtraValues() + { + base.InitializeExtraValues(); + hadOvulatoryStage |= IsEggExist; + } + public override string GetCurStageDesc { get @@ -35,7 +43,7 @@ namespace RJW_Menstruation protected override float RaceCyclesPerYear() { // Don't bother with breeding season, since so much time is planned to be spent pregnant. - float pregnanciesPerYear = GenDate.DaysPerYear / Mathf.Max(1, Pawn.def.race.gestationPeriodDays); + float pregnanciesPerYear = GenDate.DaysPerYear / Mathf.Max(1, Pawn.RaceProps.gestationPeriodDays); return 2 * pregnanciesPerYear / Configurations.ImplantationChanceDefault; } @@ -46,21 +54,35 @@ namespace RJW_Menstruation return Mathf.CeilToInt((Pawn.relations?.ChildrenCount ?? 0) / Configurations.ImplantationChanceDefault); } + public override void CompExposeData() + { + base.CompExposeData(); + Scribe_Values.Look(ref hadOvulatoryStage, "hadOvulatoryStage", false); + } + protected override void GoOvulatoryStage() { estrusflag = false; + hadOvulatoryStage = false; GoNextStage(Stage.Luteal); } + protected override void OvulatoryAction() + { + base.OvulatoryAction(); + hadOvulatoryStage = true; + } + + protected override void LutealAction() + { + base.LutealAction(); + if (curStage != Stage.Luteal) hadOvulatoryStage = false; + } + protected override void AfterCumIn(Pawn cummer) { base.AfterCumIn(cummer); - switch (curStage) - { - case Stage.Follicular: - GoNextStage(Stage.Ovulatory); - break; - } + if (curStage == Stage.Follicular) GoNextStage(Stage.Ovulatory); } public override bool IsDangerDay @@ -75,7 +97,7 @@ namespace RJW_Menstruation case Stage.Ovulatory: return true; case Stage.Luteal: - return IsEggExist && curStageHrs < EggLifespanHours; + return hadOvulatoryStage && curStageTicks < EggLifespanTicks; default: return false; } @@ -89,11 +111,11 @@ namespace RJW_Menstruation switch (curStage) { case Stage.Follicular: - return curStageHrs > currentIntervalHours - Props.estrusDaysBeforeOvulation * 24; + return curStageTicks > currentIntervalTicks - Props.estrusDaysBeforeOvulation * GenDate.TicksPerDay; case Stage.Ovulatory: return true; case Stage.Luteal: - return IsEggExist && curStageHrs < EggLifespanHours; + return hadOvulatoryStage && curStageTicks < EggLifespanTicks; default: return false; } diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Menstruation.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Menstruation.cs index d015752..c32ee83 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Menstruation.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Menstruation.cs @@ -29,6 +29,7 @@ namespace RJW_Menstruation public float baseImplantationChanceFactor; public float basefertilizationChanceFactor; public int follicularIntervalDays = 14; //before ovulation including beginning of bleeding + public int ovulationIntervalHours = 12; //between the end of follicular and the egg emerging public int lutealIntervalDays = 14; //after ovulation until bleeding public int bleedingIntervalDays = 6; //must be less than folicularIntervalDays public int recoveryIntervalDays = 10; //additional infertile days after gave birth @@ -63,17 +64,17 @@ namespace RJW_Menstruation public class HediffComp_Menstruation : HediffComp { const float minmakefilthvalue = 1.0f; - //const int ovarypowerthreshold = 72; - - const int tickInterval = GenDate.TicksPerHour; - const int maxImplantDelayHours = 30 * 24; - const int minImplantAgeHours = 3 * 24; + const int maxImplantDelayHours = 30 * GenDate.HoursPerDay; + const int minImplantAgeHours = 3 * GenDate.HoursPerDay; + const float fluidLeakThreshold = 3.5f; const float pulloutSuccessRate = 0.8f; const float fetishPulloutSuccessModifier = 0.25f; public CompProperties_Menstruation Props; public Stage curStage = Stage.Follicular; - public int curStageHrs = 0; + public int curStageTicks = 0; // Actual number of ticks equals this / cycleAcceleration + private int tickInterval = -1; + const int recalculateTickInterval = GenTicks.TickLongInterval; public bool loaded = false; public bool initError = false; public int ovarypower = -100000; @@ -103,6 +104,7 @@ namespace RJW_Menstruation public static readonly Dictionary StageTexture = new Dictionary() { { Stage.Follicular, TextureCache.FollicularTexture }, + { Stage.Ovulatory, TextureCache.OvulatoryTexture }, { Stage.Luteal, TextureCache.LutealTexture }, { Stage.Bleeding, TextureCache.BleedingTexture }, { Stage.Pregnant, TextureCache.PregnantTexture }, @@ -114,19 +116,22 @@ namespace RJW_Menstruation protected List eggs; protected float cycleSpeed = -1; protected float cycleVariability = -1; - protected int currentIntervalHours = -1; + protected int currentIntervalTicks = -1; // Actual number of ticks equals this / cycleAcceleration protected float crampPain = -1; + protected float fluidToLeak = 0; protected Need sexNeed = null; protected string customwombtex = null; protected string customvagtex = null; protected bool estrusflag = false; + protected float ovulationChanceCache = -1.0f; // Dirtied every simulation + protected float implantationChanceCache = -1.0f; protected int opcache = -1; protected float antisperm = 0.0f; protected float? originvagsize = null; // RJW pregnancy, or Biotech pregnancy/labor/laborpushing protected Hediff pregnancy = null; - protected int eggLifeSpanHours = 48; + protected int eggLifeSpanTicks = 2 * GenDate.TicksPerDay; protected EstrusLevel estrusLevel = EstrusLevel.Visible; protected float ovulationFactor = 1f; protected bool noBleeding = false; @@ -155,6 +160,24 @@ namespace RJW_Menstruation new CurvePoint(1.0f,0.5f) }; + protected int TickInterval + { + get + { + if (tickInterval <= 0) + { + if (Pawn.IsAnimal()) tickInterval = Configurations.AnimalTickInterval; + else if (Pawn.IsColonist || Pawn.IsPrisonerOfColony || Pawn.IsSlaveOfColony) tickInterval = Configurations.ColonistTickInterval; + else tickInterval = Configurations.NonColonistTickInterval; + if (tickInterval <= Configurations.TickIntervalMinimum) tickInterval = Configurations.TickIntervalMinimum; + } + return tickInterval; + } + set => tickInterval = value; + } + + public float SimulationsPerHour => (float)TickInterval / GenDate.TicksPerHour; + public Hediff Pregnancy { get { @@ -177,7 +200,7 @@ namespace RJW_Menstruation float avglittersize; try { - avglittersize = Mathf.Max(Rand.ByCurveAverage(Pawn.def.race.litterSizeCurve), 1.0f); + avglittersize = Mathf.Max(Rand.ByCurveAverage(Pawn.RaceProps.litterSizeCurve), 1.0f); } catch { @@ -189,7 +212,7 @@ namespace RJW_Menstruation opcache = (int)(RaceCyclesPerYear() * avglittersize * yearsBeforeMenopause * - (Pawn.def.race.lifeExpectancy / ThingDefOf.Human.race.lifeExpectancy)); + (Pawn.RaceProps.lifeExpectancy / ThingDefOf.Human.race.lifeExpectancy)); if (opcache == 0) opcache = 1; return opcache; } @@ -242,24 +265,15 @@ namespace RJW_Menstruation public float TotalCum { - get - { - return cums?.Sum(cum => cum.Volume) ?? 0; - } + get => cums?.Sum(cum => cum.Volume) ?? 0; } public float TotalFertCum { - get - { - return cums?.Sum(cum => cum.FertVolume) ?? 0; - } + get => cums?.Sum(cum => cum.FertVolume) ?? 0; } public float TotalCumPercent { - get - { - return cums?.Sum(cum => cum.Volume) / Props.maxCumCapacity ?? 0; - } + get => cums?.Sum(cum => cum.Volume) / Props.maxCumCapacity ?? 0; } public float CumCapacity { @@ -275,7 +289,7 @@ namespace RJW_Menstruation { get { - if (xxx.has_quirk(Pawn, "Breeder")) return 0.5f; + if (QuirkUtility.HasQuirk(Pawn, QuirkUtility.Quirks.Breeder)) return 0.5f; return 1.0f; } @@ -284,58 +298,70 @@ namespace RJW_Menstruation // I hate doing this, but it's the least bad option public bool calculatingOvulationChance = false; + protected float CalcuatedOvulationChance() + { + float ovulationChance = 1.0f; + if (EggHealth <= 0.0f) return 0.0f; + if (EggHealth < 1.0f / 3.0f) ovulationChance = 0.8f; + if (ModsConfig.BiotechActive && xxx.is_human(Pawn)) + { + if (Pawn.SterileGenes()) return 0.0f; + // Replicate how rjw.PawnCapacityWorker_Fertility.CalculateCapacityLevel does it, but without the age factor + if (!Pawn.RaceHasFertility()) return 0.0f; + if (AndroidsCompatibility.IsAndroid(Pawn) && parent.def != Genital_Helper.archotech_vagina) return 0.0f; + foreach (var part in StatDefOf.Fertility.parts) + { + if(part is StatPart_FertilityByGenderAge fertilityByAge) + { + float factor = 1.0f; + fertilityByAge.TransformValue(StatRequest.For(Pawn), ref factor); + if (factor <= 0.0f) return 0.0f; // Too young or too old + } + else part.TransformValue(StatRequest.For(Pawn), ref ovulationChance); + } + if (Pawn.HasQuirk(QuirkUtility.Quirks.Breeder)) ovulationChance *= 10.0f; + try + { + calculatingOvulationChance = true; + ovulationChance *= PawnCapacityUtility.CalculateCapacityLevel(Pawn.health.hediffSet, xxx.reproduction); + } + finally { calculatingOvulationChance = false; } + } + return ovulationChance; + } + + protected float CalcuatedImplantChance() + { + float factor = 1.0f; + if (ModsConfig.BiotechActive && xxx.is_human(Pawn)) + { + // Implant factor will be based solely on pawn age, plus any rollover from ovulation chance + StatPart_FertilityByGenderAge fertilityStatPart = StatDefOf.Fertility.GetStatPart(); + fertilityStatPart?.TransformValue(StatRequest.For(Pawn), ref factor); + if (OvulationChance > 1.0f) factor *= OvulationChance; + return Props.baseImplantationChanceFactor * FertilityModifier * factor; + } + else + { + return Pawn.health.capacities.GetLevel(xxx.reproduction) * Props.baseImplantationChanceFactor * FertilityModifier * factor; + } + } + public float OvulationChance { get { - float ovulationChance = 1.0f; - if (EggHealth <= 0.0f) return 0.0f; - if (EggHealth < 1.0f / 3.0f) ovulationChance = 0.8f; - if (ModsConfig.BiotechActive && xxx.is_human(Pawn)) - { - if (Pawn.SterileGenes()) return 0.0f; - // Replicate how rjw.PawnCapacityWorker_Fertility.CalculateCapacityLevel does it, but without the age factor - if (!Pawn.RaceHasFertility()) return 0.0f; - if (AndroidsCompatibility.IsAndroid(Pawn) && parent.def != Genital_Helper.archotech_vagina) return 0.0f; - foreach (var part in StatDefOf.Fertility.parts) - { - if(part is StatPart_FertilityByGenderAge fertilityByAge) - { - float factor = 1.0f; - fertilityByAge.TransformValue(StatRequest.For(Pawn), ref factor); - if (factor <= 0.0f) return 0.0f; // Too young or too old - } - else part.TransformValue(StatRequest.For(Pawn), ref ovulationChance); - } - if (Pawn.HasQuirk(QuirkUtility.Quirks.Breeder)) ovulationChance *= 10.0f; - try - { - calculatingOvulationChance = true; - ovulationChance *= PawnCapacityUtility.CalculateCapacityLevel(Pawn.health.hediffSet, xxx.reproduction); - } - finally { calculatingOvulationChance = false; } - } - return ovulationChance; + if (ovulationChanceCache < 0.0f) ovulationChanceCache = CalcuatedOvulationChance(); + return ovulationChanceCache; } } + public float ImplantChance { get { - float factor = 1.0f; - if (ModsConfig.BiotechActive && xxx.is_human(Pawn)) - { - // Implant factor will be based solely on pawn age, plus any rollover from ovulation chance - StatPart_FertilityByGenderAge fertilityStatPart = StatDefOf.Fertility.GetStatPart(); - fertilityStatPart?.TransformValue(StatRequest.For(Pawn), ref factor); - float ovulationOverflow = OvulationChance; - if (ovulationOverflow > 1.0f) factor *= ovulationOverflow; - return Props.baseImplantationChanceFactor * FertilityModifier * factor; - } - else - { - return Pawn.health.capacities.GetLevel(xxx.reproduction) * Props.baseImplantationChanceFactor * FertilityModifier * factor; - } + if (implantationChanceCache < 0.0f) implantationChanceCache = CalcuatedImplantChance(); + return implantationChanceCache; } } @@ -449,25 +475,13 @@ namespace RJW_Menstruation public string WombTex { - get - { - return customwombtex ?? Props.wombTex; - } - set - { - customwombtex = value; - } + get => customwombtex ?? Props.wombTex; + set => customwombtex = value; } public string VagTex { - get - { - return customvagtex ?? Props.vagTex; - } - set - { - customvagtex = value; - } + get => customvagtex ?? Props.vagTex; + set => customvagtex = value; } public string GetFertilizingInfo { @@ -501,12 +515,12 @@ namespace RJW_Menstruation /// /// returns fertstage. if not fertilized returns -1 /// - public int IsFertilized + public int EggFertilizedTime { get { if (eggs?.All(egg => !egg.fertilized) ?? true) return -1; - return eggs.Max(egg => egg.fertstage); + return eggs.Max(egg => egg.ticksSinceFertilization); } } public IEnumerable GetCummersAndFertilizers() @@ -520,18 +534,12 @@ namespace RJW_Menstruation } public bool IsEggExist { - get - { - return !eggs.NullOrEmpty(); - } + get => !eggs.NullOrEmpty(); } - public int EggLifespanHours + public int EggLifespanTicks { - get - { - return eggLifeSpanHours; - } + get => eggLifeSpanTicks; } public virtual bool IsDangerDay @@ -543,11 +551,11 @@ namespace RJW_Menstruation switch (curStage) { case Stage.Follicular: - return curStageHrs > 0.7f * currentIntervalHours; + return curStageTicks > 0.7f * currentIntervalTicks; case Stage.Ovulatory: return true; case Stage.Luteal: - return curStageHrs < EggLifespanHours; + return curStageTicks < EggLifespanTicks; default: return false; } @@ -555,10 +563,7 @@ namespace RJW_Menstruation } public int GetNumOfEggs { - get - { - return eggs?.Count ?? 0; - } + get => eggs?.Count ?? 0; } public Color BloodColor { @@ -566,14 +571,13 @@ namespace RJW_Menstruation { try { - Color c = Pawn.def.race.BloodDef.graphicData.color; + Color c = Pawn.RaceProps.BloodDef.graphicData.color; return c; } catch { return Colors.blood; } - } } @@ -587,25 +591,19 @@ namespace RJW_Menstruation } return originvagsize ?? 0.1f; } - set - { - originvagsize = value; - } + set => originvagsize = value; } - public float CurStageIntervalHours + public int CurStageIntervalTicks { - get - { - return currentIntervalHours; - } + get => currentIntervalTicks; } public float StageProgress { get { - if (pregnancy == null) return Mathf.Clamp01(curStageHrs / CurStageIntervalHours); + if (pregnancy == null) return Mathf.Clamp01((float)curStageTicks / currentIntervalTicks); bool is_discovered = false; switch (pregnancy) { @@ -627,12 +625,21 @@ namespace RJW_Menstruation if (Pawn.story?.bodyType == BodyTypeDefOf.Thin) discoveryTime = 0.25f; else if (Pawn.story?.bodyType == BodyTypeDefOf.Female) discoveryTime = 0.35f; // Estimated; there's no way to get the exact value after the fact without writing it into the save - float lutealProgressWhenImplanted = Math.Min(0.5f, maxImplantDelayHours / (Props.lutealIntervalDays * 24)); + float lutealProgressWhenImplanted = Math.Min(0.5f, maxImplantDelayHours / (Props.lutealIntervalDays * GenDate.HoursPerDay)); return GenMath.LerpDouble(0, discoveryTime, lutealProgressWhenImplanted, 1.0f, pregnancy.Severity); } } + public float StageProgessNextUpdate + { + get + { + if (pregnancy != null) return StageProgress; + return Mathf.Clamp01((float)(curStageTicks + TickInterval * Configurations.CycleAcceleration) / currentIntervalTicks); + } + } + public Texture2D GetStageTexture { get @@ -645,19 +652,30 @@ namespace RJW_Menstruation public override void CompExposeData() { base.CompExposeData(); + if (Scribe.mode == LoadSaveMode.LoadingVars) + { + int curStageHrs = -1; + int currentIntervalHours = -1; + Scribe_Values.Look(ref curStageHrs, "curStageHrs", curStageHrs, true); + Scribe_Values.Look(ref currentIntervalHours, "currentIntervalHours", currentIntervalHours, true); + if (curStageHrs >= 0) curStageTicks = curStageHrs * GenDate.TicksPerHour; + if (currentIntervalHours >= 0) currentIntervalTicks = currentIntervalHours * GenDate.TicksPerHour; + } + Scribe_Collections.Look(ref cums, saveDestroyedThings: true, label: "cums", lookMode: LookMode.Deep, ctorArgs: new object[0]); Scribe_Collections.Look(ref eggs, saveDestroyedThings: true, label: "eggs", lookMode: LookMode.Deep, ctorArgs: new object[0]); Scribe_Values.Look(ref curStage, "curStage", curStage, true); - Scribe_Values.Look(ref curStageHrs, "curStageHrs", curStageHrs, true); + Scribe_Values.Look(ref curStageTicks, "curStageTicks", curStageTicks, true); Scribe_Values.Look(ref cycleSpeed, "cycleSpeed", cycleSpeed, true); Scribe_Values.Look(ref cycleVariability, "cycleVariability", cycleVariability, true); - Scribe_Values.Look(ref currentIntervalHours, "currentIntervalHours", currentIntervalHours, true); + Scribe_Values.Look(ref currentIntervalTicks, "currentIntervalTicks", currentIntervalTicks, true); Scribe_Values.Look(ref crampPain, "crampPain", crampPain, true); + Scribe_Values.Look(ref fluidToLeak, "fluidToLeak", 0); Scribe_Values.Look(ref ovarypower, "ovarypower", ovarypower, true); - Scribe_Values.Look(ref eggstack, "eggstack", eggstack, true); - Scribe_Values.Look(ref estrusflag, "estrusflag", estrusflag, true); + Scribe_Values.Look(ref eggstack, "eggstack", 0); + Scribe_Values.Look(ref estrusflag, "estrusflag", false); Scribe_Values.Look(ref originvagsize, "originvagsize", originvagsize, true); - Scribe_Values.Look(ref DoCleanWomb, "DoCleanWomb", DoCleanWomb, true); + Scribe_Values.Look(ref DoCleanWomb, "DoCleanWomb", false); Scribe_References.Look(ref pregnancy, "pregnancy"); } @@ -672,16 +690,16 @@ namespace RJW_Menstruation public void Notify_UpdatedGenes() { - eggLifeSpanHours = Props.eggLifespanDays * 24; + eggLifeSpanTicks = Props.eggLifespanDays * GenDate.TicksPerDay; 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.ShortEggLifetime)) eggLifeSpanTicks = eggLifeSpanTicks * 3 / 4; + else if (Pawn.genes.HasGene(VariousDefOf.DoubleEggLifetime)) eggLifeSpanTicks *= 2; + else if (Pawn.genes.HasGene(VariousDefOf.QuadEggLifetime)) eggLifeSpanTicks *= 4; if (Pawn.genes.HasGene(VariousDefOf.NeverEstrus)) estrusLevel = EstrusLevel.None; else if (Pawn.genes.HasGene(VariousDefOf.FullEstrus)) estrusLevel = EstrusLevel.Visible; @@ -695,7 +713,7 @@ namespace RJW_Menstruation public bool ShouldSimulate() { if (!Configurations.EnableAnimalCycle && Pawn.IsAnimal()) return false; - if (Pawn.Spawned || Pawn.IsCaravanMember() || PawnUtility.IsTravelingInTransportPodWorldObject(Pawn)) return true; + if (Pawn.SpawnedOrAnyParentSpawned || Pawn.IsCaravanMember() || PawnUtility.IsTravelingInTransportPodWorldObject(Pawn)) return true; return false; } @@ -725,7 +743,8 @@ namespace RJW_Menstruation Initialize(); } - if (!Pawn.IsHashIntervalTick(tickInterval)) return; + if (Pawn.IsHashIntervalTick(recalculateTickInterval)) TickInterval = -1; // Every so often, force TickInterval to be recalculated in case the pawn's status changed. + if (!Pawn.IsHashIntervalTick(TickInterval)) return; if (initError) Log.Warning($"Attempting to process {Pawn}'s womb uninitialized"); @@ -807,6 +826,7 @@ namespace RJW_Menstruation { get { + if (Pawn.Dead) return null; StringBuilder tip = new StringBuilder(); tip.Append(Translations.Dialog_WombInfo01); tip.Append(": "); @@ -821,17 +841,17 @@ namespace RJW_Menstruation } } - protected virtual int HoursToNextStage() + protected virtual int TicksToNextStage() { - return Math.Max(0,(currentIntervalHours - curStageHrs) / Configurations.CycleAcceleration); + return Math.Max(0,(currentIntervalTicks - curStageTicks) / Configurations.CycleAcceleration); } public override string CompDebugString() { - if (curStage == Stage.None || curStage == Stage.Infertile || curStage == Stage.Pregnant) return base.CompDebugString(); + if (Pawn.Dead || curStage == Stage.None || curStage == Stage.Infertile || curStage == Stage.Pregnant) return null; StringBuilder debugString = new StringBuilder(); debugString.Append($"Time to next state: "); - debugString.Append(GenDate.ToStringTicksToPeriod(HoursToNextStage() * GenDate.TicksPerHour)); + debugString.Append(GenDate.ToStringTicksToPeriod(TicksToNextStage())); return debugString.ToString(); } @@ -842,11 +862,7 @@ namespace RJW_Menstruation /// public Cum GetNotCum(string notcumlabel) { - if (!cums.NullOrEmpty()) foreach (Cum cum in cums) - { - if (cum.notcum && cum.notcumLabel.Equals(notcumlabel)) return cum; - } - return null; + return cums?.Find(cum => cum.notcum && cum.notcumLabel.Equals(notcumlabel)); } /// @@ -862,17 +878,17 @@ namespace RJW_Menstruation /// /// Inject pawn's cum into womb /// - /// + /// /// /// /// - public void CumIn(Pawn pawn, float volume, float fertility = 1.0f, bool precum = false) + public void CumIn(Pawn cummer, float volume, float fertility = 1.0f, bool precum = false) { if (volume <= 0) return; - if (!precum && fertility > 0 && IsDangerDay && pawn.relations.GetPregnancyApproachForPartner(Pawn) == PregnancyApproach.AvoidPregnancy) + if (!precum && fertility > 0 && IsDangerDay && cummer.relations.GetPregnancyApproachForPartner(Pawn) == PregnancyApproach.AvoidPregnancy) { float successChance = pulloutSuccessRate; - if (pawn.HasQuirk(QuirkUtility.Quirks.ImpregnationFetish)) successChance *= fetishPulloutSuccessModifier; + if (cummer.HasQuirk(QuirkUtility.Quirks.ImpregnationFetish)) successChance *= fetishPulloutSuccessModifier; if (Pawn.HasQuirk(QuirkUtility.Quirks.ImpregnationFetish)) successChance *= fetishPulloutSuccessModifier; if (Rand.Chance(successChance)) return; } @@ -885,14 +901,14 @@ namespace RJW_Menstruation bool merged = false; if (!cums.NullOrEmpty()) foreach (Cum cum in cums) { - if (cum.pawn.Equals(pawn)) + if (cum.pawn.Equals(cummer)) { cum.MergeWithCum(volume, fertility); merged = true; } cum.DismishForce(cumoutrate); } - if (!merged) cums.Add(new Cum(pawn, volume * (1 - cumoutrate), fertility)); + if (!merged) cums.Add(new Cum(cummer, volume * (1 - cumoutrate), fertility)); } else { @@ -900,20 +916,20 @@ namespace RJW_Menstruation bool merged = false; if (!cums.NullOrEmpty()) foreach (Cum cum in cums) { - if (cum.pawn.Equals(pawn)) + if (cum.pawn.Equals(cummer)) { cum.MergeWithCum(volume, fertility); merged = true; } } - if (!merged) cums.Add(new Cum(pawn, volume, fertility)); + if (!merged) cums.Add(new Cum(cummer, volume, fertility)); } cumd = TotalCumPercent - cumd; if (!precum) { Pawn.records.AddTo(VariousDefOf.AmountofCreampied, volume); - AfterCumIn(pawn); + AfterCumIn(cummer); AfterFluidIn(cumd); } } @@ -921,12 +937,12 @@ namespace RJW_Menstruation /// /// Inject pawn's fluid into womb /// - /// + /// /// /// /// /// - public void CumIn(Pawn pawn, float volume, string notcumlabel, float decayresist = 0, ThingDef filthdef = null) + public void CumIn(Pawn cummer, float volume, string notcumlabel, float decayresist = 0, ThingDef filthdef = null) { if (volume <= 0) return; float tmp = TotalCum + volume; @@ -937,14 +953,14 @@ namespace RJW_Menstruation bool merged = false; if (!cums.NullOrEmpty()) foreach (Cum cum in cums) { - if (cum.notcum && cum.pawn.Equals(pawn) && cum.notcumLabel.Equals(notcumlabel)) + if (cum.notcum && cum.pawn.Equals(cummer) && cum.notcumLabel.Equals(notcumlabel)) { cum.MergeWithFluid(volume, decayresist, filthdef); merged = true; } cum.DismishForce(cumoutrate); } - if (!merged) cums.Add(new Cum(pawn, volume * (1 - cumoutrate), notcumlabel, decayresist, filthdef)); + if (!merged) cums.Add(new Cum(cummer, volume * (1 - cumoutrate), notcumlabel, decayresist, filthdef)); } else { @@ -952,13 +968,13 @@ namespace RJW_Menstruation bool merged = false; if (!cums.NullOrEmpty()) foreach (Cum cum in cums) { - if (cum.notcum && cum.pawn.Equals(pawn) && cum.notcumLabel.Equals(notcumlabel)) + if (cum.notcum && cum.pawn.Equals(cummer) && cum.notcumLabel.Equals(notcumlabel)) { cum.MergeWithFluid(volume, decayresist, filthdef); merged = true; } } - if (!merged) cums.Add(new Cum(pawn, volume, notcumlabel, decayresist, filthdef)); + if (!merged) cums.Add(new Cum(cummer, volume, notcumlabel, decayresist, filthdef)); } cumd = TotalCumPercent - cumd; AfterNotCumIn(); @@ -998,17 +1014,23 @@ namespace RJW_Menstruation absorber = (Absorber)Pawn.apparel?.WornApparel?.Find(x => x is Absorber); if (absorber != null) { - absorber.WearEffect(); - if (absorber.dirty && absorber.EffectAfterDirty) absorber.DirtyEffect(); + absorber.WearEffect(TickInterval); + if (absorber.dirty && absorber.EffectAfterDirty) absorber.DirtyEffect(TickInterval); } } /// /// For natural leaking /// - protected virtual void AfterCumOut() + protected virtual void AfterCumOut(float amount, List filthlabels) { - Pawn.needs?.mood?.thoughts?.memories?.TryGainMemory(VariousDefOf.LeakingFluids); + fluidToLeak += amount; + if (fluidToLeak > fluidLeakThreshold) Pawn.needs?.mood?.thoughts?.memories?.TryGainMemory(VariousDefOf.LeakingFluids); + for (; fluidToLeak > fluidLeakThreshold; fluidToLeak -= fluidLeakThreshold) + { + if (cums.Count > 1) MakeCumFilthMixture(fluidLeakThreshold, filthlabels); + else if (cums.Count == 1) MakeCumFilth(cums.First(), fluidLeakThreshold); + } } /// @@ -1037,24 +1059,20 @@ namespace RJW_Menstruation if (TotalCum > Props.maxCumCapacity * Pawn.BodySize) leakfactor = Math.Min(1 + (TotalCum - Props.maxCumCapacity * Pawn.BodySize) / 10, 2f); if (absorber != null && absorber.dirty && !absorber.LeakAfterDirty) leakfactor = 0f; if (Pawn.CurJobDef == xxx.knotted) leakfactor = 0f; - HashSet removecums = new HashSet(); foreach (Cum cum in cums) { - cum.CumEffects(Pawn); + if (Rand.Chance(SimulationsPerHour)) cum.CumEffects(Pawn); float vd = cum.DismishNatural(leakfactor, this, antisperm); - cum.MakeThinner(Configurations.CycleAcceleration); + cum.MakeThinner((float)Configurations.CycleAcceleration * SimulationsPerHour); totalleak += AbsorbCum(vd, absorber); string tmp = "FilthLabelWithSource".Translate(cum.FilthDef.label, cum.pawn?.LabelShort ?? "Unknown", 1.ToString()); filthlabels.Add(tmp.Replace(" x1", "")); - if (cum.ShouldRemove()) removecums.Add(cum); } - if (cums.Count > 1) MakeCumFilthMixture(totalleak, filthlabels); - else if (cums.Count == 1) MakeCumFilth(cums.First(), totalleak); - cums.RemoveAll(cum => removecums.Contains(cum)); + AfterCumOut(totalleak, filthlabels); + cums.RemoveAll(cum => cum.ShouldRemove()); + if (cums.NullOrEmpty()) fluidToLeak = 0; cumd = TotalCumPercent - cumd; - if (totalleak >= 1.0f) AfterCumOut(); AfterFluidOut(cumd); - } /// @@ -1084,6 +1102,7 @@ namespace RJW_Menstruation if (cums.Count > 1) MakeCumFilthMixture(totalleak, filthlabels); else if (cums.Count == 1) MakeCumFilth(cums.First(), totalleak); cums.RemoveAll(cum => removecums.Contains(cum)); + if (cums.NullOrEmpty()) fluidToLeak = 0; cumd = TotalCumPercent - cumd; AfterFluidOut(cumd); return outcum; @@ -1113,6 +1132,7 @@ namespace RJW_Menstruation if (cum.notcum) pure = false; } cums.RemoveAll(cum => removecums.Contains(cum)); + if (cums.NullOrEmpty()) fluidToLeak = 0; return new CumMixture(Pawn, totalleak, cumlabels, color, mixtureDef, pure); } @@ -1125,6 +1145,11 @@ namespace RJW_Menstruation cums.Clear(); } + public void RemoveAllEggs() + { + eggs.Clear(); + } + /// /// Fertilize eggs and return the result @@ -1148,11 +1173,13 @@ namespace RJW_Menstruation initError = true; Props = (CompProperties_Menstruation)props; - Notify_UpdatedGenes(); + if (cums == null) cums = new List(); + if (eggs == null) eggs = new List(); + + PreInitialize(); if (Props.infertile) { - if (cums == null) cums = new List(); curStage = Stage.None; loaded = true; initError = false; @@ -1164,22 +1191,20 @@ namespace RJW_Menstruation InitOvary(); - if (currentIntervalHours < 0) + if (currentIntervalTicks < 0) { if (ShouldBeInfertile()) curStage = Stage.Infertile; else if (!IsBreedingSeason()) curStage = Stage.Anestrus; else curStage = RandomStage(); if (curStage == Stage.Follicular) - currentIntervalHours = PeriodRandomizer(Stage.Follicular) - PeriodRandomizer(Stage.Bleeding); + currentIntervalTicks = PeriodRandomizer(Stage.Follicular) - PeriodRandomizer(Stage.Bleeding); else - currentIntervalHours = PeriodRandomizer(curStage); - if (currentIntervalHours <= 0) currentIntervalHours = 1; - else if (currentIntervalHours < curStageHrs) curStageHrs = currentIntervalHours; + currentIntervalTicks = PeriodRandomizer(curStage); + if (currentIntervalTicks < 0) currentIntervalTicks = 0; + else if (currentIntervalTicks < curStageTicks) curStageTicks = currentIntervalTicks; } if (crampPain < 0) crampPain = PainRandomizer(); InitializeExtraValues(); - if (cums == null) cums = new List(); - if (eggs == null) eggs = new List(); TakeLoosePregnancy(); @@ -1188,6 +1213,11 @@ namespace RJW_Menstruation initError = false; } + protected virtual void PreInitialize() + { + Notify_UpdatedGenes(); + } + protected virtual void InitializeExtraValues() { } @@ -1217,7 +1247,7 @@ namespace RJW_Menstruation float avglittersize; try { - avglittersize = Mathf.Max(Rand.ByCurveAverage(Pawn.def.race.litterSizeCurve), 1.0f); + avglittersize = Mathf.Max(Rand.ByCurveAverage(Pawn.RaceProps.litterSizeCurve), 1.0f); } catch (NullReferenceException) { @@ -1260,6 +1290,8 @@ namespace RJW_Menstruation protected virtual void BeforeSimulator() { + ovulationChanceCache = -1.0f; + implantationChanceCache = -1.0f; CumOut(); } @@ -1279,11 +1311,11 @@ namespace RJW_Menstruation switch (curStage) { case Stage.Follicular: - return curStageHrs > currentIntervalHours - Props.estrusDaysBeforeOvulation * 24; + return curStageTicks > currentIntervalTicks - Props.estrusDaysBeforeOvulation * GenDate.TicksPerDay; case Stage.Ovulatory: return true; case Stage.Luteal: - return curStageHrs < EggLifespanHours; + return curStageTicks < EggLifespanTicks; default: return false; } @@ -1333,9 +1365,12 @@ namespace RJW_Menstruation if (eligibleCum.Count == 0) return null; float totalFertPower = eligibleCum.Sum(cum => cum.FertVolume); + + //float fertFailChancePerHour = Mathf.Pow(1.0f - Configurations.FertilizeChance, totalFertPower * Props.basefertilizationChanceFactor); + //float fertFailChancePerInterval = Mathf.Pow(fertFailChancePerHour, (float)TickInterval / GenDate.TicksPerHour); + float fertFailChancePerInterval = Mathf.Pow(1.0f - Configurations.FertilizeChance, totalFertPower * Props.basefertilizationChanceFactor * SimulationsPerHour); - if (Rand.Chance(Mathf.Pow(1.0f - Configurations.FertilizeChance, totalFertPower * Props.basefertilizationChanceFactor))) - return null; + if (Rand.Chance(fertFailChancePerInterval)) return null; Pawn.records.AddTo(VariousDefOf.AmountofFertilizedEggs, 1); float selection = Rand.Range(0.0f, totalFertPower); @@ -1360,8 +1395,8 @@ namespace RJW_Menstruation foreach (Egg egg in eggs) { if (!egg.fertilized || - egg.fertstage < minImplantAgeHours || - egg.position < Math.Min(Props.lutealIntervalDays * 24 / 2, maxImplantDelayHours)) + egg.ticksSinceFertilization < minImplantAgeHours * GenDate.TicksPerHour || + egg.ageTicks < Math.Min(Props.lutealIntervalDays * GenDate.TicksPerDay / 2, maxImplantDelayHours * GenDate.TicksPerHour)) continue; else if (egg.fertilizer == null) { @@ -1445,14 +1480,18 @@ namespace RJW_Menstruation if (pregnancy is Hediff_BasePregnancy rjw_preg) { // TODO: advance biotech pregnancy - rjw_preg.p_start_tick -= egg.fertstage / Configurations.CycleAcceleration * GenDate.TicksPerHour; - rjw_preg.p_end_tick -= egg.fertstage / Configurations.CycleAcceleration * GenDate.TicksPerHour; + rjw_preg.p_start_tick -= egg.ticksSinceFertilization / Configurations.CycleAcceleration; + rjw_preg.p_end_tick -= egg.ticksSinceFertilization / Configurations.CycleAcceleration; } } } else - { - if (Configurations.Debug) Log.Message($"Fertilized egg of {Pawn} failed to implant (father {egg.fertilizer})"); + { + if (Configurations.Debug) + { + float implantChance = Configurations.ImplantationChance * ImplantChance * InterspeciesImplantFactor(egg.fertilizer); + Log.Message($"Fertilized egg of {Pawn} failed to implant (chance {implantChance.ToStringPercent()}, father {egg.fertilizer})"); + } deadeggs.Add(egg); } } @@ -1471,7 +1510,9 @@ namespace RJW_Menstruation protected void BleedOut() { - CumIn(Pawn, Rand.Range(0.02f * Configurations.BleedingAmount, 0.04f * Configurations.BleedingAmount), Translations.Menstrual_Blood, -5.0f, Pawn.def.race?.BloodDef ?? ThingDefOf.Filth_Blood); + // ~1.5 per hour times acceleration + float bledAmount = 0.03f * Configurations.BleedingAmount * Configurations.CycleAcceleration * Rand.Range(0.5f, 1.5f) * SimulationsPerHour; + CumIn(Pawn, bledAmount, Translations.Menstrual_Blood, -5.0f, Pawn.RaceProps?.BloodDef ?? ThingDefOf.Filth_Blood); Cum blood = GetNotCum(Translations.Menstrual_Blood); if (blood != null) blood.Color = BloodColor; } @@ -1538,12 +1579,12 @@ namespace RJW_Menstruation HashSet deadeggs = new HashSet(); foreach (Egg egg in eggs) { - egg.position += Configurations.CycleAcceleration; - if (egg.fertilized) egg.fertstage += Configurations.CycleAcceleration; + egg.ageTicks += TickInterval * Configurations.CycleAcceleration; + if (egg.fertilized) egg.ticksSinceFertilization += TickInterval * Configurations.CycleAcceleration; else { - egg.lifespanhrs -= Configurations.CycleAcceleration; - if (egg.lifespanhrs < 0) deadeggs.Add(egg); + egg.lifeSpanTicks -= TickInterval * Configurations.CycleAcceleration; + if (egg.lifeSpanTicks < 0) deadeggs.Add(egg); } } eggs.RemoveAll(egg => deadeggs.Contains(egg)); @@ -1554,7 +1595,7 @@ namespace RJW_Menstruation Hediff hediff = HediffMaker.MakeHediff(VariousDefOf.Hediff_MenstrualCramp, Pawn); hediff.Severity = crampPain * Rand.Range(0.9f, 1.1f); HediffCompProperties_SeverityPerDay Prop = (HediffCompProperties_SeverityPerDay)hediff.TryGetComp().props; - Prop.severityPerDay = -hediff.Severity / (currentIntervalHours / 24) * Configurations.CycleAcceleration; + Prop.severityPerDay = -hediff.Severity / (currentIntervalTicks / GenDate.TicksPerDay) * Configurations.CycleAcceleration; Pawn.health.AddHediff(hediff, Genital_Helper.get_genitalsBPR(Pawn)); } @@ -1566,14 +1607,14 @@ namespace RJW_Menstruation GoNextStage(Stage.Anestrus); return; } - else if (curStageHrs >= currentIntervalHours) + else if (curStageTicks >= currentIntervalTicks) { GoOvulatoryStage(); } else { - curStageHrs += Configurations.CycleAcceleration; - if (!estrusflag && curStageHrs > currentIntervalHours - Props.estrusDaysBeforeOvulation * 24) + curStageTicks += TickInterval * Configurations.CycleAcceleration; + if (!estrusflag && curStageTicks > currentIntervalTicks - Props.estrusDaysBeforeOvulation * GenDate.TicksPerDay) { estrusflag = true; SetEstrus(); @@ -1584,11 +1625,16 @@ namespace RJW_Menstruation protected virtual void OvulatoryAction() { + if (curStageTicks < currentIntervalTicks) + { + curStageTicks += TickInterval * Configurations.CycleAcceleration; + return; + } estrusflag = false; float eggnum; try { - eggnum = Math.Max(Rand.ByCurve(Pawn.def.race.litterSizeCurve), 1f); + eggnum = Math.Max(Rand.ByCurve(Pawn.RaceProps.litterSizeCurve), 1f); } catch (NullReferenceException) { @@ -1602,27 +1648,24 @@ namespace RJW_Menstruation eggnum *= ovulationFactor; int toOvulate = (int)eggnum + eggstack; - float ovulationChance = OvulationChance; int ovulated = 0; for (int i = 0; i < toOvulate; i++) - if (i < eggstack || Rand.Chance(ovulationChance)) // eggstack comes from drugs and are guaranteed ovulated + if (i < eggstack || Rand.Chance(OvulationChance)) // eggstack comes from drugs and are guaranteed ovulated { - eggs.Add(new Egg((int)(EggLifespanHours / CycleFactor))); + eggs.Add(new Egg((int)(EggLifespanTicks / CycleFactor))); ++ovulated; } - if(ovulated > ovarypower) ovulated = Math.Min(ovarypower, eggstack); - ovarypower -= ovulated; eggstack = 0; if (Configurations.Debug && ovulated != toOvulate) - Log.Message($"{Pawn} ovulated {ovulated}/{toOvulate} eggs ({ovulationChance.ToStringPercent()} chance)"); + Log.Message($"{Pawn} ovulated {ovulated}/{toOvulate} eggs ({OvulationChance.ToStringPercent()} chance)"); GoNextStage(Stage.Luteal); } protected virtual void LutealAction() { - if (curStageHrs >= currentIntervalHours) + if (curStageTicks >= currentIntervalTicks) { eggs.Clear(); if (EggHealth < 1f / 4f || (EggHealth < 1f / 3f && Rand.Chance(0.3f))) //skips bleeding @@ -1644,13 +1687,13 @@ namespace RJW_Menstruation } else { - curStageHrs += Configurations.CycleAcceleration; + curStageTicks += TickInterval * Configurations.CycleAcceleration; StayCurrentStage(); } } else { - curStageHrs += Configurations.CycleAcceleration; + curStageTicks += TickInterval * Configurations.CycleAcceleration; StayCurrentStage(); } @@ -1658,23 +1701,23 @@ namespace RJW_Menstruation protected virtual void BleedingAction() { - if (curStageHrs >= currentIntervalHours) + if (curStageTicks >= currentIntervalTicks) { Hediff hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_MenstrualCramp); if (hediff != null && !Pawn.GetMenstruationComps().Any(comp => comp != this && comp.curStage == Stage.Bleeding)) Pawn.health.RemoveHediff(hediff); - int totalFollicularHours = PeriodRandomizer(Stage.Follicular); // The total amount of time for both bleeding and follicular - if (totalFollicularHours <= currentIntervalHours) // We've bled for so long that we completely missed the follicular phase + int totalFollicularTicks = PeriodRandomizer(Stage.Follicular); // The total amount of time for both bleeding and follicular + if (totalFollicularTicks <= currentIntervalTicks) // We've bled for so long that we completely missed the follicular phase GoOvulatoryStage(); else { - currentIntervalHours = totalFollicularHours - currentIntervalHours; // I.e., the remaining follicular hours equals the total minus the bleeding hours elapsed + currentIntervalTicks = totalFollicularTicks - currentIntervalTicks; // I.e., the remaining follicular time equals the total minus the bleeding time elapsed GoNextStage(Stage.Follicular, false); } } else { - if (curStageHrs < currentIntervalHours / 4) for (int i = 0; i < Configurations.CycleAcceleration; i++) BleedOut(); - curStageHrs += Configurations.CycleAcceleration; + if (curStageTicks < currentIntervalTicks / 4) BleedOut(); + curStageTicks += TickInterval * Configurations.CycleAcceleration; StayCurrentStage(); } } @@ -1690,7 +1733,7 @@ namespace RJW_Menstruation if (pregnancy != null && Pawn.health.hediffSet.hediffs.Contains(pregnancy)) { - curStageHrs += 1; + curStageTicks += TickInterval; StayCurrentStageConst(Stage.Pregnant); } else @@ -1702,7 +1745,7 @@ namespace RJW_Menstruation protected virtual void RecoverAction() { - if (curStageHrs >= currentIntervalHours) + if (curStageTicks >= currentIntervalTicks) { if (ShouldBeInfertile()) { @@ -1719,7 +1762,7 @@ namespace RJW_Menstruation } else { - curStageHrs += Configurations.CycleAcceleration; + curStageTicks += TickInterval * Configurations.CycleAcceleration; StayCurrentStage(); } } @@ -1754,8 +1797,7 @@ namespace RJW_Menstruation if (!xxx.is_human(Pawn) || !xxx.is_human(cummer)) return; if ((cummer.HasQuirk(QuirkUtility.Quirks.Teratophile) != (Pawn.GetStatValue(StatDefOf.PawnBeauty) >= 0)) || - cummer.HasQuirk(QuirkUtility.Quirks.ImpregnationFetish) || - cummer.HasQuirk(QuirkUtility.Quirks.Breeder)) + cummer.IsProPregnancy()) { if (cummer.relations.OpinionOf(Pawn) <= -25) { @@ -1769,7 +1811,7 @@ namespace RJW_Menstruation if (IsDangerDay) { - if (Pawn.HasQuirk(QuirkUtility.Quirks.Breeder) || Pawn.HasQuirk(QuirkUtility.Quirks.ImpregnationFetish)) + if (Pawn.IsProPregnancy()) { Pawn.needs.mood.thoughts.memories.TryGainMemory(VariousDefOf.CameInsideFFetish, cummer); } @@ -1792,7 +1834,7 @@ namespace RJW_Menstruation } else { - if (Pawn.HasQuirk(QuirkUtility.Quirks.Breeder) || Pawn.HasQuirk(QuirkUtility.Quirks.ImpregnationFetish)) + if (Pawn.IsProPregnancy()) { Pawn.needs.mood.thoughts.memories.TryGainMemory(VariousDefOf.CameInsideFFetishSafe, cummer); } @@ -1815,8 +1857,8 @@ namespace RJW_Menstruation public void GoNextStage(Stage nextstage, bool calculateHours = true) { - curStageHrs = 0; - if (calculateHours) currentIntervalHours = PeriodRandomizer(nextstage); + curStageTicks = 0; + if (calculateHours) currentIntervalTicks = PeriodRandomizer(nextstage); curStage = nextstage; } @@ -1858,15 +1900,17 @@ namespace RJW_Menstruation switch (stage) { case Stage.Follicular: - return (int)(Props.follicularIntervalDays * 24 * (1 + Rand.Range(-cycleVariability, cycleVariability) * 1.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 1.5f)); + return (int)(Props.follicularIntervalDays * GenDate.TicksPerDay * (1 + Rand.Range(-cycleVariability, cycleVariability) * 1.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 1.5f)); + case Stage.Ovulatory: + return Props.ovulationIntervalHours * GenDate.TicksPerHour; // No variability for now case Stage.Luteal: - return (int)(Props.lutealIntervalDays * 24 * (1 + Rand.Range(-cycleVariability, cycleVariability) * 0.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 0.5f)); + return (int)(Props.lutealIntervalDays * GenDate.TicksPerDay * (1 + Rand.Range(-cycleVariability, cycleVariability) * 0.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 0.5f)); case Stage.Bleeding: - return (int)(Props.bleedingIntervalDays * 24 * (1 + Rand.Range(-cycleVariability, cycleVariability) * 0.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 0.5f)); + return (int)(Props.bleedingIntervalDays * GenDate.TicksPerDay * (1 + Rand.Range(-cycleVariability, cycleVariability) * 0.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 0.5f)); case Stage.Recover: - return (int)(Props.recoveryIntervalDays * 24 * Rand.Range(0.95f, 1.05f)); + return (int)(Props.recoveryIntervalDays * GenDate.TicksPerDay * Rand.Range(0.95f, 1.05f)); case Stage.Pregnant: - return (int)MenstruationUtility.GestationHours(pregnancy); + return (int)(MenstruationUtility.GestationHours(pregnancy) * GenDate.TicksPerHour); default: return 1; } @@ -1902,13 +1946,13 @@ namespace RJW_Menstruation switch (stage) { case Stage.Follicular: - curStageHrs = Rand.Range(0, (Props.follicularIntervalDays - Props.bleedingIntervalDays) * 24); + curStageTicks = Rand.Range(0, (Props.follicularIntervalDays - Props.bleedingIntervalDays) * GenDate.TicksPerDay); break; case Stage.Luteal: - curStageHrs = Rand.Range(0, Props.lutealIntervalDays * 24); + curStageTicks = Rand.Range(0, Props.lutealIntervalDays * GenDate.TicksPerDay); break; case Stage.Bleeding: - curStageHrs = Rand.Range(0, Props.bleedingIntervalDays * 24); + curStageTicks = Rand.Range(0, Props.bleedingIntervalDays * GenDate.TicksPerDay); break; } return stage; @@ -1954,38 +1998,52 @@ namespace RJW_Menstruation public class Egg : IExposable { public bool fertilized; - public int lifespanhrs; + public int lifeSpanTicks; // Actual ticks scaled by cycleAcceleration public Pawn fertilizer; - public int position; - public int fertstage = 0; + public int ageTicks; + public int ticksSinceFertilization = 0; public Egg() { fertilized = false; - lifespanhrs = (int)(96 * Configurations.EggLifespanMultiplier); + lifeSpanTicks = (int)(96 * GenDate.TicksPerHour * Configurations.EggLifespanMultiplier); fertilizer = null; - position = 0; + ageTicks = 0; } - public Egg(int lifespanhrs) + public Egg(int lifespanticks) { fertilized = false; - this.lifespanhrs = (int)(lifespanhrs * Configurations.EggLifespanMultiplier); + lifeSpanTicks = (int)(lifespanticks * Configurations.EggLifespanMultiplier); fertilizer = null; - position = 0; + ageTicks = 0; } public void ExposeData() { + if (Scribe.mode == LoadSaveMode.LoadingVars) + { + int lifespanhrs = -1; + int position = -1; + Scribe_Values.Look(ref lifespanhrs, "lifespanhrs", lifespanhrs, true); + Scribe_Values.Look(ref position, "position", position, true); + if (lifespanhrs >= 0) lifeSpanTicks = lifespanhrs * GenDate.TicksPerHour; + if (position >= 0) ageTicks = position * GenDate.TicksPerHour; + } Scribe_References.Look(ref fertilizer, "fertilizer", true); - Scribe_Values.Look(ref fertilized, "fertilized", fertilized, true); - Scribe_Values.Look(ref lifespanhrs, "lifespanhrs", lifespanhrs, true); - Scribe_Values.Look(ref position, "position", position, true); - Scribe_Values.Look(ref fertstage, "fertstage", fertstage, true); + Scribe_Values.Look(ref fertilized, "fertilized", false); + Scribe_Values.Look(ref lifeSpanTicks, "lifeSpanTicks", lifeSpanTicks, true); + Scribe_Values.Look(ref ageTicks, "ageTicks", ageTicks, true); + Scribe_Values.Look(ref ticksSinceFertilization, "ticksSinceFertilization", 0); + if (ticksSinceFertilization == 0 && Scribe.mode == LoadSaveMode.LoadingVars) + { + // A bit awkward to do this twice, but it prevents ticksSinceFertilization from getting overwritten on a fertstage load + int fertstage = -1; + Scribe_Values.Look(ref fertstage, "fertstage", fertstage, true); + if (fertstage >= 0) ticksSinceFertilization = fertstage * GenDate.TicksPerHour; + } } } - - } public class HediffComp_Anus : HediffComp diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PeriodicOvulator.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PeriodicOvulator.cs index 6611547..017a6ed 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PeriodicOvulator.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PeriodicOvulator.cs @@ -16,23 +16,28 @@ namespace RJW_Menstruation public class HediffComp_PeriodicOvulator : HediffComp_Menstruation { - public int hoursToNextCycle = -100000; - public int averageCycleIntervalHours = -1; + public int ticksToNextCycle = -100000; + public int averageCycleIntervalTicks = -1; public new CompProperties_PeriodicOvulator Props; + protected override void PreInitialize() + { + base.PreInitialize(); + Props = (CompProperties_PeriodicOvulator)props; + } + protected override void InitializeExtraValues() { - base.InitializeExtraValues(); - Props = (CompProperties_PeriodicOvulator)props; - if (averageCycleIntervalHours < 0) + base.InitializeExtraValues(); + if (averageCycleIntervalTicks < 0) { - averageCycleIntervalHours = (int)(24f * Props.cycleIntervalDays.RandomInRange / cycleSpeed); - if (hoursToNextCycle < -50000) - hoursToNextCycle = Rand.Range(0, averageCycleIntervalHours); + averageCycleIntervalTicks = (int)(Props.cycleIntervalDays.RandomInRange * GenDate.TicksPerDay / cycleSpeed); + if (ticksToNextCycle < -50000) + ticksToNextCycle = Rand.Range(0, averageCycleIntervalTicks); // Make the cutoff halfway into cycle, just to be sure there isn't a double-cycle the first time if ((curStage == Stage.Follicular || curStage == Stage.Luteal || curStage == Stage.Bleeding) - && (averageCycleIntervalHours - hoursToNextCycle) / 2 >= 24 * (Props.follicularIntervalDays + Props.lutealIntervalDays) / cycleSpeed) + && (averageCycleIntervalTicks - ticksToNextCycle) / 2 >= GenDate.TicksPerDay * (Props.follicularIntervalDays + Props.lutealIntervalDays) / cycleSpeed) GoNextStage(Stage.Anestrus); } } @@ -40,40 +45,46 @@ namespace RJW_Menstruation protected override float RaceCyclesPerYear() { // Don't bother trying to work seasonal breeding into the math - // Due to the enormous variation in possible cycle gaps, cheat and base it off the individual - return averageCycleIntervalHours * cycleSpeed / (24 * 360); // cancel out their cycleSpeed from initialization to get their "normal" speed + // Base it off of the shortest cycle interval of the vagina + return GenDate.DaysPerYear / (Props.cycleIntervalDays.TrueMin / Configurations.CycleAccelerationDefault); } protected override void BeforeSimulator() { base.BeforeSimulator(); - if (hoursToNextCycle > 0) hoursToNextCycle -= Configurations.CycleAcceleration; + if (ticksToNextCycle > 0) ticksToNextCycle -= TickInterval * Configurations.CycleAcceleration; } public override void CompExposeData() { base.CompExposeData(); - Scribe_Values.Look(ref hoursToNextCycle, "hoursToNextCycle", hoursToNextCycle, true); - Scribe_Values.Look(ref averageCycleIntervalHours, "averageCycleIntervalHours", averageCycleIntervalHours, true); + if (Scribe.mode == LoadSaveMode.LoadingVars) + { + int hoursToNextCycle = -1; + int averageCycleIntervalHours = -1; + Scribe_Values.Look(ref hoursToNextCycle, "hoursToNextCycle", hoursToNextCycle, true); + Scribe_Values.Look(ref averageCycleIntervalHours, "averageCycleIntervalHours", averageCycleIntervalHours, true); + if (hoursToNextCycle >= 0) ticksToNextCycle = hoursToNextCycle * GenDate.TicksPerHour; + if (averageCycleIntervalHours >= 0) averageCycleIntervalTicks = averageCycleIntervalHours * GenDate.TicksPerHour; + } + Scribe_Values.Look(ref ticksToNextCycle, "ticksToNextCycle", ticksToNextCycle, true); + Scribe_Values.Look(ref averageCycleIntervalTicks, "averageCycleIntervalTicks", averageCycleIntervalTicks, true); } - protected override int HoursToNextStage() + protected override int TicksToNextStage() { - if (curStage == Stage.Anestrus && hoursToNextCycle > 0) return hoursToNextCycle / Configurations.CycleAcceleration; - else return base.HoursToNextStage(); + if (curStage == Stage.Anestrus && ticksToNextCycle > 0) return ticksToNextCycle / Configurations.CycleAcceleration; + else return base.TicksToNextStage(); } protected override void BleedingAction() { - if (curStageHrs >= currentIntervalHours) + base.BleedingAction(); + if (curStage != Stage.Bleeding) { - Hediff hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_MenstrualCramp); - if (hediff != null && !Pawn.GetMenstruationComps().Any(comp => comp != this && comp.curStage == Stage.Bleeding)) Pawn.health.RemoveHediff(hediff); estrusflag = false; GoNextStage(Stage.Anestrus); - return; } - else base.BleedingAction(); } protected override void PregnantAction() @@ -81,14 +92,14 @@ namespace RJW_Menstruation base.PregnantAction(); if (curStage != Stage.Pregnant) // Go halfway into the cycle - hoursToNextCycle = (int)(averageCycleIntervalHours * (1 + Rand.Range(-cycleVariability, cycleVariability))) / 2; + ticksToNextCycle = (int)(averageCycleIntervalTicks * (1 + Rand.Range(-cycleVariability, cycleVariability))) / 2; } protected override void AnestrusAction() { - if (hoursToNextCycle <= 0) + if (ticksToNextCycle <= 0) { - hoursToNextCycle = (int)(averageCycleIntervalHours * (1 + Rand.Range(-cycleVariability, cycleVariability))); + ticksToNextCycle = (int)(averageCycleIntervalTicks * (1 + Rand.Range(-cycleVariability, cycleVariability))); if (IsBreedingSeason()) GoNextStage(Stage.Follicular); return; } @@ -99,7 +110,7 @@ namespace RJW_Menstruation { base.CopyCycleProperties(original); if (original is HediffComp_PeriodicOvulator comp) - averageCycleIntervalHours = comp.averageCycleIntervalHours; + averageCycleIntervalTicks = comp.averageCycleIntervalTicks; } } } diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PregeneratedBabies.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PregeneratedBabies.cs index 8d7ab50..ce0efe9 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PregeneratedBabies.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PregeneratedBabies.cs @@ -213,7 +213,7 @@ namespace RJW_Menstruation 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; + if (mother.Dead) break; if (xxx.is_human(baby)) mother.records.Increment(xxx.CountOfBirthHuman); else if (xxx.is_animal(baby)) @@ -266,7 +266,7 @@ namespace RJW_Menstruation baby.relations.ClearAllRelations(); PregnancyUtility.ApplyBirthOutcome(outcome, quality, ritual, genes, geneticMother, birtherThing, thisFather, doctor, lordJobRitual, assignments); - if (mother.health.Dead) break; + if (mother.Dead) break; if (xxx.is_human(baby)) mother.records.Increment(xxx.CountOfBirthHuman); else if (xxx.is_animal(baby)) diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/MenstruationUtility.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/MenstruationUtility.cs index d67fbb4..c3cd7e4 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/MenstruationUtility.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/HediffComps/MenstruationUtility.cs @@ -3,6 +3,7 @@ using RimWorld.Planet; using rjw; using System; using System.Collections.Generic; +using System.Diagnostics.Eventing.Reader; using System.Linq; using UnityEngine; using Verse; @@ -217,44 +218,50 @@ namespace RJW_Menstruation return wombtex; } + public static Texture2D GetOvaryIcon(this HediffComp_Menstruation comp) + { + const float ovaryChanceToShow_01 = 0.2f; + const float ovaryChanceToShow_02 = 0.8f; + float ovulatoryProgress; + bool isInduced = comp is HediffComp_InducedOvulator; + if (comp.curStage == HediffComp_Menstruation.Stage.Follicular && + isInduced && + comp.Pawn.jobs.curDriver is JobDriver_Sex job && + job.Sexprops != null && + !job.Sexprops.usedCondom && + (job.Sexprops.sexType == xxx.rjwSextype.Vaginal || job.Sexprops.sexType == xxx.rjwSextype.DoublePenetration)) + ovulatoryProgress = 0.0f; + else if (comp.curStage == HediffComp_Menstruation.Stage.Ovulatory) ovulatoryProgress = isInduced ? Mathf.Max(ovaryChanceToShow_01, comp.StageProgessNextUpdate) : comp.StageProgessNextUpdate; +// else if (comp.curStage == HediffComp_Menstruation.Stage.Luteal && comp.IsEggExist) return ContentFinder.Get("Ovaries/Ovary_02", true); + else return ContentFinder.Get("Womb/Empty", true); + + float combinedAppearance = ovulatoryProgress * comp.OvulationChance; + if (combinedAppearance >= ovaryChanceToShow_02 && comp.OvulationChance >= 1.0f) return ContentFinder.Get("Ovaries/Ovary_02", true); + else if (combinedAppearance >= ovaryChanceToShow_01) return ContentFinder.Get("Ovaries/Ovary_01", true); + else return ContentFinder.Get("Ovaries/Ovary_00", true); + } public static Texture2D GetEggIcon(this HediffComp_Menstruation comp, bool includeOvary) { - const float ovaryChanceToShow_01 = 0.4f; - const float ovaryChanceToShow_02 = 1.0f; switch (comp.CurrentVisibleStage) { case HediffComp_Menstruation.Stage.Follicular: - if (!includeOvary) break; - if (comp is HediffComp_InducedOvulator) - { - if (comp.Pawn.jobs.curDriver is JobDriver_Sex job && - job.Sexprops != null && - !job.Sexprops.usedCondom && - (job.Sexprops.sexType == xxx.rjwSextype.Vaginal || job.Sexprops.sexType == xxx.rjwSextype.DoublePenetration)) - return ContentFinder.Get((comp.OvulationChance >= ovaryChanceToShow_01) ? "Ovaries/Ovary_01" : "Ovaries_Ovary_00", true); - else break; - } - if (comp.curStageHrs > comp.CurStageIntervalHours - 30) // Approximate time for ovulation to occur - return ContentFinder.Get((comp.OvulationChance >= ovaryChanceToShow_01) ? "Ovaries/Ovary_01" : "Ovaries_Ovary_00", true); - else break; case HediffComp_Menstruation.Stage.Ovulatory: if (!includeOvary) break; - if (comp.OvulationChance >= ovaryChanceToShow_02) - return ContentFinder.Get("Ovaries/Ovary_02", true); - else if (comp.OvulationChance >= ovaryChanceToShow_01) - return ContentFinder.Get("Ovaries/Ovary_01", true); - else - return ContentFinder.Get("Ovaries/Ovary_00", true); + else return GetOvaryIcon(comp); case HediffComp_Menstruation.Stage.Luteal: if (!comp.IsEggExist) break; - int fertstage = comp.IsFertilized; - if (fertstage >= 0) + int fertTime = comp.EggFertilizedTime; + if (fertTime >= 0) { - if (fertstage <= Configurations.CycleAcceleration) return ContentFinder.Get("Eggs/Egg_Fertilizing02", true); - else if (fertstage <= 18) return ContentFinder.Get("Eggs/Egg_Fertilized00", true); - else if (fertstage <= 54) return ContentFinder.Get("Eggs/Egg_Fertilized01", true); + if (fertTime <= GenDate.TicksPerHour * Configurations.CycleAcceleration) return ContentFinder.Get("Eggs/Egg_Fertilizing02", true); + else if (fertTime <= 18 * GenDate.TicksPerHour) return ContentFinder.Get("Eggs/Egg_Fertilized00", true); + else if (fertTime <= 54 * GenDate.TicksPerHour) return ContentFinder.Get("Eggs/Egg_Fertilized01", true); else return ContentFinder.Get("Eggs/Egg_Fertilized02", true); } + else if (includeOvary && comp.curStageTicks <= comp.Props.ovulationIntervalHours * 0.4f * GenDate.TicksPerHour) // Total about as long as it spent in Ovary_01 + { + return ContentFinder.Get("Ovaries/Ovary_02", true); + } else if (comp.IsEggFertilizing) { if (comp.GetFertilityChance() < 0.5f) @@ -348,7 +355,7 @@ namespace RJW_Menstruation else if (hediff is Hediff_BasePregnancy rjw_preg) return (rjw_preg.p_end_tick - rjw_preg.p_start_tick) / GenDate.TicksPerHour; // TODO: Biotech pregnancy - else return hediff.pawn.def.race.gestationPeriodDays * GenDate.HoursPerDay; + else return hediff.pawn.RaceProps.gestationPeriodDays * GenDate.HoursPerDay; } public static float RandomVariabilityPercent(int recursion = 0) @@ -400,6 +407,22 @@ namespace RJW_Menstruation return false; } + public static bool IsProPregnancy(this Pawn pawn) + { + if (pawn.HasQuirk(QuirkUtility.Quirks.Breeder) || + pawn.HasQuirk(QuirkUtility.Quirks.ImpregnationFetish)) + return true; + + Ideo ideo = pawn.Ideo; + if (ideo == null || VariousDefOf.Pregnancy_Elevated == null) return false; + if (ideo.HasPrecept(VariousDefOf.Pregnancy_Elevated) || + ideo.HasPrecept(VariousDefOf.Pregnancy_Holy) || + ideo.HasPrecept(VariousDefOf.Pregnancy_Required)) + return true; + + return false; + } + public static float DamagePants(this Pawn pawn, float fluidAmount) { if (pawn.apparel == null) return 0; diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs index b47d614..0b5d0c5 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs @@ -23,11 +23,11 @@ namespace RJW_Menstruation { if (is_discovered || !xxx.is_human(pawn) || - pawn.HasQuirk(QuirkUtility.Quirks.Breeder) || + pawn.HasQuirk(QuirkUtility.Quirks.Breeder) || (pawn.Ideo?.HasPrecept(VariousDefOf.Pregnancy_Required) ?? false) || (pawn.relations?.DirectRelations?.Find(x => x.def.Equals(PawnRelationDefOf.Spouse) || x.def.Equals(PawnRelationDefOf.Fiance))) != null) return; - if (pawn.HasQuirk(QuirkUtility.Quirks.ImpregnationFetish) || pawn.relations?.DirectRelations?.Find(x => x.def.Equals(PawnRelationDefOf.Lover)) != null) + if (pawn.IsProPregnancy() || pawn.relations?.DirectRelations?.Find(x => x.def.Equals(PawnRelationDefOf.Lover)) != null) { pawn.needs.mood.thoughts.memories.TryGainMemory(VariousDefOf.UnwantedPregnancyMild); } diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/Patch/Biotech_Patch.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/Patch/Biotech_Patch.cs index df6584b..4bd3cef 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/Patch/Biotech_Patch.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/Patch/Biotech_Patch.cs @@ -117,7 +117,7 @@ namespace RJW_Menstruation { public static void Postfix(Thing birtherThing) { - if (birtherThing is Pawn pawn && !pawn.health.Dead) + if (birtherThing is Pawn pawn && !pawn.Dead) pawn.GetBreastComp()?.GaveBirth(); } } @@ -192,17 +192,20 @@ namespace RJW_Menstruation } } - [HarmonyPatch(typeof(Pawn_GeneTracker), "AddGene", new Type[] {typeof(Gene), typeof(bool)})] + [HarmonyPatch(typeof(Pawn_GeneTracker), "AddGene", new Type[] { typeof(Gene), typeof(bool) })] public class AddGene_Patch { public static bool Prefix(ref Gene __result, Gene gene, Pawn ___pawn) { - if(VariousDefOf.WombGenes.Contains(gene.def) && !___pawn.GetMenstruationComps().Any()) - { - __result = null; - return false; - } - else return true; + if (!VariousDefOf.WombGenes.Contains(gene.def)) return true; + bool keepGene; + if (PawnGenerator.IsBeingGenerated(___pawn)) + // During pawn generation, the vagina hediff doesn't exist yet, so use gender to decide instead + // Not the most accurate, but close enough + keepGene = ___pawn.gender == Gender.Female; + else keepGene = ___pawn.GetMenstruationComps().Any(); + if (!keepGene) __result = null; + return keepGene; } } diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/Patch/GC_Patch.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/Patch/GC_Patch.cs index 79e7be5..37eda3e 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/Patch/GC_Patch.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/Patch/GC_Patch.cs @@ -16,7 +16,7 @@ namespace RJW_Menstruation.Patch { if (!__result.NullOrEmpty()) return; if (cummedPawns.Contains(pawn)) - __result = "Has cum or fertilized egg in a womb"; + __result = "EggFertOrCumInWomb"; } } diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/Patch/Gizmo_Patch.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/Patch/Gizmo_Patch.cs index 7185ccf..86ef4d9 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/Patch/Gizmo_Patch.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/Patch/Gizmo_Patch.cs @@ -1,4 +1,5 @@ using HarmonyLib; +using RimWorld; using rjw; using System.Collections.Generic; using System.Linq; @@ -42,12 +43,12 @@ namespace RJW_Menstruation private static Gizmo CreateGizmo_WombStatus(Pawn pawn, HediffComp_Menstruation comp) { - Texture2D icon, icon_overay; + Texture2D icon, icon_overlay; StringBuilder description = new StringBuilder(); if (Configurations.Debug) { description - .AppendFormat("{0}: {1}\n", comp.curStage, comp.curStageHrs); + .AppendFormat("{0}: {1}\n", comp.curStage, comp.curStageTicks / GenDate.TicksPerHour); if (comp.Pregnancy is Hediff_BasePregnancy rjwpreg) description .AppendFormat("due: {0}\n", rjwpreg.DueDate()); else if (comp.Pregnancy is Hediff_Pregnant biopreg) description @@ -68,15 +69,15 @@ namespace RJW_Menstruation float gestationProgress = comp.StageProgress; if (hediff is Hediff_BasePregnancy || hediff is HediffWithParents) { - if (gestationProgress < 0.2f) icon_overay = comp.GetCumIcon(); - else icon_overay = ContentFinder.Get(("Womb/Empty"), true); + if (gestationProgress < 0.2f) icon_overlay = comp.GetCumIcon(); + else icon_overlay = ContentFinder.Get(("Womb/Empty"), true); } - else icon_overay = ContentFinder.Get(("Womb/Empty"), true); + else icon_overlay = ContentFinder.Get(("Womb/Empty"), true); } else { icon = comp.GetWombIcon(); - icon_overay = comp.GetCumIcon(); + icon_overlay = comp.GetCumIcon(); } } else @@ -90,7 +91,7 @@ namespace RJW_Menstruation { icon = comp.GetWombIcon(); } - icon_overay = comp.GetCumIcon(); + icon_overlay = comp.GetCumIcon(); } foreach (string s in comp.GetCumsInfo) description.AppendFormat("{0}\n", s); @@ -102,7 +103,7 @@ namespace RJW_Menstruation defaultLabel = pawn.LabelShort, defaultDesc = description.ToString(), icon = icon, - icon_overay = icon_overay, + icon_overlay = icon_overlay, shrinkable = Configurations.AllowShrinkIcon, cumcolor = c, comp = comp, diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/TextureCache.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/TextureCache.cs index b1c3853..4c9c591 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/TextureCache.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/TextureCache.cs @@ -15,13 +15,13 @@ namespace RJW_Menstruation return milktexturecache; } } - // Sex drive - public static Texture2D SexDriveTexture + // Ovulation, sex drive + public static Texture2D OvulatoryTexture { get { - if (sexdrivetexturecache == null) sexdrivetexturecache = SolidColorMaterials.NewSolidColorTexture(0.686f, 0.062f, 0.698f, 1.0f); - return sexdrivetexturecache; + if (ovulatorytexturecache == null) ovulatorytexturecache = SolidColorMaterials.NewSolidColorTexture(0.686f, 0.062f, 0.698f, 1.0f); + return ovulatorytexturecache; } } // Bleeding, vulnerability @@ -93,7 +93,7 @@ namespace RJW_Menstruation public static readonly Texture2D GatherCum_Pussy = ContentFinder.Get("UI/Icon/ToPussy"); private static Texture2D milktexturecache = SolidColorMaterials.NewSolidColorTexture(0.992f, 1.0f, 0.960f, 1.0f); - private static Texture2D sexdrivetexturecache = SolidColorMaterials.NewSolidColorTexture(0.686f, 0.062f, 0.698f, 1.0f); + private static Texture2D ovulatorytexturecache = SolidColorMaterials.NewSolidColorTexture(0.686f, 0.062f, 0.698f, 1.0f); private static Texture2D bleedingtexturecache = SolidColorMaterials.NewSolidColorTexture(0.415f, 0.0f, 0.003f, 1.0f); private static Texture2D pregnanttexturecache = SolidColorMaterials.NewSolidColorTexture(0.082f, 0.453f, 0.6f, 1.0f); private static Texture2D recovertexturecache = SolidColorMaterials.NewSolidColorTexture(0.6f, 0.83f, 0.35f, 1.0f); @@ -101,10 +101,5 @@ namespace RJW_Menstruation private static Texture2D animaltexturecache = SolidColorMaterials.NewSolidColorTexture(0.411f, 0.521f, 0.878f, 1.0f); private static Texture2D lutealtexturecache = SolidColorMaterials.NewSolidColorTexture(0.843f, 0.474f, 0.6f, 1.0f); private static Texture2D whoredtexturecache = SolidColorMaterials.NewSolidColorTexture(0.7f, 0.7f, 0.0f, 1.0f); - - - - - } } diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/Things.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/Things.cs index e427e0f..5e4dd91 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/Things.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/Things.cs @@ -197,7 +197,8 @@ namespace RJW_Menstruation public float absorbedfluids = 0; public bool dirty = false; - public int wearhours = 0; + public int wearTicks = 0; + protected virtual float PassiveAbsorptionPerHour => 0.1f; public virtual bool LeakAfterDirty => def.GetModExtension().leakAfterDirty; public virtual bool EffectAfterDirty => def.GetModExtension().effectsAfterDirty; public virtual ThingDef DirtyDef => def.GetModExtension().dirtyDef; @@ -205,12 +206,12 @@ namespace RJW_Menstruation public Color fluidColor = Color.white; - public virtual void DirtyEffect() { } + public virtual void DirtyEffect(int tickInterval) { } - public virtual void WearEffect() + public virtual void WearEffect(int tickInterval) { - absorbedfluids += 0.1f; - if (dirty) wearhours++; + absorbedfluids += PassiveAbsorptionPerHour * tickInterval / GenDate.TicksPerHour; + if (dirty) wearTicks += tickInterval; } public override Color DrawColorTwo => fluidColor; @@ -218,26 +219,27 @@ namespace RJW_Menstruation public override void ExposeData() { base.ExposeData(); - Scribe_Values.Look(ref absorbedfluids, "absorbedfluids", absorbedfluids, true); - Scribe_Values.Look(ref dirty, "dirty", dirty, true); - Scribe_Values.Look(ref wearhours, "wearhours", wearhours, true); - Scribe_Values.Look(ref fluidColor, "fluidColor", fluidColor, true); + if(Scribe.mode == LoadSaveMode.LoadingVars) + { + int wearhours = -1; + Scribe_Values.Look(ref wearhours, "wearhours", wearhours, true); + if (wearhours >= 0) wearTicks = wearhours * GenDate.TicksPerHour; + } + Scribe_Values.Look(ref absorbedfluids, "absorbedfluids", 0); + Scribe_Values.Look(ref dirty, "dirty", false); + Scribe_Values.Look(ref wearTicks, "wearTicks", 0); + Scribe_Values.Look(ref fluidColor, "fluidColor", Color.white); } } public class Absorber_Tampon : Absorber { - - public override void WearEffect() + protected override float PassiveAbsorptionPerHour => 0.5f; + public override void DirtyEffect(int tickInterval) { - if (dirty) wearhours++; - absorbedfluids += 0.5f; - } - public override void DirtyEffect() - { - if (wearhours > MinHrstoDirtyEffect && Rand.Chance(0.01f) && !Wearer.apparel.IsLocked(this)) + if (wearTicks > MinHrstoDirtyEffect * GenDate.TicksPerHour && Rand.MTBEventOccurs(100.0f, GenDate.TicksPerHour, tickInterval) && !Wearer.apparel.IsLocked(this)) { Wearer.health.AddHediff(HediffDefOf.WoundInfection, Genital_Helper.get_genitalsBPR(Wearer)); } @@ -254,7 +256,7 @@ namespace RJW_Menstruation public override void ExposeData() { base.ExposeData(); - Scribe_Values.Look(ref color, "color", color, true); + Scribe_Values.Look(ref color, "color", Color.white); } public override Color DrawColor diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/Translations.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/Translations.cs index 1a67ebf..dd2982f 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/Translations.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/Translations.cs @@ -60,6 +60,12 @@ namespace RJW_Menstruation public static readonly string Option6_Desc = "Option6_Desc".Translate(); public static readonly string Option7_Label = "Option7_Label".Translate(); public static readonly string Option7_Desc = "Option7_Desc".Translate(); + public static readonly string Option_ColonistUpdateInterval_Label = "Option_ColonistUpdateInterval_Label".Translate(); + public static readonly string Option_ColonistUpdateInterval_Desc = "Option_ColonistUpdateInterval_Desc".Translate(); + public static readonly string Option_NonColonistUpdateInterval_Label = "Option_NonColonistUpdateInterval_Label".Translate(); + public static readonly string Option_NonColonistUpdateInterval_Desc = "Option_NonColonistUpdateInterval_Desc".Translate(); + public static readonly string Option_AnimalUpdateInterval_Label = "Option_AnimalUpdateInterval_Label".Translate(); + public static readonly string Option_AnimalUpdateInterval_Desc = "Option_AnimalUpdateInterval_Desc".Translate(); public static readonly string Option8_Label = "Option8_Label".Translate(); public static readonly string Option8_Desc = "Option8_Desc".Translate(); public static readonly string Option9_Label = "Option9_Label".Translate(); diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs index 9b726b2..0448aac 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs @@ -433,7 +433,7 @@ namespace RJW_Menstruation float statvalue; const float height = 24f; statvalue = pawn.GetStatValue(xxx.sex_drive_stat); - FillableBarLabeled(lineRect, " " + xxx.sex_drive_stat.LabelCap.CapitalizeFirst() + " " + statvalue.ToStringPercent(), statvalue / 2, TextureCache.SexDriveTexture, Texture2D.blackTexture, xxx.sex_drive_stat.description); + FillableBarLabeled(lineRect, " " + xxx.sex_drive_stat.LabelCap.CapitalizeFirst() + " " + statvalue.ToStringPercent(), statvalue / 2, TextureCache.OvulatoryTexture, Texture2D.blackTexture, xxx.sex_drive_stat.description); lineRect.y += height; statvalue = pawn.GetStatValue(xxx.vulnerability_stat); @@ -462,8 +462,8 @@ namespace RJW_Menstruation statvalue = Configurations.ImplantationChance * comp.ImplantChance; float fertchance = comp.GetFertilityChance(); FillableBarLabeled(lineRect, " " + xxx.reproduction.LabelCap.CapitalizeFirst() + " " + statvalue.ToStringPercent(), statvalue, TextureCache.LutealTexture, Texture2D.blackTexture, Translations.FertilityDesc(string.Format("{0:0.##}", fertchance * 100))); - Rect overayRect = new Rect(lineRect.x, lineRect.y, lineRect.width * Math.Min(1.0f, fertchance), lineRect.height); - GUI.DrawTexture(overayRect, TextureCache.FertChanceTex); + Rect overlayRect = new Rect(lineRect.x, lineRect.y, lineRect.width * Math.Min(1.0f, fertchance), lineRect.height); + GUI.DrawTexture(overlayRect, TextureCache.FertChanceTex); lineRect.y += height; } diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/UI/Gizmo_Womb.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/UI/Gizmo_Womb.cs index c303d4e..aaaa96f 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/UI/Gizmo_Womb.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/UI/Gizmo_Womb.cs @@ -5,7 +5,7 @@ namespace RJW_Menstruation { public class Gizmo_Womb : Command_Action { - public Texture2D icon_overay; + public Texture2D icon_overlay; public Color cumcolor; public HediffComp_Menstruation comp; @@ -14,23 +14,23 @@ namespace RJW_Menstruation public override void DrawIcon(Rect rect, Material buttonMat, GizmoRenderParms parms) { Texture badTex = icon; - Texture2D overay = icon_overay; + Texture2D overlay = icon_overlay; Color color = cumcolor; if (badTex == null) { badTex = BaseContent.BadTex; } - if (overay == null) + if (overlay == null) { - overay = BaseContent.BadTex; + overlay = BaseContent.BadTex; } if (color == null) color = Color.white; rect.position += new Vector2(iconOffset.x * rect.size.x, iconOffset.y * rect.size.y); GUI.color = IconDrawColor; Widgets.DrawTextureFitted(rect, badTex, this.iconDrawScale * 0.85f, this.iconProportions, this.iconTexCoords, this.iconAngle, buttonMat); GUI.color = color; - Widgets.DrawTextureFitted(rect, overay, iconDrawScale * 0.85f, iconProportions, iconTexCoords, iconAngle, buttonMat); + Widgets.DrawTextureFitted(rect, overlay, iconDrawScale * 0.85f, iconProportions, iconTexCoords, iconAngle, buttonMat); GUI.color = Color.white; if (Configurations.DrawEggOverlay) comp.DrawEggOverlay(rect, false); Rect progressRect = new Rect(rect.x + 2f, rect.y, rect.width - 4f, progressbarHeight); diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/Utility.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/Utility.cs index 13aae6e..db91411 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/Utility.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/Utility.cs @@ -53,7 +53,7 @@ namespace RJW_Menstruation if (pawn.kindDef?.race == pawn.def) return pawn.kindDef; return VariousDefOf.AllKinds.Find(kind => kind.race == pawn.def && kind.defName.Contains("Colonist")) ?? VariousDefOf.AllKinds.Find(kind => kind.race == pawn.def) ?? - pawn.def.race?.AnyPawnKind ?? + pawn.RaceProps?.AnyPawnKind ?? pawn.kindDef; } @@ -433,7 +433,7 @@ namespace RJW_Menstruation } - public static float LerpMultiple(this float a, float b, float t, int num) + public static float LerpMultiple(this float a, float b, float t, float num) { float tmult = Mathf.Pow(1 - t, num); return tmult * a + (1 - tmult) * b; diff --git a/1.4/source/RJW_Menstruation/RJW_Menstruation/VariousDefOf.cs b/1.4/source/RJW_Menstruation/RJW_Menstruation/VariousDefOf.cs index 7f368cc..6c5e143 100644 --- a/1.4/source/RJW_Menstruation/RJW_Menstruation/VariousDefOf.cs +++ b/1.4/source/RJW_Menstruation/RJW_Menstruation/VariousDefOf.cs @@ -167,5 +167,10 @@ namespace RJW_Menstruation public static readonly HediffDef Hediff_Lactating_Permanent = DefDatabase.GetNamedSilentFail("Lactating_Permanent"); public static readonly HediffDef Hediff_Heavy_Lactating_Permanent = DefDatabase.GetNamedSilentFail("Heavy_Lactating_Permanent"); public static readonly JobDef Job_LactateSelf_MC = DefDatabase.GetNamedSilentFail("LactateSelf_MC"); + + // Defs from Sexperience Ideology + public static readonly PreceptDef Pregnancy_Elevated = DefDatabase.GetNamedSilentFail("Pregnancy_Elevated"); + public static readonly PreceptDef Pregnancy_Holy = DefDatabase.GetNamedSilentFail("Pregnancy_Holy"); + public static readonly PreceptDef Pregnancy_Required = DefDatabase.GetNamedSilentFail("Pregnancy_Required"); } } diff --git a/About/Manifest.xml b/About/Manifest.xml index fc6edef..3299391 100644 --- a/About/Manifest.xml +++ b/About/Manifest.xml @@ -1,7 +1,7 @@ RJW Menstruation - 1.0.8.9 + 1.0.9.0 diff --git a/changelogs.txt b/changelogs.txt index f68bbbe..97ae1c8 100644 --- a/changelogs.txt +++ b/changelogs.txt @@ -1,3 +1,11 @@ +Version 1.0.9.0 + - Fix errors when opening the womb dialog of some low fertility pawns. + - Updated Traditional Chinese translation by Hydrogen. + - New options to update wombs more or less often, defaulting to every hour. + - When using the sexperience-ideology mod, pawns with pro-pregnancy precepts will have thoughts more agreeable with potential pregnancies. + - More generous egg allocation for newly spawned periodic ovulators. + - Menstruation-related genes will now stay on females during initial pawn setup. + Version 1.0.8.9 - Fix bug that sent pawns into menopause very early. Please use the recalculate ovary power dev action to restore lost eggs.