diff --git a/1.3/Assemblies/RJW_Menstruation.dll b/1.3/Assemblies/RJW_Menstruation.dll index 9f159dc..189a970 100644 Binary files a/1.3/Assemblies/RJW_Menstruation.dll and b/1.3/Assemblies/RJW_Menstruation.dll differ diff --git a/1.3/Languages/English/Keyed/RJW_Menstruation.xml b/1.3/Languages/English/Keyed/RJW_Menstruation.xml index bdb4a6f..908b411 100644 --- a/1.3/Languages/English/Keyed/RJW_Menstruation.xml +++ b/1.3/Languages/English/Keyed/RJW_Menstruation.xml @@ -37,7 +37,7 @@ Gather cum into bucket Store cum in womb Unknown - + Enable womb icon @@ -94,14 +94,12 @@ Dominant hybrid extension Mother Father - Transition variance of nipples after pregnancy - Set how much nipples/areolas should darken/widen on every pregnancy. - Permanent transition variance of nipples - Set how much nipples/areolas should darken/widen permanently on every pregnancy. - Maximum transition - Nipples/areolas won't be darker/wider than this value. - Transition speed of nipples - Set speed of transition of nipples/areolas. 1 = instant transition + Breast growth during pregnancy + Change how much a pregnant pawn's breasts will grow when pregnant. Some pawns will grow more than others. + Nipple change during pregnancy + Change how much a pregnant pawn's nipples will change during pregnancy. + Permanent nipple change after pregnancy + Adjusts approximately how much of a pregnant pawn's nipples will remain changed after the pregnancy ends. Customize Hybrids Open custom hybrid editor. This will overrides hybrid definitions of XML files. Allow shrink icon diff --git a/1.3/MilkModule/Assemblies/MilkModule.dll b/1.3/MilkModule/Assemblies/MilkModule.dll index 778684a..f032d8c 100644 Binary files a/1.3/MilkModule/Assemblies/MilkModule.dll and b/1.3/MilkModule/Assemblies/MilkModule.dll differ diff --git a/1.3/SexperienceModule/Assemblies/SexperienceModule.dll b/1.3/SexperienceModule/Assemblies/SexperienceModule.dll index fa2d04c..308d693 100644 Binary files a/1.3/SexperienceModule/Assemblies/SexperienceModule.dll and b/1.3/SexperienceModule/Assemblies/SexperienceModule.dll differ diff --git a/1.3/source/RJW_Menstruation/MilkModule/JobDriver_MilkSelf.cs b/1.3/source/RJW_Menstruation/MilkModule/JobDriver_MilkSelf.cs index b35b0a6..0a73ead 100644 --- a/1.3/source/RJW_Menstruation/MilkModule/JobDriver_MilkSelf.cs +++ b/1.3/source/RJW_Menstruation/MilkModule/JobDriver_MilkSelf.cs @@ -32,8 +32,7 @@ namespace MilkModule { if (breastcomp != null) { - breastcomp.AdjustAreolaSize(Rand.Range(0.0f, 0.0001f * Configurations.NipplePermanentTransitionVariance)); - breastcomp.AdjustNippleSize(Rand.Range(0.0f, 0.0001f * Configurations.NipplePermanentTransitionVariance)); + breastcomp.AdjustNippleProgress(Rand.Range(0.0f, 0.01f)); } } diff --git a/1.3/source/RJW_Menstruation/MilkModule/Milk_Patch.cs b/1.3/source/RJW_Menstruation/MilkModule/Milk_Patch.cs index 2de9e87..ee5ec1d 100644 --- a/1.3/source/RJW_Menstruation/MilkModule/Milk_Patch.cs +++ b/1.3/source/RJW_Menstruation/MilkModule/Milk_Patch.cs @@ -24,8 +24,7 @@ namespace MilkModule if (__instance.parent is Pawn pawn) comp = pawn.GetBreastComp(); if (comp != null) { - comp.AdjustAreolaSize(Rand.Range(0.0f, 0.01f * Configurations.NipplePermanentTransitionVariance)); - comp.AdjustNippleSize(Rand.Range(0.0f, 0.01f * Configurations.NipplePermanentTransitionVariance)); + comp.AdjustNippleProgress(Rand.Range(0.0f, 0.01f)); } } diff --git a/1.3/source/RJW_Menstruation/RJW_Menstruation/Configurations.cs b/1.3/source/RJW_Menstruation/RJW_Menstruation/Configurations.cs index 2ef752e..319f64a 100644 --- a/1.3/source/RJW_Menstruation/RJW_Menstruation/Configurations.cs +++ b/1.3/source/RJW_Menstruation/RJW_Menstruation/Configurations.cs @@ -21,10 +21,12 @@ namespace RJW_Menstruation public const int EnzygoticTwinsChanceAdjustDefault = 2; public const int MaxEnzygoticTwinsDefault = 9; public const int BleedingAmountDefault = 50; - public const float NippleTransitionVarianceDefault = 0.2f; - public const float NipplePermanentTransitionVarianceDefault = 0.02f; - public const float NippleMaximumTransitionDefault = 0.4f; - public const float NippleTransitionSpeedDefault = 0.035f; + public const float MaxBreastIncrementFactorDefault = 1.0f; + public const float MaxBreastIncrementFactorMax = 2.5f; + public const float MaxNippleIncrementFactorDefault = 1.0f; + public const float MaxNippleIncrementFactorMax = 2.5f; + public const float PermanentNippleChangeDefault = 0.1f; + public const float PermanentNippleChangeMax = 0.25f; public const float EggLifespanMultiplierDefault = 1.0f; public const float VaginaMorphPowerDefault = 0.2f; @@ -67,19 +69,9 @@ namespace RJW_Menstruation public static float EggLifespanMultiplier = EggLifespanMultiplierDefault; public static bool EnableBirthVaginaMorph = false; public static float VaginaMorphPower = VaginaMorphPowerDefault; - - public static float NippleTransitionVariance = NippleTransitionVarianceDefault; - public static float NipplePermanentTransitionVariance = NipplePermanentTransitionVarianceDefault; - public static float NippleMaximumTransition = NippleMaximumTransitionDefault; - public static float NippleTransitionSpeed = NippleTransitionSpeedDefault; - public static float NippleTransitionRatio - { - get - { - return NippleTransitionVariance * NippleTransitionSpeed; - } - } - + public static float MaxBreastIncrementFactor = MaxBreastIncrementFactorDefault; + public static float MaxNippleIncrementFactor = MaxNippleIncrementFactorDefault; + public static float PermanentNippleChange = PermanentNippleChangeDefault; public static void SettoDefault() { ImplantationChanceAdjust = ImplantationChanceAdjustDefault; @@ -101,10 +93,9 @@ namespace RJW_Menstruation MaxEnzygoticTwins = MaxEnzygoticTwinsDefault; BleedingAmount = BleedingAmountDefault; MotherFirst = false; - NippleTransitionVariance = NippleTransitionVarianceDefault; - NipplePermanentTransitionVariance = NipplePermanentTransitionVarianceDefault; - NippleMaximumTransition = NippleMaximumTransitionDefault; - NippleTransitionSpeed = NippleTransitionSpeedDefault; + MaxBreastIncrementFactor = MaxBreastIncrementFactorDefault; + MaxNippleIncrementFactor= MaxNippleIncrementFactorDefault; + PermanentNippleChange = PermanentNippleChangeDefault; EggLifespanMultiplier = EggLifespanMultiplierDefault; VaginaMorphPower = VaginaMorphPowerDefault; } @@ -214,10 +205,9 @@ namespace RJW_Menstruation 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 NippleTransitionVariance, "NippleTransitionVariance", NippleTransitionVariance, true); - Scribe_Values.Look(ref NipplePermanentTransitionVariance, "NipplePermanentTransitionVariance", NipplePermanentTransitionVariance, true); - Scribe_Values.Look(ref NippleMaximumTransition, "NippleMaximumTransition", NippleMaximumTransition, true); - Scribe_Values.Look(ref NippleTransitionSpeed, "NippleTransitionSpeed", NippleTransitionSpeed, 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); @@ -259,8 +249,8 @@ namespace RJW_Menstruation public RJW_Menstruation(ModContentPack content) : base(content) { GetSettings(); - Configurations.HARActivated = ModLister.HasActiveModWithName("Humanoid Alien Races 2.0"); - Configurations.LLActivated = ModLister.HasActiveModWithName("RimJobWorld - Licentia Labs"); + Configurations.HARActivated = ModLister.GetActiveModWithIdentifier("erdelf.HumanoidAlienRaces") != null; + Configurations.LLActivated = ModLister.GetActiveModWithIdentifier("LustLicentia.RJWLabs") != null; } @@ -294,7 +284,7 @@ namespace RJW_Menstruation Widgets.CheckboxLabeled(middleAndRightCells.RightHalf(), Translations.Option_EnableGatherCumGizmo_Label, ref Configurations.EnableGatherCumGizmo, false, null, null, true); if (Configurations.EnableWombIcon || Configurations.EnableButtonInHT) { - Listing_Standard wombsection = listmain.BeginSection(400); + Listing_Standard wombsection = listmain.BeginSection(350); wombsection.CheckboxLabeled(Translations.Option9_Label, ref Configurations.DrawWombStatus, Translations.Option9_Desc); if (Configurations.DrawWombStatus) { @@ -352,25 +342,20 @@ namespace RJW_Menstruation Configurations.ShowFlag ^= Configurations.PawnFlags.Hostile; } - Adjust = (int)(Configurations.NippleTransitionVariance * 1000); - wombsection.Label(Translations.Option24_Label + " " + Configurations.NippleTransitionVariance * 100 + " / 100", -1, Translations.Option24_Desc); + Adjust = (int)(Configurations.MaxBreastIncrementFactor * 1000 / Configurations.MaxBreastIncrementFactorMax); + wombsection.Label(Translations.Option_MaxBreastIncrementFactor_Label + " " + Configurations.MaxBreastIncrementFactor * 100 + "%", -1, Translations.Option_MaxBreastIncrementFactor_Desc); Adjust = (int)wombsection.Slider(Adjust, 0, 1000); - Configurations.NippleTransitionVariance = (float)Adjust / 1000; + Configurations.MaxBreastIncrementFactor = (float)Adjust / (1000 / Configurations.MaxBreastIncrementFactorMax); - Adjust = (int)(Configurations.NipplePermanentTransitionVariance * 1000); - wombsection.Label(Translations.Option25_Label + " " + Configurations.NipplePermanentTransitionVariance * 100 + " / 100", -1, Translations.Option25_Desc); + Adjust = (int)(Configurations.MaxNippleIncrementFactor * 1000 / Configurations.MaxNippleIncrementFactorMax); + wombsection.Label(Translations.Option_MaxNippleIncrementFactor_Label + " " + Configurations.MaxNippleIncrementFactor * 100 + "%", -1, Translations.Option_MaxNippleIncrementFactor_Desc); Adjust = (int)wombsection.Slider(Adjust, 0, 1000); - Configurations.NipplePermanentTransitionVariance = (float)Adjust / 1000; + Configurations.MaxNippleIncrementFactor = (float)Adjust / (1000 / Configurations.MaxNippleIncrementFactorMax); - Adjust = (int)(Configurations.NippleMaximumTransition * 1000); - wombsection.Label(Translations.Option26_Label + " " + Configurations.NippleMaximumTransition * 100 + " / 100", -1, Translations.Option26_Desc); + Adjust = (int)(Configurations.PermanentNippleChange * 1000 / Configurations.PermanentNippleChangeMax); + wombsection.Label(Translations.Option_PermanentNippleChange_Label + " " + Configurations.PermanentNippleChange, -1, Translations.Option_PermanentNippleChange_Desc); Adjust = (int)wombsection.Slider(Adjust, 0, 1000); - Configurations.NippleMaximumTransition = (float)Adjust / 1000; - - Adjust = (int)(Configurations.NippleTransitionSpeed * 1000); - wombsection.Label(Translations.Option27_Label + " " + Configurations.NippleTransitionSpeed, -1, Translations.Option27_Desc); - Adjust = (int)wombsection.Slider(Adjust, 0, 1000); - Configurations.NippleTransitionSpeed = (float)Adjust / 1000; + Configurations.PermanentNippleChange = (float)Adjust / (1000 / Configurations.PermanentNippleChangeMax); listmain.EndSection(wombsection); } diff --git a/1.3/source/RJW_Menstruation/RJW_Menstruation/DebugActions.cs b/1.3/source/RJW_Menstruation/RJW_Menstruation/DebugActions.cs index 44f787d..3a8fdb5 100644 --- a/1.3/source/RJW_Menstruation/RJW_Menstruation/DebugActions.cs +++ b/1.3/source/RJW_Menstruation/RJW_Menstruation/DebugActions.cs @@ -11,7 +11,7 @@ namespace RJW_Menstruation { foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) comp.curStage = HediffComp_Menstruation.Stage.Follicular; - Messages.Message($"{p} is now follicular", MessageTypeDefOf.NeutralEvent, false); + Messages.Message($"{p} is now follicular", p, MessageTypeDefOf.NeutralEvent, false); } [DebugAction("RJW Menstruation", "Set pawn's state to ovulatory", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] @@ -19,7 +19,7 @@ namespace RJW_Menstruation { foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) comp.curStage = HediffComp_Menstruation.Stage.Ovulatory; - Messages.Message($"{p} is now ovulatory", MessageTypeDefOf.NeutralEvent, false); + Messages.Message($"{p} is now ovulatory", p, MessageTypeDefOf.NeutralEvent, false); } [DebugAction("RJW Menstruation", "Set pawn's state to luteal", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] @@ -27,7 +27,7 @@ namespace RJW_Menstruation { foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) comp.curStage = HediffComp_Menstruation.Stage.Luteal; - Messages.Message($"{p} is now luteal", MessageTypeDefOf.NeutralEvent, false); + Messages.Message($"{p} is now luteal", p, MessageTypeDefOf.NeutralEvent, false); } [DebugAction("RJW Menstruation", "Set pawn's state to bleeding", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] @@ -35,7 +35,7 @@ namespace RJW_Menstruation { foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) comp.curStage = HediffComp_Menstruation.Stage.Bleeding; - Messages.Message($"{p} is now bleeding", MessageTypeDefOf.NeutralEvent, false); + Messages.Message($"{p} is now bleeding", p, MessageTypeDefOf.NeutralEvent, false); } /* [DebugAction("RJW Menstruation", "Set pawn's state to recovering", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] @@ -55,14 +55,14 @@ namespace RJW_Menstruation { foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) comp.RemoveAllCums(); - Messages.Message($"All cum removed from {p}'s womb", MessageTypeDefOf.NeutralEvent, false); + Messages.Message($"All cum 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) { foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) comp.eggstack++; - Messages.Message($"1 egg added to {p}'s next ovulation ({p.GetFirstMenstruationComp().eggstack})", MessageTypeDefOf.NeutralEvent, false); + Messages.Message($"1 egg added to {p}'s next ovulation ({p.GetFirstMenstruationComp().eggstack})", p, MessageTypeDefOf.NeutralEvent, false); } [DebugAction("RJW Menstruation", "Recalculate pawn's ovary power", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] @@ -70,7 +70,7 @@ namespace RJW_Menstruation { foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) comp.ovarypower = comp.GetOvaryPowerByAge(); - Messages.Message($"{p}'s ovarypower recalculated ({p.GetFirstMenstruationComp().ovarypower})", MessageTypeDefOf.NeutralEvent, false); + Messages.Message($"{p}'s ovarypower recalculated ({p.GetFirstMenstruationComp().ovarypower})", p, MessageTypeDefOf.NeutralEvent, false); } } } diff --git a/1.3/source/RJW_Menstruation/RJW_Menstruation/HARCompatibility.cs b/1.3/source/RJW_Menstruation/RJW_Menstruation/HARCompatibility.cs index c274d8d..863eaa4 100644 --- a/1.3/source/RJW_Menstruation/RJW_Menstruation/HARCompatibility.cs +++ b/1.3/source/RJW_Menstruation/RJW_Menstruation/HARCompatibility.cs @@ -1,4 +1,6 @@ -using System.Linq; +using AlienRace; +using System.Collections.Generic; +using UnityEngine; using Verse; namespace RJW_Menstruation @@ -8,24 +10,38 @@ namespace RJW_Menstruation public static bool IsHAR(this Pawn pawn) { - return pawn.def.GetType().ToString().StartsWith("AlienRace"); + if (!Configurations.HARActivated) return false; + return pawn?.def is ThingDef_AlienRace; } - public static ThingComp GetHARComp(this Pawn pawn) + public static AlienPartGenerator.AlienComp GetHARComp(this Pawn pawn) { - return pawn?.GetComps()?.First(x => x.GetType().Namespace.EqualsIgnoreCase("AlienRace") && x.GetType().Name.EndsWith("AlienComp")); + return pawn?.TryGetComp(); } - public static string GetHARCrown(this Pawn pawn) + public static void CopyHARProperties(Pawn baby, Pawn original) { - return (string)pawn.GetHARComp().GetMemberValue("crownType"); + AlienPartGenerator.AlienComp babyHARComp = baby.GetHARComp(); + AlienPartGenerator.AlienComp originalHARComp = original.GetHARComp(); + if (babyHARComp == null || originalHARComp == null) return; + babyHARComp.crownType = originalHARComp.crownType; + + foreach(KeyValuePair> channel in originalHARComp.ColorChannels) + { + babyHARComp.OverwriteColorChannel(channel.Key, channel.Value.first, channel.Value.second); + } + babyHARComp.headMaskVariant = originalHARComp.headMaskVariant; + babyHARComp.bodyMaskVariant = originalHARComp.bodyMaskVariant; } - public static void SetHARCrown(this Pawn pawn, string crown) + // HAR doesn't populate variants until the graphics are called for, so this has to happen late + public static void CopyHARPropertiesPostBirth(Pawn baby, Pawn original) { - pawn.GetHARComp().SetMemberValue("crownType", crown); + AlienPartGenerator.AlienComp babyHARComp = baby.GetHARComp(); + AlienPartGenerator.AlienComp originalHARComp = original.GetHARComp(); + if (babyHARComp == null || originalHARComp == null) return; + if (originalHARComp.addonVariants != null) // Testing has shown that the addons are valid by this point, but it's better to be safe + babyHARComp.addonVariants = new List(originalHARComp.addonVariants); } - - } } diff --git a/1.3/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Breast.cs b/1.3/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Breast.cs index 4a38f7a..a275479 100644 --- a/1.3/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Breast.cs +++ b/1.3/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Breast.cs @@ -1,8 +1,8 @@ -using HugsLib; -using RimWorld; +using RimWorld; using rjw; using System; using System.Collections.Generic; +using System.Linq; using UnityEngine; using Verse; @@ -10,6 +10,7 @@ namespace RJW_Menstruation { public class CompProperties_Breast : HediffCompProperties { + public static readonly ColorInt DefaultBlacknippleColor = new ColorInt(55, 20, 0); public string BreastTex = "Breasts/Breast"; public ColorInt BlacknippleColor = new ColorInt(55, 20, 0); @@ -31,117 +32,98 @@ namespace RJW_Menstruation public class HediffComp_Breast : HediffComp { - public const float DEFAULTALPHA = -1; - public const float DEFAULTAREOLA = -1; - public const float DEFAULTNIPPLE = -1; - public const float VARIANT = 0.2f; - public const int TICKINTERVAL = 3750; - public const float MAX_BREAST_INCREMENT = 0.10f; - public const float BREAST_GROWTH_START = 1f / 6f; - public const float BREAST_GROWTH_END = 1f / 3f; + public const int tickInterval = GenDate.TicksPerHour * 3 / 2; + public const float breastGrowthStart = 1f / 6f; + public const float breastGrowthEnd = 1f / 3f; + public static readonly SimpleCurve nippleTransitions = new SimpleCurve() + { + new CurvePoint(0f,0f), + new CurvePoint(0.1f,0f), + new CurvePoint(0.333f,0.167f), + new CurvePoint(0.667f,0.833f), + new CurvePoint(1.0f,1.0f) + }; + public const float nippleChange = 0.2f; public CompProperties_Breast Props; - protected float alphaPermanent = -1; - protected float alphaCurrent = -1; - protected float alpha = -1; - protected float areolaSizePermanent = -1f; - protected float areolaSizeCurrent = -1f; - protected float areolaSize = -1f; - protected float nippleSizePermanent = -1f; - protected float nippleSizeCurrent = -1f; - protected float nippleSize = -1f; protected long ageOfLastBirth = 0; + protected float maxBreastIncrement = -1f; protected float breastSizeIncreased = 0f; protected string debugGrowthStatus = "(Growth/shrink not yet calculated; run for 1.5h to update)"; - protected float originalpha = -1f; - protected float originareola = -1f; - protected float originnipple = -1f; - protected Color cachedcolor; - protected bool loaded = false; - protected bool pregnant = false; - public Action action; + protected float nippleProgress = 0f; + protected float baseAlpha = -1f; // Will grow in response to pregnancy + protected float baseAreola = -1f; + protected float baseNipple = -1f; + protected float cachedAlpha = -1f; // Calculated dynamically instead of saved + protected float cachedAreola = -1f; // Actual size = these * breast size + protected float cachedNipple = -1f; + protected float babyHalfAge = -1f; + protected Color cachedColor; + protected bool loaded = false; + protected float BabyHalfAge { get { - float res = 0; - List ages = parent.pawn.RaceProps.lifeStageAges; + if (babyHalfAge > 0f) return babyHalfAge; + List ages = parent.pawn.def.race.lifeStageAges; if (ages?.Count > 1) - res = ages[1].minAge / 2; + babyHalfAge = ages[1].minAge / 2; - if (res <= 0) res = 1.2f / 2; // Default to human + if (babyHalfAge <= 0) babyHalfAge = 1.2f / 2; // Default to human if (RJWPregnancySettings.phantasy_pregnancy) - res /= GenDate.DaysPerYear; + babyHalfAge /= GenDate.DaysPerYear; - return res; + return babyHalfAge; } } protected void ShrinkBreasts() { // The natural rate will take them from full to empty during the second half of their child's babyhood - float shrinkRate = TICKINTERVAL * MAX_BREAST_INCREMENT / (BabyHalfAge * GenDate.TicksPerYear); + float shrinkRate = tickInterval * MaxBreastIncrement / (BabyHalfAge * GenDate.TicksPerYear); float shrinkAmount = Mathf.Min(shrinkRate, breastSizeIncreased); breastSizeIncreased -= shrinkAmount; parent.Severity -= shrinkAmount; } - public float MaxAlpha + protected float MaxBreastIncrement { get { - return originalpha + Configurations.NippleMaximumTransition; + return maxBreastIncrement * Configurations.MaxBreastIncrementFactor; } } - public float MaxAreola - { - get - { - return originareola + Configurations.NippleMaximumTransition; - } - } - public float MaxNipple - { - get - { - return originnipple + Configurations.NippleMaximumTransition; - } - } - - public float OriginAlpha => originalpha; - public float OriginNipple => originnipple; - public float OriginAreola => originareola; - public Color OriginColor => Colors.CMYKLerp(parent?.pawn?.story?.SkinColor ?? Color.white, Props.BlackNippleColor, originalpha); public Color NippleColor { get { - return cachedcolor; + return cachedColor; } } public float Alpha { get { - return alphaCurrent; + return cachedAlpha; } } public float NippleSize { get { - return nippleSizeCurrent; + return cachedNipple * parent.Severity; } } public float AreolaSize { get { - return areolaSizeCurrent; + return cachedAreola * parent.Severity; } } @@ -156,25 +138,50 @@ namespace RJW_Menstruation public override void CompExposeData() { base.CompExposeData(); - Scribe_Values.Look(ref alphaPermanent, "alphaPermanent", DEFAULTALPHA, true); - Scribe_Values.Look(ref alphaCurrent, "alphaCurrent", DEFAULTALPHA, true); - Scribe_Values.Look(ref alpha, "alpha", DEFAULTALPHA, true); - Scribe_Values.Look(ref areolaSizePermanent, "areolaSizePermanent", DEFAULTAREOLA, true); - Scribe_Values.Look(ref areolaSizeCurrent, "areolaSizeCurrent", DEFAULTAREOLA, true); - Scribe_Values.Look(ref areolaSize, "areolaSize", DEFAULTAREOLA, true); - Scribe_Values.Look(ref nippleSizePermanent, "nippleSizePermanent", DEFAULTNIPPLE, true); - Scribe_Values.Look(ref nippleSizeCurrent, "nippleSizeCurrent", DEFAULTNIPPLE, true); - Scribe_Values.Look(ref nippleSize, "nippleSize", DEFAULTNIPPLE, true); - Scribe_Values.Look(ref ageOfLastBirth, "ageOfLastBirth", ageOfLastBirth, true); - Scribe_Values.Look(ref breastSizeIncreased, "breastSizeIncreased", breastSizeIncreased, true); - Scribe_Values.Look(ref originalpha, "originalpha", originalpha, true); - Scribe_Values.Look(ref originareola, "originareola", originareola, true); - Scribe_Values.Look(ref originnipple, "originnipple", originnipple, true); - Scribe_Values.Look(ref pregnant, "pregnant", pregnant, true); + + if (Scribe.mode == LoadSaveMode.LoadingVars) + { // For compatibility + Scribe_Values.Look(ref baseAlpha, "alphaPermanent", baseAlpha / 2, false); + Scribe_Values.Look(ref baseAreola, "areolaSizePermanent", baseAreola / 2, false); + Scribe_Values.Look(ref baseNipple, "nippleSizePermanent", baseNipple / 2, false); + baseAlpha *= 2; + baseAreola *= 2; + baseNipple *= 2; + } + Scribe_Values.Look(ref ageOfLastBirth, "ageOfLastBirth", ageOfLastBirth, true); + 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 baseAlpha, "baseAlpha", baseAlpha, true); + Scribe_Values.Look(ref baseAreola, "baseAreola", baseAreola, true); + Scribe_Values.Look(ref baseNipple, "baseNipple", baseNipple, true); } - public override void CompPostTick(ref float severityAdjustment) { } + public override void CompPostTick(ref float severityAdjustment) + { + base.CompPostTick(ref severityAdjustment); + // If an exception makes it out, RW will remove the hediff, so catch it here + try + { + if ( + !parent.pawn.IsHashIntervalTick(tickInterval) || + !parent.pawn.Spawned || // TODO: Add option to simulate off-map pawns + parent.pawn.health.Dead + ) + { + return; + } + CalculateBreastSize(); + CalculateNipples(); + UpdateNipples(); + } + catch (Exception ex) + { + Log.Error($"Error processing breasts of {parent.pawn}: {ex}"); + } + + } public override void CompPostPostAdd(DamageInfo? dinfo) { @@ -189,8 +196,6 @@ namespace RJW_Menstruation Log.Warning($"Attempted to remove breast comp from wrong pawn ({parent.pawn})."); return; } - HugsLibController.Instance.TickDelayScheduler.TryUnscheduleCallback(action); - if (Configurations.Debug) Log.Message(parent.pawn.Label + " breast tick scheduler removed"); base.CompPostPostRemoved(); } @@ -202,15 +207,12 @@ namespace RJW_Menstruation foreach (Pawn child in parent.pawn.relations.Children) { bool isFetus = false; - foreach (Hediff_BasePregnancy preg in parent.pawn.health.hediffSet.GetHediffs()) + if (parent.pawn.health.hediffSet.GetHediffs().Any(preg => preg.babies.Contains(child))) { - if (preg.babies.Contains(child)) - { - isFetus = true; - break; - } + isFetus = true; + break; } - + if ( parent.pawn.ageTracker.BirthAbsTicks - child.ageTracker.BirthAbsTicks > ageOfLastBirth && !isFetus && @@ -225,70 +227,54 @@ namespace RJW_Menstruation public void Initialize() { Props = (CompProperties_Breast)props; - action = Transition; + if (maxBreastIncrement <= 0f) + { + maxBreastIncrement = Utility.RandGaussianLike(0.088f, 0.202f); + } if (ageOfLastBirth == 0) { ageOfLastBirth = CalculateLastBirth(); } - - if (alphaPermanent < 0f) + if (baseAlpha <= 0f) { - alphaPermanent = (Utility.RandGaussianLike(0.0f, 0.3f) + Rand.Range(0.0f, 0.5f)) / 2; - originalpha = alphaPermanent; - alpha = alphaPermanent; - alphaCurrent = alphaPermanent; + baseAlpha = Utility.RandGaussianLike(0.0f, 0.3f) + Rand.Range(0.0f, 0.5f); } - if (areolaSizePermanent < 0f) + if (baseAreola <= 0f) { - areolaSizePermanent = Utility.RandGaussianLike(0f, parent.Severity); - originareola = areolaSizePermanent; - areolaSize = areolaSizePermanent; - areolaSizeCurrent = areolaSizePermanent; + baseAreola = Utility.RandGaussianLike(0.0f, 1.0f); } - if (nippleSizePermanent < 0f) + if (baseNipple <= 0f) { - nippleSizePermanent = Utility.RandGaussianLike(0f, parent.Severity); - originnipple = nippleSizePermanent; - nippleSize = nippleSizePermanent; - nippleSizeCurrent = nippleSizePermanent; + baseNipple = Utility.RandGaussianLike(0.0f, 1.0f); } - UpdateColor(); + UpdateNipples(); loaded = true; - HugsLibController.Instance.TickDelayScheduler.ScheduleCallback(action, TICKINTERVAL, parent.pawn); } - - - public void Transition() + protected void CalculateBreastSize() { - alphaCurrent = Mathf.Lerp(alphaCurrent, alpha, Configurations.NippleTransitionRatio); - areolaSizeCurrent = Mathf.Lerp(areolaSizeCurrent, areolaSize, Configurations.NippleTransitionRatio); - nippleSizeCurrent = Mathf.Lerp(nippleSizeCurrent, nippleSize, Configurations.NippleTransitionRatio); - UpdateColor(); - HugsLibController.Instance.TickDelayScheduler.ScheduleCallback(action, TICKINTERVAL, parent.pawn); - // Scenario A: the youngest child is less than halfway into babyhood: Full size if (ageOfLastBirth + BabyHalfAge * GenDate.TicksPerYear > parent.pawn.ageTracker.AgeBiologicalTicks) { debugGrowthStatus = "Full size due to young child"; - if (breastSizeIncreased < MAX_BREAST_INCREMENT) + if (breastSizeIncreased < MaxBreastIncrement) { - parent.Severity += (MAX_BREAST_INCREMENT - breastSizeIncreased); - breastSizeIncreased = MAX_BREAST_INCREMENT; + parent.Severity += (MaxBreastIncrement - breastSizeIncreased); + breastSizeIncreased = MaxBreastIncrement; } } // Scenario B: Pregnant, grow in the second half of first trimester else if (parent.pawn.IsPregnant()) { - float pregnancySize = Mathf.InverseLerp(BREAST_GROWTH_START, BREAST_GROWTH_END, parent.pawn.GetFarthestPregnancyProgress()) * MAX_BREAST_INCREMENT; + float pregnancySize = Mathf.InverseLerp(breastGrowthStart, breastGrowthEnd, parent.pawn.GetFarthestPregnancyProgress()) * MaxBreastIncrement; if (breastSizeIncreased > pregnancySize) { debugGrowthStatus = "Shrinking due to being oversize for pregnancy"; // Breasts still large from the last kid ShrinkBreasts(); } - else if (breastSizeIncreased < MAX_BREAST_INCREMENT) + else if (breastSizeIncreased < MaxBreastIncrement) { // Time to grow float growAmount = pregnancySize - breastSizeIncreased; @@ -310,106 +296,88 @@ namespace RJW_Menstruation else debugGrowthStatus = "Base size"; } - public void ChangeColorFermanant(float alpha) + protected void CalculateNipples() { - alphaPermanent = alpha; + float newNippleProgress; + if (ageOfLastBirth + BabyHalfAge * GenDate.TicksPerYear > parent.pawn.ageTracker.AgeBiologicalTicks) + newNippleProgress = 1f; + else if (parent.pawn.IsPregnant()) + newNippleProgress = nippleTransitions.Evaluate(parent.pawn.GetFarthestPregnancyProgress()); + else + newNippleProgress = 0f; + + if (newNippleProgress == nippleProgress) return; // Nothing to change + else if (newNippleProgress > nippleProgress) + { + float progressDifference = newNippleProgress - nippleProgress; + // All nipple growth has a slight effect on the base + // Not mathematically precise in hitting the goal at the end of the term, but close enough + baseAlpha *= 1.0f + progressDifference * Configurations.PermanentNippleChange; + if (baseAlpha > 1.0f) baseAlpha = 1.0f; + baseAreola *= 1.0f + progressDifference * Configurations.PermanentNippleChange; + if (baseAreola > 1.0f) baseAreola = 1.0f; + baseNipple *= 1.0f + progressDifference * Configurations.PermanentNippleChange; + if (baseNipple > 1.0f) baseNipple = 1.0f; + nippleProgress = newNippleProgress; + } + else + { + nippleProgress -= tickInterval / (BabyHalfAge * GenDate.TicksPerYear); + if (nippleProgress < newNippleProgress) nippleProgress = newNippleProgress; + } } - public void ChangeColor(float alpha) + public void AdjustNippleProgress(float amount) { - this.alpha = alpha; + nippleProgress = Mathf.Clamp01(nippleProgress + amount); + UpdateNipples(); } - public void PregnancyTransition() + public void AdjustNippleSizeImmediately(float amount) { - alphaPermanent = Math.Min(MaxAlpha, alphaPermanent + Configurations.NipplePermanentTransitionVariance.VariationRange(VARIANT)); - areolaSizePermanent = Math.Min(MaxAreola, areolaSizePermanent + Configurations.NipplePermanentTransitionVariance.VariationRange(VARIANT)); - nippleSizePermanent = Math.Min(MaxNipple, nippleSizePermanent + Configurations.NipplePermanentTransitionVariance.VariationRange(VARIANT)); - alpha = Math.Min(MaxAlpha, alpha + Configurations.NippleTransitionVariance.VariationRange(VARIANT)); - areolaSize = Math.Min(MaxAreola, areolaSize + Configurations.NippleTransitionVariance.VariationRange(VARIANT)); - nippleSize = Math.Min(MaxNipple, nippleSize + Configurations.NippleTransitionVariance.VariationRange(VARIANT)); - pregnant = true; + baseNipple = Mathf.Clamp01(baseNipple + amount); + UpdateNipples(); } - public void BirthTransition() + public void AdjustAreolaSizeImmediately(float amount) { - alpha = alphaPermanent; - areolaSize = areolaSizePermanent; - nippleSize = nippleSizePermanent; - pregnant = false; - ageOfLastBirth = parent.pawn.ageTracker.AgeBiologicalTicks; + baseAreola = Mathf.Clamp01(baseAreola + amount); + UpdateNipples(); } - - public void AdjustBreastSize(float amount) + public void UpdateNipples() { - parent.Severity += amount; - breastSizeIncreased += amount; + cachedAlpha = baseAlpha + nippleProgress * nippleChange; + cachedAreola = baseAreola + nippleProgress * nippleChange; + cachedNipple = baseNipple + nippleProgress * nippleChange; + + // For some reason, Props can go null when RJW relocates the chest (e.g. some animals), so catch that + cachedColor = Colors.CMYKLerp(parent.pawn.story?.SkinColor ?? Color.white, (Props?.BlackNippleColor ?? CompProperties_Breast.DefaultBlacknippleColor.ToColor), Alpha); } - public void AdjustNippleSize(float amount) + public void CopyBreastProperties(HediffComp_Breast original) { - nippleSizePermanent = Math.Min(MaxNipple, nippleSizePermanent + amount); - nippleSize = Math.Min(MaxNipple, nippleSize + amount); - } - - public void AdjustAreolaSize(float amount) - { - areolaSizePermanent = Math.Min(MaxAreola, areolaSizePermanent + amount); - areolaSize = Math.Min(MaxAreola, areolaSize + amount); - } - - public void RestoreBreastSize(float ratio) - { - float variance = breastSizeIncreased * Math.Min(ratio, 1.0f); - breastSizeIncreased -= variance; - parent.Severity -= variance; - } - - public void AdjustNippleSizeImmidiately(float amount) - { - originnipple = Math.Max(0, originnipple + amount); - nippleSizePermanent = Math.Min(MaxNipple, nippleSizePermanent + amount); - nippleSize = Math.Min(MaxNipple, nippleSize + amount); - nippleSizeCurrent = nippleSize; - } - - public void AdjustAreolaSizeImmidiately(float amount) - { - originareola = Math.Max(0, originareola + amount); - areolaSizePermanent = Math.Min(MaxAreola, areolaSizePermanent + amount); - areolaSize = Math.Min(MaxAreola, areolaSize + amount); - areolaSizeCurrent = areolaSize; - } - - - - public void UpdateColor() - { - cachedcolor = Colors.CMYKLerp(parent?.pawn?.story?.SkinColor ?? Color.white, Props.BlackNippleColor, Alpha); + maxBreastIncrement = original.maxBreastIncrement; + baseAlpha = original.baseAlpha; + baseAreola = original.baseAreola; + baseNipple = original.baseNipple; + UpdateNipples(); } public string DebugInfo() { - return "Increase: " + breastSizeIncreased + + return "Size: " + parent.Severity + + "\nIncrease: " + breastSizeIncreased + "\n" + debugGrowthStatus + - "\nAlpha: " + alpha + - "\nNippleSize: " + nippleSize + - "\nAreolaSize: " + areolaSize + - "\nAlphaCurrent: " + alphaCurrent + - "\nNippleSizeCurrent: " + nippleSizeCurrent + - "\nAreolaSizeCurrent: " + areolaSizeCurrent + - "\nAlphaOrigin: " + originalpha + - "\nNippleSizeOrigin: " + originnipple + - "\nAreolaSizeOrigin: " + originareola + - "\nAlphaMax: " + MaxAlpha + - "\nNippleSizeMax: " + MaxNipple + - "\nAreolaSizeMax: " + MaxAreola + - "\nPermanentAlpha:" + alphaPermanent + - "\nPermanentNipple:" + nippleSizePermanent + - "\nPermanentAreola:" + areolaSizePermanent; + "\nNipple progress: " + nippleProgress + + "\nBase alpha: " + baseAlpha + + "\nAlpha: " + cachedAlpha + + "\nBase areola: " + baseAreola + + "\nAreola: " + cachedAreola + + "\nDisplayed areola: " + AreolaSize + + "\nBase nipple: " + baseNipple + + "\nNipple: " + cachedNipple + + "\nDisplayed nipple: " + NippleSize; } - } - } diff --git a/1.3/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Menstruation.cs b/1.3/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Menstruation.cs index a4e75af..fc07cb6 100644 --- a/1.3/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Menstruation.cs +++ b/1.3/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Menstruation.cs @@ -1,5 +1,4 @@ -using HugsLib; -using RimWorld; +using RimWorld; using rjw; using System; using System.Collections.Generic; @@ -70,7 +69,6 @@ namespace RJW_Menstruation public CompProperties_Menstruation Props; public Stage curStage = Stage.Follicular; public int curStageHrs = 0; - public Action actionref; public bool loaded = false; public int ovarypower = -100000; public int eggstack = 0; @@ -139,7 +137,22 @@ namespace RJW_Menstruation { get { - if (opcache < 0) opcache = (int)(72f * parent.pawn.def.race.lifeExpectancy / ThingDefOf.Human.race.lifeExpectancy); + if (opcache >= 0) return opcache; + // Climacteric will set in 6 (human) years before egg exhaustion + float avglittersize; + try + { + avglittersize = Mathf.Max(Rand.ByCurveAverage(parent.pawn.def.race.litterSizeCurve), 1.0f); + } + catch + { + // Any exceptions in that will have been reported elsewhere in the code by now + avglittersize = 1.0f; + }; + opcache = (int)(RaceCyclesPerYear() * + avglittersize * + 6f * + (parent.pawn.def.race.lifeExpectancy / ThingDefOf.Human.race.lifeExpectancy)); return opcache; } } @@ -487,7 +500,17 @@ namespace RJW_Menstruation { get { - return Mathf.Clamp01(curStageHrs / CurStageIntervalHours); + if (pregnancy == null) return Mathf.Clamp01(curStageHrs / CurStageIntervalHours); + if (pregnancy.is_discovered || Configurations.infoDetail == Configurations.DetailLevel.All) return pregnancy.Severity; + + // Luteal will appear to progress, hitting the end of the phase when the pregnancy is discovered + float discoveryTime = 0.5f; + if (parent.pawn.story?.bodyType == BodyTypeDefOf.Thin) discoveryTime = 0.25f; + else if (parent.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)); + + return GenMath.LerpDouble(0, discoveryTime, lutealProgressWhenImplanted, 1.0f, pregnancy.Severity); } } @@ -530,11 +553,69 @@ namespace RJW_Menstruation public override void CompPostTick(ref float severityAdjustment) { - //initializer moved to SpawnSetup - //if (!loaded) - //{ - // Initialize(); - //} + base.CompPostTick(ref severityAdjustment); + // If an exception makes it out, RW will remove the hediff, so catch it here + try + { + if ( + !parent.pawn.IsHashIntervalTick(tickInterval) || + !parent.pawn.Spawned || // TODO: Add option to simulate off-map pawns + parent.pawn.health.Dead || + (parent.pawn.IsAnimal() && !Configurations.EnableAnimalCycle) + ) + { + return; + } + + CumOut(); + if (pregnancy == null && parent.pawn.health.capacities.GetLevel(xxx.reproduction) <= 0) curStage = Stage.Young; + switch (curStage) + { + case Stage.Follicular: + FollicularAction(false); + break; + case Stage.Ovulatory: + OvulatoryAction(); + break; + case Stage.Luteal: + LutealAction(false); + break; + case Stage.Bleeding: + BleedingAction(false); + break; + case Stage.Pregnant: + PregnantAction(); + break; + case Stage.Recover: + RecoverAction(); + break; + case Stage.None: + break; + case Stage.Young: + YoungAction(); + break; + case Stage.ClimactericFollicular: + FollicularAction(true); + break; + case Stage.ClimactericLuteal: + LutealAction(true); + break; + case Stage.ClimactericBleeding: + BleedingAction(true); + break; + case Stage.Anestrus: + AnestrusAction(); + break; + default: + GoNextStage(Stage.Follicular); + break; + } + AfterSimulator(); + } + catch (Exception ex) + { + Log.Error($"Error processing womb of {parent.pawn}: {ex}"); + } } public override void CompPostPostRemoved() @@ -546,8 +627,6 @@ namespace RJW_Menstruation Log.Warning($"Attempted to remove menstruation comp from wrong pawn ({parent.pawn})."); return; } - HugsLibController.Instance.TickDelayScheduler.TryUnscheduleCallback(actionref); - if (Configurations.Debug) Log.Message(parent.pawn.Label + " menstruation tick scheduler removed"); pregnancy?.Miscarry(); base.CompPostPostRemoved(); } @@ -871,7 +950,6 @@ namespace RJW_Menstruation { if (cums == null) cums = new List(); curStage = Stage.None; - HugsLibController.Instance.TickDelayScheduler.ScheduleCallback(PeriodSimulator(curStage), GetNextUpdate(), parent.pawn, false); loaded = true; return; } @@ -912,18 +990,6 @@ namespace RJW_Menstruation } } - if (parent.pawn.IsAnimal()) - { - if (Configurations.EnableAnimalCycle) - { - HugsLibController.Instance.TickDelayScheduler.ScheduleCallback(PeriodSimulator(curStage), GetNextUpdate(), parent.pawn, false); - } - } - else - { - if (pregnancy == null && parent.pawn.health.capacities.GetLevel(xxx.reproduction) <= 0) HugsLibController.Instance.TickDelayScheduler.ScheduleCallback(PeriodSimulator(Stage.Young), GetNextUpdate(), parent.pawn, false); - else HugsLibController.Instance.TickDelayScheduler.ScheduleCallback(PeriodSimulator(curStage), GetNextUpdate(), parent.pawn, false); - } //Log.Message(parent.pawn.Label + " - Initialized menstruation comp"); loaded = true; } @@ -995,7 +1061,7 @@ namespace RJW_Menstruation else if (ovarypower < OvaryPowerThreshold) { Hediff hediff = HediffMaker.MakeHediff(VariousDefOf.Hediff_Climacteric, parent.pawn); - hediff.Severity = 0.008f * (OvaryPowerThreshold - ovarypower); + hediff.Severity = Mathf.InverseLerp(OvaryPowerThreshold, 0, ovarypower); parent.pawn.health.AddHediff(hediff, Genital_Helper.get_genitalsBPR(parent.pawn)); } } @@ -1146,14 +1212,12 @@ namespace RJW_Menstruation PregnancyHelper.PregnancyDecider(parent.pawn, egg.fertilizer); // I hate having to do this, but it gets the newest pregnancy pregnancy = parent.pawn.health.hediffSet.GetHediffs().MaxBy(hediff => hediff.loadID); - currentIntervalHours = (int)pregnancy?.GestationHours(); pregnant = true; break; } else { pregnancy = Hediff_BasePregnancy.Create(parent.pawn, egg.fertilizer); - currentIntervalHours = (int)pregnancy?.GestationHours(); pregnant = true; deadeggs.Add(egg); } @@ -1317,7 +1381,7 @@ namespace RJW_Menstruation float eggnum; try { - eggnum = Rand.ByCurve(parent.pawn.RaceProps.litterSizeCurve); + eggnum = Rand.ByCurve(parent.pawn.def.race.litterSizeCurve); } catch (NullReferenceException) { @@ -1325,7 +1389,7 @@ namespace RJW_Menstruation } catch (ArgumentException e) { - Log.Warning($"Invalid litterSizeCurve for {parent.pawn.RaceProps}: {e}"); + Log.Warning($"Invalid litterSizeCurve for {parent.pawn.def}: {e}"); eggnum = 1; } eggnum += eggstack; @@ -1351,7 +1415,7 @@ namespace RJW_Menstruation else if (Configurations.EnableMenopause && ovarypower < OvaryPowerThreshold) { Hediff hediff = HediffMaker.MakeHediff(VariousDefOf.Hediff_Climacteric, parent.pawn); - hediff.Severity = 0.008f * i; + hediff.Severity = Mathf.InverseLerp(OvaryPowerThreshold, 0, ovarypower); parent.pawn.health.AddHediff(hediff, Genital_Helper.get_genitalsBPR(parent.pawn)); GoNextStage(Stage.ClimactericLuteal); } @@ -1394,10 +1458,6 @@ namespace RJW_Menstruation EggDecay(); if (Implant()) { - if (Breast != null) - { - Breast.PregnancyTransition(); - } GoNextStage(Stage.Pregnant); } else @@ -1459,10 +1519,6 @@ namespace RJW_Menstruation else { if (pregnancy != null) pregnancy = null; - if (Breast != null) - { - Breast.BirthTransition(); - } GoNextStage(Stage.Recover); } } @@ -1584,108 +1640,12 @@ namespace RJW_Menstruation TaleRecorder.RecordTale(VariousDefOf.TaleCameInside, new object[] { cummer, parent.pawn }); } - private Action PeriodSimulator(Stage targetstage) - { - Action action = null; - switch (targetstage) - { - case Stage.Follicular: - action = delegate - { - FollicularAction(false); - }; - break; - case Stage.Ovulatory: - action = OvulatoryAction; - break; - case Stage.Luteal: - action = delegate - { - LutealAction(false); - }; - break; - case Stage.Bleeding: - action = delegate - { - BleedingAction(false); - }; - break; - case Stage.Pregnant: - action = PregnantAction; - break; - case Stage.Recover: - action = RecoverAction; - break; - case Stage.None: - action = delegate - { - StayCurrentStageConst(Stage.None); - }; - break; - case Stage.Young: - action = YoungAction; - break; - case Stage.ClimactericFollicular: - action = delegate - { - FollicularAction(true); - }; - break; - case Stage.ClimactericLuteal: - action = delegate - { - LutealAction(true); - }; - break; - case Stage.ClimactericBleeding: - action = delegate - { - BleedingAction(true); - }; - break; - case Stage.Anestrus: - action = AnestrusAction; - break; - default: - curStage = Stage.Follicular; - curStageHrs = 0; - if (currentIntervalHours < 0) currentIntervalHours = PeriodRandomizer(curStage); - HugsLibController.Instance.TickDelayScheduler.ScheduleCallback(PeriodSimulator(Stage.Follicular), GetNextUpdate(), parent.pawn, false); - break; - } - action += delegate - { - if (parent.pawn.health.capacities.GetLevel(xxx.reproduction) <= 0) curStage = Stage.Young; - //CumOut(); - AfterSimulator(); - }; - action = CumOut + action; - - actionref = action; - return actionref; - - - - - } - - protected int GetNextUpdate() - { - // Ticks past the hour. Will be equal except for game start or load - int currentOffset = Find.TickManager.TicksGame % tickInterval; - int nextOffset = (parent.pawn.HashOffset() % tickInterval + tickInterval) % tickInterval; // Messy, but HashOffset is negative a lot - - // The -1/+1 to ensure that equality works out to 1 hour and not 0 ticks - return ((nextOffset - currentOffset + tickInterval - 1) % tickInterval) + 1; - } - protected void GoNextStage(Stage nextstage, bool calculateHours = true) { curStageHrs = 0; float variabilityFactor = nextstage == Stage.ClimactericFollicular || nextstage == Stage.ClimactericLuteal || nextstage == Stage.ClimactericBleeding ? 6.0f : 1.0f; if (calculateHours) currentIntervalHours = PeriodRandomizer(nextstage, variabilityFactor); curStage = nextstage; - HugsLibController.Instance.TickDelayScheduler.ScheduleCallback(PeriodSimulator(nextstage), GetNextUpdate(), parent.pawn, false); } protected virtual void GoOvulatoryStage(bool climacteric) @@ -1696,13 +1656,11 @@ namespace RJW_Menstruation //stage can be interrupted in other reasons protected void StayCurrentStage() { - HugsLibController.Instance.TickDelayScheduler.ScheduleCallback(PeriodSimulator(curStage), GetNextUpdate(), parent.pawn, false); } //stage never changes protected void StayCurrentStageConst(Stage curstage) { - HugsLibController.Instance.TickDelayScheduler.ScheduleCallback(PeriodSimulator(curstage), GetNextUpdate(), parent.pawn, false); } protected void GoFollicularOrBleeding() @@ -1745,6 +1703,8 @@ namespace RJW_Menstruation return (int)(Props.bleedingIntervalDays * 24 * (1 + Rand.Range(-cycleVariability, cycleVariability) * 0.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 0.5f)); case Stage.Recover: return (int)(Props.recoveryIntervalDays * 24 * Rand.Range(-0.05f, 0.05f)); + case Stage.Pregnant: + return (int)MenstruationUtility.GestationHours(pregnancy); default: // Often unused return 1; } @@ -1772,24 +1732,32 @@ namespace RJW_Menstruation protected Stage RandomStage() { - int rand = Rand.ElementByWeight( - 0, Props.follicularIntervalDays - Props.bleedingIntervalDays, - 1, Props.lutealIntervalDays, - 2, Props.bleedingIntervalDays); + Stage stage = Rand.ElementByWeight( + Stage.Follicular, Props.follicularIntervalDays - Props.bleedingIntervalDays, + Stage.Luteal, Props.lutealIntervalDays, + Stage.Bleeding, Props.bleedingIntervalDays); - switch (rand) + switch (stage) { - case 0: + case Stage.Follicular: curStageHrs = Rand.Range(0, (Props.follicularIntervalDays - Props.bleedingIntervalDays) * 24); - return Stage.Follicular; - case 1: + break; + case Stage.Luteal: curStageHrs = Rand.Range(0, Props.lutealIntervalDays * 24); - return Stage.Luteal; - case 2: + break; + case Stage.Bleeding: curStageHrs = Rand.Range(0, Props.bleedingIntervalDays * 24); - return Stage.Bleeding; - default: return Stage.Follicular; + break; } + return stage; + } + + public void CopyCycleProperties(HediffComp_Menstruation original) + { + cycleSpeed = original.cycleSpeed; + cycleVariability = original.cycleVariability; + ovarypower = original.ovarypower; + crampPain = original.crampPain; } public class Egg : IExposable diff --git a/1.3/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs b/1.3/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs index 56eff5c..79ef1c0 100644 --- a/1.3/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs +++ b/1.3/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs @@ -9,6 +9,8 @@ namespace RJW_Menstruation { public class Hediff_MultiplePregnancy : Hediff_BasePregnancy { + protected Dictionary enzygoticSiblings; // Each pawn and who they split from + public override void DiscoverPregnancy() { PregnancyThought(); @@ -185,6 +187,68 @@ namespace RJW_Menstruation //baby.story.birthLastName = last_name; } + protected void CopyBodyPartProperties(Hediff part, Hediff originalPart) + { + CompHediffBodyPart comp = part.TryGetComp(); + CompHediffBodyPart originalComp = originalPart.TryGetComp(); + + if (comp != null && originalComp != null) + { + // the string properties should be the same between both pawns anyways, besides the name of the owner + part.Severity = originalPart.Severity; + comp.SizeBase = originalComp.SizeBase; + comp.SizeOwner = originalComp.SizeOwner; + comp.EffSize = originalComp.EffSize; + comp.FluidAmmount = originalComp.FluidAmmount; + comp.FluidModifier = originalComp.FluidModifier; + } + + HediffComp_Menstruation originalMenstruationComp = originalPart.GetMenstruationComp(); + if (originalMenstruationComp != null) + { + part.GetMenstruationComp()?.CopyCycleProperties(originalMenstruationComp); + } + HediffComp_Breast originalBreastComp = originalPart.GetBreastComp(); + if (originalBreastComp != null) + { + part.GetBreastComp()?.CopyBreastProperties(originalBreastComp); + } + } + + protected void CopyBodyPartRecord(Pawn baby, Pawn original, BodyPartRecord babyBPR, BodyPartRecord originalBPR) + { + if (babyBPR == null || originalBPR == null) return; + + RemoveBabyParts(baby, Genital_Helper.get_PartsHediffList(baby, babyBPR)); + foreach (Hediff originalPart in Genital_Helper.get_PartsHediffList(original, originalBPR)) + { + Hediff part = SexPartAdder.MakePart(originalPart.def, baby, babyBPR); + CopyBodyPartProperties(part, originalPart); + baby.health.AddHediff(part, babyBPR); + } + } + + // Baby is the sibling to be changed, original is the first of the set and the one to copy to the rest. + public virtual void ProcessIdenticalSibling(Pawn baby, Pawn original) + { + // They'll be the same pawnkind, which lets us make a lot of useful assumptions + // However, some RNG might still be involved in genital generation (e.g. futas), so the easiest method is to clear out and re-generate + // A bit wasteful since Hediff_BasePregnancy.PostBirth already redid the genitals + CopyBodyPartRecord(baby, original, Genital_Helper.get_genitalsBPR(baby), Genital_Helper.get_genitalsBPR(original)); + CopyBodyPartRecord(baby, original, Genital_Helper.get_breastsBPR(baby), Genital_Helper.get_breastsBPR(original)); + CopyBodyPartRecord(baby, original, Genital_Helper.get_anusBPR(baby), Genital_Helper.get_anusBPR(original)); + if (baby.IsHAR()) + HARCompatibility.CopyHARPropertiesPostBirth(baby, original); + } + + public override void PostBirth(Pawn mother, Pawn father, Pawn baby) + { + base.PostBirth(mother, father, baby); + // Has to happen on birth since RJW redoes the genitals at birth + if (!enzygoticSiblings.NullOrEmpty() && enzygoticSiblings.TryGetValue(baby, out Pawn original) && baby != original) + ProcessIdenticalSibling(baby, original); + } + // From RJW's trait code protected List GetInheritableTraits(Pawn mother, Pawn father) { @@ -279,13 +343,17 @@ namespace RJW_Menstruation return traitpool; } + public override void ExposeData() + { + base.ExposeData(); + Scribe_Collections.Look(ref enzygoticSiblings, "enzygoticSiblings", keyLookMode: LookMode.Reference, valueLookMode: LookMode.Reference); + } + protected override void GenerateBabies() { AddNewBaby(pawn, father); } - - protected void Train(Pawn baby, Pawn mother) { if (xxx.is_human(baby) || baby.Faction != Faction.OfPlayer) return; @@ -348,27 +416,25 @@ namespace RJW_Menstruation ); int division = 1; - HairDef firsthair = null; - Color firsthaircolor = Color.white; - BodyTypeDef firstbody = null; - CrownType firstcrown = CrownType.Undefined; + Pawn firstbaby = null; string firstheadpath = null; - string firstHARcrown = null; int traitSeed = Rand.Int; List parentTraits = GetInheritableTraits(mother, father); while (Rand.Chance(Configurations.EnzygoticTwinsChance) && division < Configurations.MaxEnzygoticTwins) division++; for (int i = 0; i < division; i++) { Pawn baby = GenerateBaby(request, mother, father, parentTraits, traitSeed); + if (baby == null) break; if (division > 1) { - if (i == 0 && baby.story != null) + if (i == 0) firstbaby = baby; + else enzygoticSiblings?.Add(baby, firstbaby); + + if (baby.story == null) continue; + + if (i == 0) { - firsthair = baby.story.hairDef; - firsthaircolor = baby.story.hairColor; request.FixedGender = baby.gender; - firstbody = baby.story.bodyType; - firstcrown = baby.story.crownType; firstheadpath = (string)baby.story.GetMemberValue("headGraphicPath"); if (firstheadpath == null) { @@ -376,36 +442,25 @@ namespace RJW_Menstruation if (head != null) baby.story.SetMemberValue("headGraphicPath", head.GraphicPath); firstheadpath = (string)baby.story.GetMemberValue("headGraphicPath"); } - if (Configurations.HARActivated && baby.IsHAR()) - { - firstHARcrown = baby.GetHARCrown(); - } } else { - if (baby.story != null) - { - baby.story.hairDef = firsthair; - baby.story.hairColor = firsthaircolor; - baby.story.bodyType = firstbody; - baby.story.crownType = firstcrown; - baby.story.SetMemberValue("headGraphicPath", firstheadpath); + baby.story.hairDef = firstbaby.story.hairDef; + baby.story.hairColor = firstbaby.story.hairColor; + baby.story.bodyType = firstbaby.story.bodyType; + baby.story.crownType = firstbaby.story.crownType; + baby.story.SetMemberValue("headGraphicPath", firstheadpath); - if (Configurations.HARActivated && baby.IsHAR()) - { - baby.SetHARCrown(firstHARcrown); - } + if (baby.IsHAR()) + { + HARCompatibility.CopyHARProperties(baby, firstbaby); } } } - - if (baby != null) babies.Add(baby); + babies.Add(baby); } - - - return true; } @@ -665,8 +720,17 @@ namespace RJW_Menstruation pawn.story.traits.allTraits = selectedTraits; } + public override void Initialize(Pawn mother, Pawn dad) + { + enzygoticSiblings = new Dictionary(); + base.Initialize(mother, dad); + } - + public string DueDate() + { + if (pawn.Map == null) return ""; + return GenDate.DateFullStringWithHourAt(GenDate.TickGameToAbs((int)p_end_tick), Find.WorldGrid.LongLatOf(pawn.Map.Tile)); + } } /// diff --git a/1.3/source/RJW_Menstruation/RJW_Menstruation/Patch/GetGizmos.cs b/1.3/source/RJW_Menstruation/RJW_Menstruation/Patch/GetGizmos.cs index 22bf735..2c8c2c9 100644 --- a/1.3/source/RJW_Menstruation/RJW_Menstruation/Patch/GetGizmos.cs +++ b/1.3/source/RJW_Menstruation/RJW_Menstruation/Patch/GetGizmos.cs @@ -43,12 +43,18 @@ namespace RJW_Menstruation { Texture2D icon, icon_overay; string description = ""; - if (Configurations.Debug) description += comp.curStage + ": " + comp.curStageHrs + "\n" + "fertcums: " + comp.TotalFertCum + "\n" + "ovarypower: " + comp.ovarypower + "\n" + "eggs: " + comp.GetNumofEggs + "\n"; + if (Configurations.Debug) { + description += comp.curStage + ": " + comp.curStageHrs + "\n" + + (comp.Pregnancy is Hediff_MultiplePregnancy preg ? "due: " + preg.DueDate() + "\n" : "") + + "fertcums: " + comp.TotalFertCum + "\n" + + "ovarypower: " + comp.ovarypower + "\n" + + "eggs: " + comp.GetNumofEggs + "\n"; + } else description += comp.GetCurStageLabel + "\n"; if (pawn.IsPregnant()) { Hediff_BasePregnancy hediff = comp.Pregnancy; - if (Utility.ShowFetusImage(hediff)) + if (hediff != null && Utility.ShowFetusImage(hediff)) { icon = comp.GetPregnancyIcon(hediff); if (hediff is Hediff_BasePregnancy h) diff --git a/1.3/source/RJW_Menstruation/RJW_Menstruation/Patch/Pawn_Patch.cs b/1.3/source/RJW_Menstruation/RJW_Menstruation/Patch/Pawn_Patch.cs index 2265058..f26ca4c 100644 --- a/1.3/source/RJW_Menstruation/RJW_Menstruation/Patch/Pawn_Patch.cs +++ b/1.3/source/RJW_Menstruation/RJW_Menstruation/Patch/Pawn_Patch.cs @@ -1,5 +1,4 @@ using HarmonyLib; -using HugsLib; using RimWorld; using System.Collections.Generic; using UnityEngine; @@ -16,14 +15,12 @@ namespace RJW_Menstruation //Log.Message("Initialize on spawnsetup"); foreach (HediffComp_Menstruation comp in __instance.GetMenstruationComps()) { - HugsLibController.Instance.TickDelayScheduler.TryUnscheduleCallback(comp.actionref); comp.Initialize(); } HediffComp_Breast bcomp = __instance.GetBreastComp(); if (bcomp != null) { - HugsLibController.Instance.TickDelayScheduler.TryUnscheduleCallback(bcomp.action); bcomp.Initialize(); } } diff --git a/1.3/source/RJW_Menstruation/RJW_Menstruation/RJW_Menstruation.csproj b/1.3/source/RJW_Menstruation/RJW_Menstruation/RJW_Menstruation.csproj index 198c10f..f73a2ef 100644 --- a/1.3/source/RJW_Menstruation/RJW_Menstruation/RJW_Menstruation.csproj +++ b/1.3/source/RJW_Menstruation/RJW_Menstruation/RJW_Menstruation.csproj @@ -89,12 +89,12 @@ - - ..\..\..\..\..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll + + ..\..\..\..\..\..\..\..\workshop\content\294100\839005762\1.3\Assemblies\AlienRace.dll False - - ..\..\..\..\..\..\..\..\workshop\content\294100\818773962\v1.3\Assemblies\HugsLib.dll + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll False diff --git a/1.3/source/RJW_Menstruation/RJW_Menstruation/Recipe_Surgery.cs b/1.3/source/RJW_Menstruation/RJW_Menstruation/Recipe_Surgery.cs index 6a1f8b8..c34c0e9 100644 --- a/1.3/source/RJW_Menstruation/RJW_Menstruation/Recipe_Surgery.cs +++ b/1.3/source/RJW_Menstruation/RJW_Menstruation/Recipe_Surgery.cs @@ -48,7 +48,7 @@ namespace RJW_Menstruation { protected override void SurgeryResult(HediffComp_Breast breast) { - breast.AdjustAreolaSizeImmidiately(0.1f); + breast.AdjustAreolaSizeImmediately(0.2f); } } @@ -56,7 +56,7 @@ namespace RJW_Menstruation { protected override void SurgeryResult(HediffComp_Breast breast) { - breast.AdjustAreolaSizeImmidiately(-0.1f); + breast.AdjustAreolaSizeImmediately(-0.2f); } } @@ -64,7 +64,7 @@ namespace RJW_Menstruation { protected override void SurgeryResult(HediffComp_Breast breast) { - breast.AdjustNippleSizeImmidiately(0.1f); + breast.AdjustNippleSizeImmediately(0.2f); } } @@ -72,7 +72,7 @@ namespace RJW_Menstruation { protected override void SurgeryResult(HediffComp_Breast breast) { - breast.AdjustNippleSizeImmidiately(-0.1f); + breast.AdjustNippleSizeImmediately(-0.2f); } } } diff --git a/1.3/source/RJW_Menstruation/RJW_Menstruation/Translations.cs b/1.3/source/RJW_Menstruation/RJW_Menstruation/Translations.cs index 6189613..320763d 100644 --- a/1.3/source/RJW_Menstruation/RJW_Menstruation/Translations.cs +++ b/1.3/source/RJW_Menstruation/RJW_Menstruation/Translations.cs @@ -98,14 +98,6 @@ namespace RJW_Menstruation public static readonly string Option23_Label = "Option23_Label".Translate(); public static readonly string Option23_Label_1 = "Option23_Label_1".Translate(); public static readonly string Option23_Label_2 = "Option23_Label_2".Translate(); - public static readonly string Option24_Label = "Option24_Label".Translate(); - public static readonly string Option24_Desc = "Option24_Desc".Translate(); - public static readonly string Option25_Label = "Option25_Label".Translate(); - public static readonly string Option25_Desc = "Option25_Desc".Translate(); - public static readonly string Option26_Label = "Option26_Label".Translate(); - public static readonly string Option26_Desc = "Option26_Desc".Translate(); - public static readonly string Option27_Label = "Option27_Label".Translate(); - public static readonly string Option27_Desc = "Option27_Desc".Translate(); public static readonly string Option28_Label = "Option28_Label".Translate(); public static readonly string Option28_Tooltip = "Option28_Tooltip".Translate(); public static readonly string Option29_Label = "Option29_Label".Translate(); @@ -116,6 +108,12 @@ namespace RJW_Menstruation public static readonly string Option31_Desc = "Option31_Desc".Translate(); public static readonly string Option32_Label = "Option32_Label".Translate(); public static readonly string Option32_Desc = "Option32_Desc".Translate(); + public static readonly string Option_MaxBreastIncrementFactor_Label = "Option_MaxBreastIncrementFactor_Label".Translate(); + public static readonly string Option_MaxBreastIncrementFactor_Desc = "Option_MaxBreastIncrementFactor_Desc".Translate(); + public static readonly string Option_MaxNippleIncrementFactor_Label = "Option_MaxNippleIncrementFactor_Label".Translate(); + public static readonly string Option_MaxNippleIncrementFactor_Desc = "Option_MaxNippleIncrementFactor_Desc".Translate(); + public static readonly string Option_PermanentNippleChange_Label = "Option_PermanentNippleChange_Label".Translate(); + public static readonly string Option_PermanentNippleChange_Desc = "Option_PermanentNippleChange_Desc".Translate(); public static readonly string Option_EnableGatherCumGizmo_Label = "Option_EnableGatherCumGizmo_Label".Translate(); public static readonly string Option_EstrusOverride_Label = "Option_EstrusOverride_Label".Translate(); public static readonly string Option_EstrusOverride_Desc = "Option_EstrusOverride_Desc".Translate(); diff --git a/1.3/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs b/1.3/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs index 21ed45b..7ec6033 100644 --- a/1.3/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs +++ b/1.3/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs @@ -32,11 +32,11 @@ namespace RJW_Menstruation private Texture2D anal; private Color cumcolor; - private readonly GUIStyle fontstylecenter = new GUIStyle() { alignment = TextAnchor.MiddleCenter }; - private readonly GUIStyle fontstyleright = new GUIStyle() { alignment = TextAnchor.MiddleRight }; - private readonly GUIStyle fontstyleleft = new GUIStyle() { alignment = TextAnchor.MiddleLeft }; - private readonly GUIStyle boxstyle = new GUIStyle(GUI.skin.textArea); - private readonly GUIStyle buttonstyle = new GUIStyle(GUI.skin.button); + private static GUIStyle fontstylecenter = null; + private static GUIStyle fontstyleright = null; + private static GUIStyle fontstyleleft = null; + private static GUIStyle boxstyle = null; + private static GUIStyle buttonstyle = null; public Pawn Pawn { @@ -137,6 +137,16 @@ namespace RJW_Menstruation } + public override void PreOpen() + { + base.PreOpen(); + if (fontstylecenter == null) fontstylecenter = new GUIStyle() { alignment = TextAnchor.MiddleCenter }; + if (fontstyleright == null) fontstyleright = new GUIStyle() { alignment = TextAnchor.MiddleRight }; + if (fontstyleleft == null) fontstyleleft = new GUIStyle() { alignment = TextAnchor.MiddleLeft }; + if (boxstyle == null) boxstyle = new GUIStyle(GUI.skin.textArea); + if (buttonstyle == null) buttonstyle = new GUIStyle(GUI.skin.button); + } + private void MainContents(Rect mainRect) { @@ -370,7 +380,7 @@ namespace RJW_Menstruation - pawn.DrawBreastIcon(BreastIconRect, Mouse.IsOver(BreastIconRect) && Input.GetMouseButton(0)); + pawn.DrawBreastIcon(BreastIconRect); GUI.color = Color.white; diff --git a/1.3/source/RJW_Menstruation/RJW_Menstruation/Utility.cs b/1.3/source/RJW_Menstruation/RJW_Menstruation/Utility.cs index 38d40a3..5e4ab93 100644 --- a/1.3/source/RJW_Menstruation/RJW_Menstruation/Utility.cs +++ b/1.3/source/RJW_Menstruation/RJW_Menstruation/Utility.cs @@ -159,7 +159,7 @@ namespace RJW_Menstruation } } - public static void DrawBreastIcon(this Pawn pawn, Rect rect, bool drawOrigin = false) + public static void DrawBreastIcon(this Pawn pawn, Rect rect) { Hediff hediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_breastsBPR(pawn)).FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("breast")); Texture2D breast, nipple, areola; @@ -167,7 +167,7 @@ namespace RJW_Menstruation { HediffComp_Breast comp = hediff.TryGetComp(); string icon; - if (comp != null) icon = comp.Props.BreastTex ?? "Breasts/Breast_Breast"; + if (comp != null) icon = comp.Props?.BreastTex ?? "Breasts/Breast_Breast"; else { breast = ContentFinder.Get("Breasts/Breast_Breast00", false); @@ -191,16 +191,8 @@ namespace RJW_Menstruation string nippleicon, areolaicon; float nipplesize, areolasize; - if (drawOrigin) - { - nipplesize = comp.OriginNipple; - areolasize = comp.OriginAreola; - } - else - { - nipplesize = comp.NippleSize; - areolasize = comp.AreolaSize; - } + nipplesize = comp.NippleSize; + areolasize = comp.AreolaSize; nippleicon = icon + "_Nipple0" + GetNippleIndex(nipplesize); areolaicon = icon + "_Areola0" + GetAreolaIndex(areolasize); @@ -212,14 +204,8 @@ namespace RJW_Menstruation GUI.color = pawn.story.SkinColor; GUI.DrawTexture(rect, breast, ScaleMode.ScaleToFit); - if (drawOrigin) - { - GUI.color = comp.OriginColor; - } - else - { - GUI.color = comp.NippleColor; - } + GUI.color = comp.NippleColor; + GUI.DrawTexture(rect, areola, ScaleMode.ScaleToFit); GUI.DrawTexture(rect, nipple, ScaleMode.ScaleToFit); diff --git a/About/About.xml b/About/About.xml index ac2c696..4dbf4bb 100644 --- a/About/About.xml +++ b/About/About.xml @@ -13,12 +13,6 @@ steam://url/CommunityFilePage/2009463077 https://github.com/pardeike/HarmonyRimWorld/releases/latest -
  • - UnlimitedHugs.HugsLib - HugsLib - https://github.com/UnlimitedHugs/RimworldHugsLib/releases/latest - steam://url/CommunityFilePage/818773962 -
  • rim.job.world RimJobWorld @@ -26,12 +20,13 @@
  • -
  • UnlimitedHugs.HugsLib
  • brrainz.harmony
  • +
  • erdelf.HumanoidAlienRaces
  • rim.job.world
  • Abraxas.RJW.RaceSupport
  • rjw.milk.humanoid
  • rjw.sexperience
  • +
  • rjw.cum
  • rjw.menstruation Adds menstruation mechanics to vaginas diff --git a/About/Manifest.xml b/About/Manifest.xml index d56ea34..8984142 100644 --- a/About/Manifest.xml +++ b/About/Manifest.xml @@ -1,7 +1,7 @@ RJW Menstruation - 1.0.7.0 + 1.0.7.1 @@ -12,6 +12,7 @@
  • Abraxas.RJW.RaceSupport
  • rjw.milk.humanoid
  • rjw.sexperience
  • +
  • rjw.cum
  • diff --git a/changelogs.txt b/changelogs.txt index 45dff74..9dbd28c 100644 --- a/changelogs.txt +++ b/changelogs.txt @@ -1,3 +1,15 @@ +Version 1.0.7.1 + - Null reference error fix for multiple wombs when one is pregnant. + - Fix the progress bar on pregnancy again. Also make undiscovered pregnancies a little more subtle. + - Nipple size/transition system rewritten to be simpler under the hood. Should work with existing saves, but you might find sizes to be different, especially for very large or very small breasts. + - Replaced HugsLib-based scheduler with normal ticking. This should reduce some 'phantom cycle' bugs. + - Redone calculation to determine low eggs remaining. This should cause climacteric to be applied at a more appropriate time in the pawn's life, especially for those with very long cycles. + - Identical twins conceived after this update will have identical sex part sizes, properties, etc. upon being born. + - Identical twins of HAR races will have identical coloration, part variations, and masking. + - For modders: + - The function Hediff_MultiplePregnancy.ProcessIdenticalSibling is called on every identical sibling when born except the first. Any race-specfic genetic properties can be patched in there. + - Any mods that add comps to RJW parts should copy what they need to on a postfix to Hediff_MultiplePregnancy.CopyBodyPartProperties, e.g. how menstruation itself does in that function. + Version 1.0.7.0 - Not save compatible with previous versions. Expect glitches and many red errors if you try. However, things should stabilize eventually. - Designed for RJW 5.0.0, but should work with previous versions.