Merge branch 'dev'

This commit is contained in:
lutepickle 2022-09-05 10:41:10 -07:00
commit 4b558ed1e7
26 changed files with 273 additions and 203 deletions

Binary file not shown.

View File

@ -174,7 +174,7 @@
<HediffDef Name="Hediff_Estrus">
<hediffClass>HediffWithComps</hediffClass>
<hediffClass>RJW_Menstruation.Hediff_Estrus</hediffClass>
<defName>Hediff_Estrus</defName>
<label>Estrus</label>
<labelNoun>estrus</labelNoun>
@ -197,15 +197,10 @@
</statFactors>
</li>
</stages>
<comps>
<li Class="HediffCompProperties_SeverityPerDay">
<severityPerDay>-1.0</severityPerDay>
</li>
</comps>
</HediffDef>
<HediffDef Name="Hediff_Estrus_Concealed">
<hediffClass>HediffWithComps</hediffClass>
<hediffClass>RJW_Menstruation.Hediff_Estrus</hediffClass>
<defName>Hediff_Estrus_Concealed</defName>
<label>Estrus (concealed)</label>
<labelNoun>estrus</labelNoun>
@ -229,11 +224,6 @@
</statFactors>
</li>
</stages>
<comps>
<li Class="HediffCompProperties_SeverityPerDay">
<severityPerDay>-1.0</severityPerDay>
</li>
</comps>
</HediffDef>

View File

@ -78,20 +78,6 @@
</value>
</Operation>
<Operation Class="PatchOperationAddModExtension">
<xpath>/Defs/ThingDef[defName="YorkshireTerrier"]</xpath>
<value>
<li Class="RJW_Menstruation.PawnDNAModExtension">
<fetusTexPath>Fetus/Canines/Fetus_Dog</fetusTexPath>
<cumColor>(255,255,255,255)</cumColor>
<cumThickness>0.05</cumThickness>
<hybridExtension>
</hybridExtension>
</li>
</value>
</Operation>
<Operation Class="PatchOperationAddModExtension">
<xpath>/Defs/ThingDef[defName="Husky"]</xpath>
<value>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -29,11 +29,8 @@ namespace MilkModule
}
protected override void PostTickAction()
{
if (breastcomp != null)
{
breastcomp.AdjustNippleProgress(Rand.Range(0.0f, 0.01f));
}
{
breastcomp?.AdjustNippleProgress(Rand.Range(0.0f, 0.000005f) * Configurations.MaxNippleIncrementFactor);
}

View File

@ -15,18 +15,13 @@ namespace MilkModule
}
}
[HarmonyPatch(typeof(HumanCompHasGatherableBodyResource), "Gathered")]
[HarmonyPatch(typeof(HumanCompHasGatherableBodyResource), nameof(HumanCompHasGatherableBodyResource.Gathered))]
public static class Milk_Patch
{
public static void Postfix(HumanCompHasGatherableBodyResource __instance)
{
HediffComp_Breast comp = null;
if (__instance.parent is Pawn pawn) comp = pawn.GetBreastComp();
if (comp != null)
{
comp.AdjustNippleProgress(Rand.Range(0.0f, 0.01f));
}
if (__instance.parent is Pawn pawn)
pawn.GetBreastComp()?.AdjustNippleProgress(Rand.Range(0.0f, 0.005f) * Configurations.MaxNippleIncrementFactor);
}
}

View File

@ -148,14 +148,10 @@ namespace RJW_Menstruation
if (o.IsNull) removeList.Add(o);
if (o.DefName == def.defName) return true;
}
if (!removeList.NullOrEmpty())
foreach (HybridInformations o in removeList)
{
foreach (HybridInformations o in removeList)
{
HybridOverride.Remove(o);
}
HybridOverride.Remove(o);
}
removeList.Clear();
return false;
}

View File

