Estrus rework. Properly layer estrus from multiple wombs. Have induced ovulator estrus only last until egg expiration.

This commit is contained in:
lutepickle 2022-09-03 15:40:25 -07:00
parent eda71f70a8
commit 2b5d5443d3
9 changed files with 148 additions and 48 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

@ -87,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;
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>()
{
@ -1063,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;
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()

View File

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Verse;
using Verse.AI;
namespace RJW_Menstruation
{
@ -330,5 +331,19 @@ 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())
{
HediffComp_Menstruation.EstrusLevel current = comp.GetEstrusLevel();
if (current == HediffComp_Menstruation.EstrusLevel.Visible) return HediffComp_Menstruation.EstrusLevel.Visible;
else if (current == HediffComp_Menstruation.EstrusLevel.Concealed) res = HediffComp_Menstruation.EstrusLevel.Concealed;
}
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

@ -81,7 +81,7 @@ namespace RJW_Menstruation
{
icon = comp.GetWombIcon();
}
icon_overay = comp.GetCumIcon();
icon_overay = comp.GetCumIcon();
}
foreach (string s in comp.GetCumsInfo) description += s + "\n";

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" />

View File

@ -1,14 +1,16 @@
Version 1.0.7.4
- Fix errors when using mods with bad HediffCompProperties.
- Fix egg appearing to be fertilized in womb display when it isn't.
- Fix egg appearing to be fertilized in womb display when there is no cum.
- 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 reasonably 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 still be simulated.
- 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.
- Title addition on pregnancy 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 early upon being induced (lasting about until their egg would expire).
Version 1.0.7.3
- Fix null reference error upon birth of female pawns.