Merge branch 'dev'
|
@ -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>
|
||||
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 6 KiB |
BIN
1.3/Textures/Womb/Womb_Implanted_Multiplet_2.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 />
|
||||
|
|
|
@ -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.
|
||||
|
|