@ -222,14 +222,10 @@ namespace RJW_Menstruation
public void CumEffects(Pawn pawn)
{
if (notcum || DNA == null || volume < 1.0f) return;
if (notcum || DNA?.ingestionOutcomeDoers == null || volume < 1.0f) return;
List<IngestionOutcomeDoer> doers = DNA.ingestionOutcomeDoers;
if (!doers.NullOrEmpty()) for (int i = 0; i < doers.Count; i++)
{
doers[i].DoIngestionOutcome(pawn, CumThing);
}
foreach (IngestionOutcomeDoer doer in DNA.ingestionOutcomeDoers)
doer.DoIngestionOutcome(pawn, CumThing);
}
protected void CutMinor()
@ -238,7 +234,7 @@ namespace RJW_Menstruation
}
}
public class CumMixture : Cum, IDisposable
public class CumMixture : Cum
{
protected List<string> cums;
public bool ispurecum = true;
@ -260,12 +256,6 @@ namespace RJW_Menstruation
ispurecum = pure;
}
public void Dispose()
{
cums.Clear();
}
public override void ExposeData()
{
base.ExposeData();

View File

@ -1,4 +1,5 @@
using RimWorld;
using RimWorld.Planet;
using rjw;
using System;
using System.Collections.Generic;
@ -158,6 +159,14 @@ namespace RJW_Menstruation
Scribe_Values.Look(ref baseNipple, "baseNipple", baseNipple, true);
}
public bool ShouldSimulate()
{
if (!Configurations.EnableAnimalCycle && Pawn.IsAnimal()) return false;
if (Pawn.Spawned || Pawn.IsCaravanMember() || PawnUtility.IsTravelingInTransportPodWorldObject(Pawn)) return true;
return false;
}
public override void CompPostTick(ref float severityAdjustment)
{
base.CompPostTick(ref severityAdjustment);
@ -166,7 +175,7 @@ namespace RJW_Menstruation
{
if (
!Pawn.IsHashIntervalTick(tickInterval) ||
!Pawn.Spawned // TODO: Add option to simulate off-map pawns
!ShouldSimulate()
)
{
return;

View File

@ -1,4 +1,5 @@
using RimWorld;
using UnityEngine;
using Verse;
namespace RJW_Menstruation
@ -30,27 +31,21 @@ namespace RJW_Menstruation
}
}
// The maximum theoretical rate of ovulation is inducing the moment it goes follicular and no pregnancies
// There will be far more eggs than will ever actually be produced, but it fits the induced ovulator philosophy
// In an induced ovulator, about 65% of eggs ovulated will become pregnancies, so the expected lifetime supply
// is the number of pregnancies they could have, with some extra to be sure.
// An IUD or a poor fertility mate could run this down quicker. Oh well.
protected override float RaceCyclesPerYear()
{
int breedingSeasons = 0;
if (Props.breedingSeason == SeasonalBreed.Always) breedingSeasons = 4;
else
{
if ((Props.breedingSeason & SeasonalBreed.Spring) != 0) breedingSeasons++;
if ((Props.breedingSeason & SeasonalBreed.Summer) != 0) breedingSeasons++;
if ((Props.breedingSeason & SeasonalBreed.Fall) != 0) breedingSeasons++;
if ((Props.breedingSeason & SeasonalBreed.Winter) != 0) breedingSeasons++;
}
float breedingRatio = breedingSeasons / 4.0f;
return breedingRatio * GenDate.DaysPerYear / ((float)(Props.lutealIntervalDays + Props.bleedingIntervalDays) / Configurations.CycleAccelerationDefault);
// 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);
return 2 * pregnanciesPerYear / Configurations.ImplantationChanceDefault;
}
// There's really no good way to estimate the number of times it's been induced, so this is all we can do
protected override int PawnEggsUsed(float pawnCyclesElapsed, float avglittersize)
{
return 0;
return Mathf.CeilToInt((Pawn.relations?.ChildrenCount ?? 0) / Configurations.ImplantationChanceDefault);
}
protected override void GoOvulatoryStage(bool climacteric)
@ -92,14 +87,21 @@ namespace RJW_Menstruation
}
}
protected override bool ShouldBeInEstrus()
{
switch (curStage)
{
case Stage.Follicular:
case Stage.ClimactericFollicular:
return curStageHrs > currentIntervalHours - Props.estrusDaysBeforeOvulation * 24;
case Stage.Ovulatory:
return true;
case Stage.Luteal:
case Stage.ClimactericLuteal:
return IsEggExist && curStageHrs < Props.eggLifespanDays * 24;
default:
return false;
}
}
}
}

View File

@ -91,6 +91,12 @@ namespace RJW_Menstruation
Anestrus
}
public enum EstrusLevel
{
None,
Concealed,
Visible
}
public static readonly Dictionary<Stage, Texture2D> StageTexture = new Dictionary<Stage, Texture2D>()
{
@ -115,7 +121,6 @@ namespace RJW_Menstruation
protected string customvagtex = null;
protected bool estrusflag = false;
protected int opcache = -1;
protected HediffComp_Breast breastcache = null;
protected float antisperm = 0.0f;
protected float? originvagsize = null;
protected Hediff_BasePregnancy pregnancy = null;
@ -139,7 +144,6 @@ namespace RJW_Menstruation
get
{
if (opcache >= 0) return opcache;
// Climacteric will set in 6 (human) years before egg exhaustion
float avglittersize;
try
{
@ -150,9 +154,10 @@ namespace RJW_Menstruation
// Any exceptions in that will have been reported elsewhere in the code by now
avglittersize = 1.0f;
};
const float yearsBeforeMenopause = 6.0f;
opcache = (int)(RaceCyclesPerYear() *
avglittersize *
6f *
yearsBeforeMenopause *
(Pawn.def.race.lifeExpectancy / ThingDefOf.Human.race.lifeExpectancy));
return opcache;
}
@ -162,24 +167,21 @@ namespace RJW_Menstruation
{
get
{
if (cums.NullOrEmpty()) return 0;
return cums.Sum(cum => cum.Volume);
return cums?.Sum(cum => cum.Volume) ?? 0;
}
}
public float TotalFertCum
{
get
{
if (cums.NullOrEmpty()) return 0;
return cums.Sum(cum => cum.FertVolume);
return cums?.Sum(cum => cum.FertVolume) ?? 0;
}
}
public float TotalCumPercent
{
get
{
if (cums.NullOrEmpty()) return 0;
return cums.Sum(cum => cum.Volume) / Props.maxCumCapacity;
return cums?.Sum(cum => cum.Volume) / Props.maxCumCapacity ?? 0;
}
}
public float CumCapacity
@ -333,8 +335,7 @@ namespace RJW_Menstruation
{
get
{
if (customwombtex == null) return Props.wombTex;
else return customwombtex;
return customwombtex ?? Props.wombTex;
}
set
{
@ -345,8 +346,7 @@ namespace RJW_Menstruation
{
get
{
if (customvagtex == null) return Props.vagTex;
else return customvagtex;
return customvagtex ?? Props.vagTex;
}
set
{
@ -382,8 +382,8 @@ namespace RJW_Menstruation
{
get
{
if (eggs.NullOrEmpty() || cums.NullOrEmpty()) return false;
return cums.Any(cum => cum.FertVolume > 0);
if (eggs.NullOrEmpty()) return false;
return cums?.Any(cum => cum.FertVolume > 0) ?? false;
}
}
/// <summary>
@ -393,7 +393,7 @@ namespace RJW_Menstruation
{
get
{
if (eggs.NullOrEmpty()) return -1;
if (eggs?.All(egg => !egg.fertilized) ?? true) return -1;
return eggs.Max(egg => egg.fertstage);
}
}
@ -434,12 +434,11 @@ namespace RJW_Menstruation
}
}
}
public int GetNumofEggs
public int GetNumOfEggs
{
get
{
if (eggs.NullOrEmpty()) return 0;
else return eggs.Count;
return eggs?.Count ?? 0;
}
}
public Color BloodColor
@ -458,17 +457,6 @@ namespace RJW_Menstruation
}
}
public HediffComp_Breast Breast
{
get
{
if (breastcache == null)
{
breastcache = Pawn.GetBreastComp();
}
return breastcache;
}
}
public float OriginVagSize
{
@ -549,6 +537,14 @@ namespace RJW_Menstruation
}
}
public bool ShouldSimulate()
{
if (!Configurations.EnableAnimalCycle && Pawn.IsAnimal()) return false;
if (Pawn.Spawned || Pawn.IsCaravanMember() || PawnUtility.IsTravelingInTransportPodWorldObject(Pawn)) return true;
return false;
}
public override void CompPostTick(ref float severityAdjustment)
{
base.CompPostTick(ref severityAdjustment);
@ -557,8 +553,7 @@ namespace RJW_Menstruation
{
if (
!Pawn.IsHashIntervalTick(tickInterval) ||
!Pawn.Spawned || // TODO: Add option to simulate off-map pawns
(Pawn.IsAnimal() && !Configurations.EnableAnimalCycle)
!ShouldSimulate()
)
{
return;
@ -656,8 +651,7 @@ namespace RJW_Menstruation
/// <returns></returns>
public Cum GetCum(Pawn pawn)
{
if (cums.NullOrEmpty()) return null;
return cums.Find(cum => !cum.notcum && cum.pawn == pawn);
return cums?.Find(cum => !cum.notcum && cum.pawn == pawn);
}
/// <summary>
@ -845,7 +839,6 @@ namespace RJW_Menstruation
{
cums.Remove(cum);
}
removecums.Clear();
cumd = TotalCumPercent - cumd;
if (totalleak >= 1.0f) AfterCumOut();
AfterFluidOut(cumd);
@ -882,7 +875,6 @@ namespace RJW_Menstruation
{
cums.Remove(cum);
}
removecums.Clear();
cumd = TotalCumPercent - cumd;
AfterFluidOut(cumd);
return outcum;
@ -915,7 +907,6 @@ namespace RJW_Menstruation
{
cums.Remove(cum);
}
removecums.Clear();
return new CumMixture(Pawn, totalleak, cumlabels, color, mixtureDef, pure);
}
@ -978,21 +969,7 @@ namespace RJW_Menstruation
InitOvary();
if (pregnancy == null)
{
// If this womb isn't marked pregnant, search for pregnancies that have no womb and claim one
foreach (Hediff_BasePregnancy preg in Pawn.health.hediffSet.GetHediffs<Hediff_BasePregnancy>())
{
if (preg.GetMenstruationComp() == null)
{
currentIntervalHours = (int)preg.GestationHours();
curStage = Stage.Pregnant;
pregnancy = preg;
break;
}
}
}
TakeLoosePregnancy();
//Log.Message(Pawn.Label + " - Initialized menstruation comp");
loaded = true;
@ -1092,31 +1069,33 @@ namespace RJW_Menstruation
}
}
protected virtual bool ShouldBeInEstrus()
{
switch (curStage)
{
case Stage.Follicular:
case Stage.ClimactericFollicular:
return curStageHrs > currentIntervalHours - Props.estrusDaysBeforeOvulation * 24;
case Stage.Ovulatory:
return true;
case Stage.Luteal:
case Stage.ClimactericLuteal:
return curStageHrs < Props.eggLifespanDays * 24;
default:
return false;
}
}
public EstrusLevel GetEstrusLevel()
{
if (!ShouldBeInEstrus()) return EstrusLevel.None;
else return Props.concealedEstrus ? EstrusLevel.Concealed : EstrusLevel.Visible;
}
public void SetEstrus(int days)
{
HediffDef estrusdef = Props.concealedEstrus ? VariousDefOf.Hediff_Estrus_Concealed : VariousDefOf.Hediff_Estrus;
Hediff hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(estrusdef);
if (Props.concealedEstrus)
{
if (Pawn.health.hediffSet.HasHediff(VariousDefOf.Hediff_Estrus)) return;
}
else
{
Hediff concealedHediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_Estrus_Concealed);
if (concealedHediff != null) Pawn.health.RemoveHediff(concealedHediff);
}
if (hediff != null)
{
hediff.Severity = (float)days / Configurations.CycleAcceleration + 0.2f;
}
else
{
hediff = HediffMaker.MakeHediff(estrusdef, Pawn);
hediff.Severity = (float)days / Configurations.CycleAcceleration + 0.2f;
Pawn.health.AddHediff(hediff);
}
Hediff hediff = HediffMaker.MakeHediff(Props.concealedEstrus ? VariousDefOf.Hediff_Estrus_Concealed : VariousDefOf.Hediff_Estrus, Pawn);
Pawn.health.AddHediff(hediff);
}
public bool IsBreedingSeason()
@ -1194,14 +1173,14 @@ namespace RJW_Menstruation
}
else if (Rand.Range(0.0f, 1.0f) <= Configurations.ImplantationChance * ImplantFactor * InterspeciesImplantFactor(egg.fertilizer))
{
if (Configurations.Debug) Log.Message($"Implanting fertilized egg of {Pawn}, father {egg.fertilizer}");
if (Configurations.Debug) Log.Message($"Implanting fertilized egg of {Pawn} into {parent}, father {egg.fertilizer}");
if (pregnancy != null)
{
if (Configurations.UseMultiplePregnancy && Configurations.EnableHeteroOvularTwins)
{
if (pregnancy is Hediff_MultiplePregnancy h)
{
if (Configurations.Debug) Log.Message($"Adding to existing pregnancy");
if (Configurations.Debug) Log.Message($"Adding to existing pregnancy {h}");
h.AddNewBaby(Pawn, egg.fertilizer);
}
pregnant = true;
@ -1244,16 +1223,14 @@ namespace RJW_Menstruation
if (pregnant && (!Configurations.UseMultiplePregnancy || !Configurations.EnableHeteroOvularTwins))
{
eggs.Clear();
deadeggs.Clear();
return true;
}
else if (!deadeggs.NullOrEmpty())
else
{
foreach (Egg egg in deadeggs)
{
eggs.Remove(egg);
}
deadeggs.Clear();
}
return pregnant;
}
@ -1335,13 +1312,9 @@ namespace RJW_Menstruation
if (egg.lifespanhrs < 0) deadeggs.Add(egg);
}
}
if (!deadeggs.NullOrEmpty())
foreach (Egg egg in deadeggs)
{
foreach (Egg egg in deadeggs)
{
eggs.Remove(egg);
}
deadeggs.Clear();
eggs.Remove(egg);
}
}
@ -1525,7 +1498,7 @@ namespace RJW_Menstruation
Implant();
}
if (Pawn.health.hediffSet.hediffs.Contains(pregnancy))
if (pregnancy != null && Pawn.health.hediffSet.hediffs.Contains(pregnancy))
{
curStageHrs += 1;
StayCurrentStageConst(Stage.Pregnant);
@ -1541,14 +1514,18 @@ namespace RJW_Menstruation
{
if (curStageHrs >= currentIntervalHours)
{
if (Configurations.EnableMenopause && ovarypower < OvaryPowerThreshold)
{
GoNextStage(Stage.ClimactericFollicular);
}
else if (Pawn.health.capacities.GetLevel(xxx.reproduction) == 0)
if (Pawn.health.capacities.GetLevel(xxx.reproduction) == 0)
{
GoNextStage(Stage.Young);
}
else if (!IsBreedingSeason())
{
GoNextStage(Stage.Anestrus);
}
else if (Configurations.EnableMenopause && ovarypower < OvaryPowerThreshold)
{
GoNextStage(Stage.ClimactericFollicular);
}
else
{
GoNextStage(Stage.Follicular);
@ -1716,7 +1693,7 @@ namespace RJW_Menstruation
case Stage.ClimactericBleeding:
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));
return (int)(Props.recoveryIntervalDays * 24 * Rand.Range(0.95f, 1.05f));
case Stage.Pregnant:
return (int)MenstruationUtility.GestationHours(pregnancy);
default: // Often unused
@ -1766,6 +1743,19 @@ namespace RJW_Menstruation
return stage;
}
// Searches for an RJW pregnancy unclaimed by any womb and put it in this one
public void TakeLoosePregnancy()
{
if (pregnancy != null) return;
pregnancy =
Pawn.health.hediffSet.GetHediffs<Hediff_BasePregnancy>().Except(
Pawn.GetMenstruationComps().Select(comp => comp.pregnancy).Where(preg => preg != null)
).FirstOrDefault();
if (pregnancy != null)
GoNextStage(Stage.Pregnant);
}
public void CopyCycleProperties(HediffComp_Menstruation original)
{
cycleSpeed = original.cycleSpeed;

View File

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Verse;
using Verse.AI;
namespace RJW_Menstruation
{
@ -45,7 +46,7 @@ namespace RJW_Menstruation
public static HediffComp_Menstruation GetMenstruationComp(this Hediff vagina)
{
if (vagina is Hediff_PartBaseNatural || vagina is Hediff_PartBaseArtifical)
if (VariousDefOf.AllVaginas.Contains(vagina?.def))
{
return vagina.TryGetComp<HediffComp_Menstruation>();
}
@ -330,5 +331,26 @@ namespace RJW_Menstruation
if (pawn.Dead) return false;
return pawn.health?.hediffSet?.HasHediff(visible ? VariousDefOf.Hediff_Estrus : VariousDefOf.Hediff_Estrus_Concealed) ?? false;
}
public static HediffComp_Menstruation.EstrusLevel HighestEstrus(this Pawn pawn)
{
HediffComp_Menstruation.EstrusLevel res = HediffComp_Menstruation.EstrusLevel.None;
foreach(HediffComp_Menstruation comp in pawn.GetMenstruationComps())
{
switch (comp.GetEstrusLevel())
{
case HediffComp_Menstruation.EstrusLevel.None:
break;
case HediffComp_Menstruation.EstrusLevel.Concealed:
res = HediffComp_Menstruation.EstrusLevel.Concealed;
break;
case HediffComp_Menstruation.EstrusLevel.Visible:
return HediffComp_Menstruation.EstrusLevel.Visible;
}
}
return res;
}
}
}

View File

@ -0,0 +1,77 @@
using RimWorld;
using System.Linq;
using Verse;
namespace RJW_Menstruation
{
public class Hediff_Estrus : HediffWithComps
{
const int checkInterval = GenTicks.TickRareInterval;
private bool shouldRemove = false;
public override bool ShouldRemove
{
get
{
return shouldRemove || base.ShouldRemove;
}
}
protected virtual bool IsVisible
{
get
{
return def == VariousDefOf.Hediff_Estrus;
}
}
public override void PostAdd(DamageInfo? dinfo)
{
base.PostAdd(dinfo);
if (IsVisible)
{
foreach (Hediff concealedEstrus in pawn.health.hediffSet.hediffs.Where(hediff => hediff.def == VariousDefOf.Hediff_Estrus_Concealed))
{
pawn.health.RemoveHediff(concealedEstrus);
}
}
}
public override void PostTick()
{
base.PostTick();
if (!pawn.IsHashIntervalTick(checkInterval)) return;
if (IsVisible)
{
switch (pawn.HighestEstrus())
{
case HediffComp_Menstruation.EstrusLevel.None:
shouldRemove = true;
break;
case HediffComp_Menstruation.EstrusLevel.Concealed:
shouldRemove = true;
pawn.health.AddHediff(VariousDefOf.Hediff_Estrus_Concealed);
break;
case HediffComp_Menstruation.EstrusLevel.Visible:
break;
}
}
else
{
// Adding a visible will remove this one, so we don't have to check it here
if (pawn.HighestEstrus() == HediffComp_Menstruation.EstrusLevel.None) shouldRemove = true;
}
}
public override bool TryMergeWith(Hediff other)
{
if (!(other is Hediff_Estrus otherEstrus)) return false;
if (this.def == otherEstrus.def) return true;
else if (!this.IsVisible && otherEstrus.IsVisible && !otherEstrus.shouldRemove) return true; // A concealed estrus won't be added if there's a visible
// This is a visible estrus overwriting a concealed.
else return false; // Since this is being added while hediffs are being looped through, it's not safe to remove the concealed yet. Do it in PostAdd.
}
}
}

View File

@ -411,7 +411,7 @@ namespace RJW_Menstruation
fixedLastName: lastname,
kind: BabyPawnKindDecider(mother, father),
//fixedIdeo: mother.Ideo,
//forbidAnyTitle: true,
forbidAnyTitle: true,
forceNoBackstory: true
);
@ -734,9 +734,7 @@ namespace RJW_Menstruation
public override bool TryMergeWith(Hediff other)
{
if (other is Hediff_MultiplePregnancy preg)
return this.GetMenstruationComp() == preg.GetMenstruationComp();
else return base.TryMergeWith(other);
return false;
}
}

View File

@ -48,7 +48,7 @@ namespace RJW_Menstruation
(comp.Pregnancy is Hediff_MultiplePregnancy preg ? "due: " + preg.DueDate() + "\n" : "") +
"fertcums: " + comp.TotalFertCum + "\n" +
"ovarypower: " + comp.ovarypower + "\n" +
"eggs: " + comp.GetNumofEggs + "\n";
"eggs: " + comp.GetNumOfEggs + "\n";
}
else description += comp.GetCurStageLabel + "\n";
if (pawn.IsRJWPregnant())
@ -75,14 +75,14 @@ namespace RJW_Menstruation
Hediff hediff = pawn.health.hediffSet.GetHediffs<Hediff_InsectEgg>().FirstOrDefault();
if (hediff != null)
{
icon = ContentFinder<Texture2D>.Get(("Womb/Womb_Egged"), true);
icon_overay = ContentFinder<Texture2D>.Get(("Womb/Empty"), true);
icon = MenstruationUtility.GetInsectEggedIcon(comp);
}
else
{
icon = comp.GetWombIcon();
icon_overay = comp.GetCumIcon();
}
icon_overay = comp.GetCumIcon();
}
foreach (string s in comp.GetCumsInfo) description += s + "\n";

View File

@ -8,6 +8,7 @@ using System.Reflection;
using System.Reflection.Emit;
using UnityEngine;
using Verse;
using static RJW_Menstruation.HediffComp_Menstruation;
namespace RJW_Menstruation
{
@ -15,15 +16,12 @@ namespace RJW_Menstruation
[HarmonyPatch(typeof(PregnancyHelper), nameof(PregnancyHelper.impregnate))]
public static class Impregnate_Patch
{
public static bool Prefix(SexProps props, out HediffComp_Menstruation __state)
public static bool Prefix(SexProps props)
{
xxx.rjwSextype sextype = props.sexType;
Pawn pawn = props.pawn;
Pawn partner = props.partner;
if (PregnancyHelper.GetPregnancy(partner) is Hediff_BasePregnancy oldestPregnancy) __state = oldestPregnancy.GetMenstruationComp();
else __state = null;
if (sextype != xxx.rjwSextype.Vaginal && sextype != xxx.rjwSextype.DoublePenetration) return true;
if (partner.IsAnimal() && !Configurations.EnableAnimalCycle) return true;
@ -52,15 +50,18 @@ namespace RJW_Menstruation
return true;
}
public static void Postfix(SexProps props, HediffComp_Menstruation __state)
public static void Postfix(SexProps props)
{
if (__state == null || __state.Pregnancy != null) return;
// It was pregnant, but not anymore. This probably means the pregnancy was destroyed by e.g. a mech implant
Pawn pawn = props.partner;
Hediff_BasePregnancy newestPregnancy = pawn.health.hediffSet.GetHediffs<Hediff_BasePregnancy>().MaxByWithFallback(hediff => hediff.loadID);
if (newestPregnancy == null || pawn.GetMenstruationComps().Any(comp => comp.Pregnancy == newestPregnancy)) return; // One of the wombs did get it
else __state.Pregnancy = newestPregnancy;
if (props.sexType != xxx.rjwSextype.MechImplant && !pawn.health.hediffSet.GetHediffs<Hediff_InsectEgg>().Any()) return;
// The existing pregnancies might have been destroyed, so go through see if any new mech pregnancies need to be picked up
foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps())
{
_ = comp.Pregnancy; // get_Pregnancy will do any removals
comp.TakeLoosePregnancy();
}
}
/// <summary>

View File

@ -65,6 +65,7 @@
<Compile Include="EstrusPartKindUsageRule.cs" />
<Compile Include="HediffComps\HediffComp_InducedOvulator.cs" />
<Compile Include="HediffComps\MenstruationUtility.cs" />
<Compile Include="Hediff_Estrus.cs" />
<Compile Include="IngestionOutcomeDoers.cs" />
<Compile Include="Patch\GC_Patch.cs" />
<Compile Include="Recipe_Surgery.cs" />
@ -162,5 +163,10 @@
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Content Include="..\..\..\..\changelogs.txt">
<Link>changelogs.txt</Link>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -404,10 +404,8 @@ namespace RJW_Menstruation
DoSubRow(sublist.GetRect(rowH), key, extension, removeelements);
}
}
if (!removeelements.NullOrEmpty()) foreach (string key in removeelements)
{
extension.hybridInfo.Remove(key);
}
foreach (string key in removeelements)
extension.hybridInfo.Remove(key);
sublist.End();
Widgets.DrawHighlightIfMouseover(rect);

View File

@ -81,13 +81,12 @@ namespace RJW_Menstruation
if (allvaginas != null) return allvaginas;
allvaginas = new HashSet<HediffDef>();
List<HediffDef> allHediffs = DefDatabase<HediffDef>.AllDefsListForReading;
foreach(HediffDef hediffDef in allHediffs)
foreach(HediffDef hediffDef in DefDatabase<HediffDef>.AllDefsListForReading)
{
if (hediffDef.comps.NullOrEmpty()) continue;
foreach (HediffCompProperties comp in hediffDef.comps)
{
if (comp.compClass == typeof(HediffComp_Menstruation) || comp.compClass.IsSubclassOf(typeof(HediffComp_Menstruation)))
if (comp.compClass == typeof(HediffComp_Menstruation) || (comp.compClass?.IsSubclassOf(typeof(HediffComp_Menstruation)) ?? false))
{
allvaginas.Add(hediffDef);
break;

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Manifest>
<identifier>RJW Menstruation</identifier>
<version>1.0.7.3</version>
<version>1.0.7.4</version>
<dependencies>
</dependencies>
<incompatibleWith />

View File

@ -1,3 +1,17 @@
Version 1.0.7.4
- Fix errors when using other mods with bad HediffCompProperties.
- Fix egg appearing to be fertilized in womb display when it is not.
- Fix post-birth recovery being instant or very short.
- Fix womb gizmo error when insect egged.
- Induced ovulators will start with a lower number of eggs, but still enough for a long breeding life. IUDs or sex with poor fertility partners may result in early menopause.
- Pawns on caravans and in transport pods will have their wombs simulated.
- Updated max size areola images by wruf.
- Substantially reduce the speed of nipple variance during milking and respect the max nipple increment setting.
- Possible titles for newborns removed to match RJW 5.1.0.
- Improve compatibility with RJW 5.1.0 for multiple wombs.
- Better handling of estrus for multiple wombs.
- Induced ovulators will end estrus immediately upon reaching luteal if not induced. One that is induced will have their estrus only last as long as an unfertilized egg would.
Version 1.0.7.3
- Fix null reference error upon birth of female pawns.
- Properly display multiple icons for pawns with multiple wombs.