Make climacteric/menopause per-womb. Obsolete climacteric phases. Add stat parts for those wombs.

This commit is contained in:
lutepickle 2022-09-05 17:44:23 -07:00
parent 61bf4e188d
commit 3512f55363
14 changed files with 240 additions and 212 deletions

Binary file not shown.

View file

@ -79,19 +79,13 @@
</injuryProps> </injuryProps>
<stages> <stages>
<li> <li>
<statFactors> <label>Obsolete</label>
<SexFrequency>0.01</SexFrequency>
<SexSatisfaction>0.50</SexSatisfaction>
</statFactors>
<capMods>
<li>
<capacity>RJW_Fertility</capacity>
<postFactor>0.00</postFactor>
</li>
</capMods>
</li> </li>
</stages> </stages>
<comps> <comps>
<li Class="HediffCompProperties_Disappears">
<disappearsAfterTicks>0</disappearsAfterTicks>
</li>
</comps> </comps>
</HediffDef> </HediffDef>
@ -113,62 +107,13 @@
</injuryProps> </injuryProps>
<stages> <stages>
<li> <li>
<label>early</label> <label>Obsolete</label>
<statFactors>
<SexFrequency>0.50</SexFrequency>
<SexSatisfaction>0.8</SexSatisfaction>
</statFactors>
<capMods>
<li>
<capacity>RJW_Fertility</capacity>
<postFactor>0.50</postFactor>
</li>
</capMods>
</li>
<li>
<label>middle</label>
<minSeverity>0.2</minSeverity>
<statFactors>
<SexFrequency>0.25</SexFrequency>
<SexSatisfaction>0.7</SexSatisfaction>
</statFactors>
<capMods>
<li>
<capacity>RJW_Fertility</capacity>
<postFactor>0.25</postFactor>
</li>
</capMods>
</li>
<li>
<label>latter</label>
<minSeverity>0.4</minSeverity>
<statFactors>
<SexFrequency>0.10</SexFrequency>
<SexSatisfaction>0.6</SexSatisfaction>
</statFactors>
<capMods>
<li>
<capacity>RJW_Fertility</capacity>
<postFactor>0.10</postFactor>
</li>
</capMods>
</li>
<li>
<label>end</label>
<minSeverity>0.6</minSeverity>
<statFactors>
<SexFrequency>0.05</SexFrequency>
<SexSatisfaction>0.5</SexSatisfaction>
</statFactors>
<capMods>
<li>
<capacity>RJW_Fertility</capacity>
<postFactor>0.01</postFactor>
</li>
</capMods>
</li> </li>
</stages> </stages>
<comps> <comps>
<li Class="HediffCompProperties_Disappears">
<disappearsAfterTicks>0</disappearsAfterTicks>
</li>
</comps> </comps>
</HediffDef> </HediffDef>

View file

@ -7,14 +7,6 @@
<Hediff_MenstrualCramp.stages.1.label>恼人</Hediff_MenstrualCramp.stages.1.label> <Hediff_MenstrualCramp.stages.1.label>恼人</Hediff_MenstrualCramp.stages.1.label>
<Hediff_MenstrualCramp.stages.2.label>疼痛</Hediff_MenstrualCramp.stages.2.label> <Hediff_MenstrualCramp.stages.2.label>疼痛</Hediff_MenstrualCramp.stages.2.label>
<Hediff_MenstrualCramp.stages.3.label>痛苦</Hediff_MenstrualCramp.stages.3.label> <Hediff_MenstrualCramp.stages.3.label>痛苦</Hediff_MenstrualCramp.stages.3.label>
<Hediff_Climacteric.label>更年期</Hediff_Climacteric.label>
<Hediff_Climacteric.description>到了更年期</Hediff_Climacteric.description>
<Hediff_Climacteric.stages.0.label>初期</Hediff_Climacteric.stages.0.label>
<Hediff_Climacteric.stages.1.label>中期</Hediff_Climacteric.stages.1.label>
<Hediff_Climacteric.stages.2.label>后期</Hediff_Climacteric.stages.2.label>
<Hediff_Climacteric.stages.3.label>更年期</Hediff_Climacteric.stages.3.label>
<Hediff_Menopause.label>更年期</Hediff_Menopause.label>
<Hediff_Menopause.description>不孕</Hediff_Menopause.description>

View file

@ -7,14 +7,6 @@
<Hediff_MenstrualCramp.stages.1.label>惱人</Hediff_MenstrualCramp.stages.1.label> <Hediff_MenstrualCramp.stages.1.label>惱人</Hediff_MenstrualCramp.stages.1.label>
<Hediff_MenstrualCramp.stages.2.label>疼痛</Hediff_MenstrualCramp.stages.2.label> <Hediff_MenstrualCramp.stages.2.label>疼痛</Hediff_MenstrualCramp.stages.2.label>
<Hediff_MenstrualCramp.stages.3.label>痛苦</Hediff_MenstrualCramp.stages.3.label> <Hediff_MenstrualCramp.stages.3.label>痛苦</Hediff_MenstrualCramp.stages.3.label>
<Hediff_Climacteric.label>更年期</Hediff_Climacteric.label>
<Hediff_Climacteric.description>到了更年期</Hediff_Climacteric.description>
<Hediff_Climacteric.stages.0.label>初期</Hediff_Climacteric.stages.0.label>
<Hediff_Climacteric.stages.1.label>中期</Hediff_Climacteric.stages.1.label>
<Hediff_Climacteric.stages.2.label>後期</Hediff_Climacteric.stages.2.label>
<Hediff_Climacteric.stages.3.label>更年期</Hediff_Climacteric.stages.3.label>
<Hediff_Menopause.label>更年期</Hediff_Menopause.label>
<Hediff_Menopause.description>不孕</Hediff_Menopause.description>

View file

@ -12,6 +12,7 @@
<Stage_Recover>Recovering from birth</Stage_Recover> <Stage_Recover>Recovering from birth</Stage_Recover>
<Stage_None>None</Stage_None> <Stage_None>None</Stage_None>
<Stage_Climacteric>Climacteric</Stage_Climacteric> <Stage_Climacteric>Climacteric</Stage_Climacteric>
<Stage_Menopause>Menopause</Stage_Menopause>
<Stage_Anestrus>Anestrus</Stage_Anestrus> <Stage_Anestrus>Anestrus</Stage_Anestrus>
<Stage_Follicular_Desc>The ovaries are preparing to release an egg. Ovulation will occur at the end of this phase.</Stage_Follicular_Desc> <Stage_Follicular_Desc>The ovaries are preparing to release an egg. Ovulation will occur at the end of this phase.</Stage_Follicular_Desc>
<Stage_Follicular_Induced_Desc>The ovaries are preparing to release an egg. Ovulation will occur if semen enters the womb.</Stage_Follicular_Induced_Desc> <Stage_Follicular_Induced_Desc>The ovaries are preparing to release an egg. Ovulation will occur if semen enters the womb.</Stage_Follicular_Induced_Desc>
@ -22,6 +23,7 @@
<Stage_Recover_Desc>The womb is recovering from its recent pregnancy.</Stage_Recover_Desc> <Stage_Recover_Desc>The womb is recovering from its recent pregnancy.</Stage_Recover_Desc>
<Stage_None_Desc>The womb is not fertile and cannot become pregnant.</Stage_None_Desc> <Stage_None_Desc>The womb is not fertile and cannot become pregnant.</Stage_None_Desc>
<Stage_Climacteric_Desc>The ovaries have neared exhaustion and the menstrual cycle has become irregular.</Stage_Climacteric_Desc> <Stage_Climacteric_Desc>The ovaries have neared exhaustion and the menstrual cycle has become irregular.</Stage_Climacteric_Desc>
<Stage_Menopause_Desc>The ovaries have been exhausted and the womb can no longer produce eggs.</Stage_Menopause_Desc>
<Stage_Anestrus_Desc>The womb is out of breeding season. The cycle will resume once conditions are met.</Stage_Anestrus_Desc> <Stage_Anestrus_Desc>The womb is out of breeding season. The cycle will resume once conditions are met.</Stage_Anestrus_Desc>
<Button_HealthTab>Status</Button_HealthTab> <Button_HealthTab>Status</Button_HealthTab>
<Button_MilkTooltip>Lactate self</Button_MilkTooltip> <Button_MilkTooltip>Lactate self</Button_MilkTooltip>

View file

@ -6,14 +6,6 @@
<Hediff_MenstrualCramp.stages.1.label>짜증남</Hediff_MenstrualCramp.stages.1.label> <Hediff_MenstrualCramp.stages.1.label>짜증남</Hediff_MenstrualCramp.stages.1.label>
<Hediff_MenstrualCramp.stages.2.label>아픔</Hediff_MenstrualCramp.stages.2.label> <Hediff_MenstrualCramp.stages.2.label>아픔</Hediff_MenstrualCramp.stages.2.label>
<Hediff_MenstrualCramp.stages.3.label>고통스러움</Hediff_MenstrualCramp.stages.3.label> <Hediff_MenstrualCramp.stages.3.label>고통스러움</Hediff_MenstrualCramp.stages.3.label>
<Hediff_Climacteric.label>갱년기</Hediff_Climacteric.label>
<Hediff_Climacteric.description>갱년기입니다.</Hediff_Climacteric.description>
<Hediff_Climacteric.stages.0.label>초기</Hediff_Climacteric.stages.0.label>
<Hediff_Climacteric.stages.1.label>중기</Hediff_Climacteric.stages.1.label>
<Hediff_Climacteric.stages.2.label>후기</Hediff_Climacteric.stages.2.label>
<Hediff_Climacteric.stages.3.label>폐경</Hediff_Climacteric.stages.3.label>
<Hediff_Menopause.label>폐경</Hediff_Menopause.label>
<Hediff_Menopause.description>임신할수 없습니다.</Hediff_Menopause.description>
<Hediff_Estrus.label>발정기</Hediff_Estrus.label> <Hediff_Estrus.label>발정기</Hediff_Estrus.label>
<Hediff_Estrus.description>발정기입니다.</Hediff_Estrus.description> <Hediff_Estrus.description>발정기입니다.</Hediff_Estrus.description>
<Hediff_Estrus_Concealed.label>발정기(숨김)</Hediff_Estrus_Concealed.label> <Hediff_Estrus_Concealed.label>발정기(숨김)</Hediff_Estrus_Concealed.label>

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<Patch>
<Operation Class="PatchOperationAdd">
<xpath>/Defs/StatDef[defName="SexFrequency"]/parts</xpath>
<value>
<li Class="RJW_Menstruation.StatPart_Climacteric_SexFrequency"/>
<li Class="RJW_Menstruation.StatPart_Menopause_SexFrequency"/>
</value>
</Operation>
<Operation Class="PatchOperationAdd">
<xpath>/Defs/StatDef[defName="SexSatisfaction"]/parts</xpath>
<value>
<li Class="RJW_Menstruation.StatPart_Climacteric_SexSatisfaction"/>
<li Class="RJW_Menstruation.StatPart_Menopause_SexSatisfaction"/>
</value>
</Operation>
</Patch>

View file

@ -48,10 +48,10 @@ namespace RJW_Menstruation
return Mathf.CeilToInt((Pawn.relations?.ChildrenCount ?? 0) / Configurations.ImplantationChanceDefault); return Mathf.CeilToInt((Pawn.relations?.ChildrenCount ?? 0) / Configurations.ImplantationChanceDefault);
} }
protected override void GoOvulatoryStage(bool climacteric) protected override void GoOvulatoryStage()
{ {
estrusflag = false; estrusflag = false;
GoNextStage(climacteric ? Stage.ClimactericLuteal : Stage.Luteal); GoNextStage(Stage.Luteal);
} }
protected override void AfterCumIn(Pawn cummer) protected override void AfterCumIn(Pawn cummer)

View file

@ -85,9 +85,9 @@ namespace RJW_Menstruation
Recover, Recover,
None, None,
Young, Young,
ClimactericFollicular, ClimactericFollicular, // obsolete
ClimactericLuteal, ClimactericLuteal, // obsolete
ClimactericBleeding, ClimactericBleeding, // obsolete
Anestrus Anestrus
} }
@ -125,6 +125,30 @@ namespace RJW_Menstruation
protected float? originvagsize = null; protected float? originvagsize = null;
protected Hediff_BasePregnancy pregnancy = null; protected Hediff_BasePregnancy pregnancy = null;
private static readonly SimpleCurve SexFrequencyCurve = new SimpleCurve()
{
new CurvePoint(0.4f,0.05f),
new CurvePoint(0.6f,0.1f),
new CurvePoint(0.8f,0.25f),
new CurvePoint(1.0f,0.5f)
};
private static readonly SimpleCurve SexSatisfactionCurve = new SimpleCurve()
{
new CurvePoint(0.4f,0.5f),
new CurvePoint(0.6f,0.6f),
new CurvePoint(0.8f,0.7f),
new CurvePoint(1.0f,0.8f)
};
private static readonly SimpleCurve FertilityCurve = new SimpleCurve()
{
new CurvePoint(0.4f,0.01f),
new CurvePoint(0.6f,0.1f),
new CurvePoint(0.8f,0.25f),
new CurvePoint(1.0f,0.5f)
};
public Hediff_BasePregnancy Pregnancy { public Hediff_BasePregnancy Pregnancy {
get get
{ {
@ -163,6 +187,42 @@ namespace RJW_Menstruation
} }
} }
// >= 1: Normal cycles
// 1 - 0: Climacteric
// <= 0: Menopause
public float EggHealth
{
get
{
if (!Configurations.EnableMenopause) return Mathf.Min(1.0f, ovarypower / OvaryPowerThreshold);
else return ovarypower / OvaryPowerThreshold;
}
}
public float SexFrequencyModifier()
{
float eggHealth = EggHealth;
if (eggHealth >= 1) return 1.0f;
else if (eggHealth <= 0) return 0.01f;
else return SexFrequencyCurve.Evaluate(eggHealth);
}
public float SexSatisfactionModifier()
{
float eggHealth = EggHealth;
if (eggHealth >= 1) return 1.0f;
else if (eggHealth <= 0) return 0.5f;
else return SexSatisfactionCurve.Evaluate(eggHealth);
}
public float FertilityModifier()
{
float eggHealth = EggHealth;
if (eggHealth >= 1) return 1.0f;
else if (eggHealth <= 0) return 0.0f;
else return FertilityCurve.Evaluate(eggHealth);
}
public float TotalCum public float TotalCum
{ {
get get
@ -210,7 +270,7 @@ namespace RJW_Menstruation
{ {
float factor = 1.0f; float factor = 1.0f;
if (Pawn.Has(Quirk.Breeder)) factor = 10.0f; if (Pawn.Has(Quirk.Breeder)) factor = 10.0f;
return Pawn.health.capacities.GetLevel(xxx.reproduction) * Props.baseImplantationChanceFactor * factor; return Pawn.health.capacities.GetLevel(xxx.reproduction) * Props.baseImplantationChanceFactor * FertilityModifier() * factor;
} }
} }
public IEnumerable<string> GetCumsInfo public IEnumerable<string> GetCumsInfo
@ -268,20 +328,21 @@ namespace RJW_Menstruation
switch (CurrentVisibleStage) switch (CurrentVisibleStage)
{ {
case Stage.Follicular: case Stage.Follicular:
return Translations.Stage_Follicular; return Translations.Stage_Follicular + (EggHealth < 1f ? Translations.Stage_Climacteric : "");
case Stage.Ovulatory: case Stage.Ovulatory:
return Translations.Stage_Ovulatory; return Translations.Stage_Ovulatory + (EggHealth < 1f ? Translations.Stage_Climacteric : "");
case Stage.Luteal: case Stage.Luteal:
return Translations.Stage_Luteal; return Translations.Stage_Luteal + (EggHealth < 1f ? Translations.Stage_Climacteric : "");
case Stage.Bleeding: case Stage.Bleeding:
return Translations.Stage_Bleeding; return Translations.Stage_Bleeding + (EggHealth < 1f ? Translations.Stage_Climacteric : "");
case Stage.Pregnant: case Stage.Pregnant:
return Translations.Stage_Pregnant; return Translations.Stage_Pregnant;
case Stage.Recover: case Stage.Recover:
return Translations.Stage_Recover; return Translations.Stage_Recover;
case Stage.None: case Stage.None:
case Stage.Young: case Stage.Young:
return Translations.Stage_None; if (EggHealth <= 0f) return Translations.Stage_Menopause;
else return Translations.Stage_None;
case Stage.ClimactericFollicular: case Stage.ClimactericFollicular:
return Translations.Stage_Follicular + " - " + Translations.Stage_Climacteric; return Translations.Stage_Follicular + " - " + Translations.Stage_Climacteric;
case Stage.ClimactericLuteal: case Stage.ClimactericLuteal:
@ -303,20 +364,21 @@ namespace RJW_Menstruation
switch (CurrentVisibleStage) switch (CurrentVisibleStage)
{ {
case Stage.Follicular: case Stage.Follicular:
return Translations.Stage_Follicular_Desc; return Translations.Stage_Follicular_Desc + (EggHealth < 1f ? Translations.Stage_Climacteric_Desc : "");
case Stage.Ovulatory: case Stage.Ovulatory:
return Translations.Stage_Ovulatory_Desc; return Translations.Stage_Ovulatory_Desc + (EggHealth < 1f ? Translations.Stage_Climacteric_Desc : "");
case Stage.Luteal: case Stage.Luteal:
return Translations.Stage_Luteal_Desc; return Translations.Stage_Luteal_Desc + (EggHealth < 1f ? Translations.Stage_Climacteric_Desc : "");
case Stage.Bleeding: case Stage.Bleeding:
return Translations.Stage_Bleeding_Desc; return Translations.Stage_Bleeding_Desc + (EggHealth < 1f ? Translations.Stage_Climacteric_Desc : "");
case Stage.Pregnant: case Stage.Pregnant:
return Translations.Stage_Pregnant_Desc; return Translations.Stage_Pregnant_Desc;
case Stage.Recover: case Stage.Recover:
return Translations.Stage_Recover_Desc; return Translations.Stage_Recover_Desc;
case Stage.None: case Stage.None:
case Stage.Young: case Stage.Young:
return Translations.Stage_None_Desc; if (EggHealth <= 0f) return Translations.Stage_Menopause_Desc;
else return Translations.Stage_None_Desc;
case Stage.ClimactericFollicular: case Stage.ClimactericFollicular:
return Translations.Stage_Follicular_Desc + " " + Translations.Stage_Climacteric_Desc; return Translations.Stage_Follicular_Desc + " " + Translations.Stage_Climacteric_Desc;
case Stage.ClimactericLuteal: case Stage.ClimactericLuteal:
@ -566,20 +628,25 @@ namespace RJW_Menstruation
} }
CumOut(); CumOut();
if (pregnancy == null && Pawn.health.capacities.GetLevel(xxx.reproduction) <= 0) curStage = Stage.Young;
if (curStage == Stage.ClimactericFollicular) curStage = Stage.Follicular;
else if (curStage == Stage.ClimactericLuteal) curStage = Stage.Luteal;
else if (curStage == Stage.ClimactericBleeding) curStage = Stage.Bleeding;
if (pregnancy == null && (Pawn.health.capacities.GetLevel(xxx.reproduction) <= 0) || EggHealth <= 0) curStage = Stage.Young;
switch (curStage) switch (curStage)
{ {
case Stage.Follicular: case Stage.Follicular:
FollicularAction(false); FollicularAction();
break; break;
case Stage.Ovulatory: case Stage.Ovulatory:
OvulatoryAction(); OvulatoryAction();
break; break;
case Stage.Luteal: case Stage.Luteal:
LutealAction(false); LutealAction();
break; break;
case Stage.Bleeding: case Stage.Bleeding:
BleedingAction(false); BleedingAction();
break; break;
case Stage.Pregnant: case Stage.Pregnant:
PregnantAction(); PregnantAction();
@ -592,15 +659,6 @@ namespace RJW_Menstruation
case Stage.Young: case Stage.Young:
YoungAction(); YoungAction();
break; break;
case Stage.ClimactericFollicular:
FollicularAction(true);
break;
case Stage.ClimactericLuteal:
LutealAction(true);
break;
case Stage.ClimactericBleeding:
BleedingAction(true);
break;
case Stage.Anestrus: case Stage.Anestrus:
AnestrusAction(); AnestrusAction();
break; break;
@ -1024,36 +1082,19 @@ namespace RJW_Menstruation
protected void InitOvary() protected void InitOvary()
{ {
if (!Configurations.EnableMenopause) if (ovarypower < -50000)
{
RemoveClimactericEffect();
}
else if (ovarypower < -50000)
{ {
ovarypower = GetOvaryPowerByAge(); ovarypower = GetOvaryPowerByAge();
if (ovarypower < 1) if (ovarypower < 1)
{ {
Hediff hediff = HediffMaker.MakeHediff(VariousDefOf.Hediff_Menopause, Pawn);
hediff.Severity = 0.2f;
Pawn.health.AddHediff(hediff, Genital_Helper.get_genitalsBPR(Pawn));
curStage = Stage.Young; curStage = Stage.Young;
} }
else if (ovarypower < OvaryPowerThreshold)
{
Hediff hediff = HediffMaker.MakeHediff(VariousDefOf.Hediff_Climacteric, Pawn);
hediff.Severity = Mathf.InverseLerp(OvaryPowerThreshold, 0, ovarypower);
Pawn.health.AddHediff(hediff, Genital_Helper.get_genitalsBPR(Pawn));
}
} }
} }
public void RecoverOvary(float multiply = 1.2f) public void RecoverOvary(float multiply = 1.2f)
{ {
ovarypower = Math.Max(0, (int)(ovarypower * multiply)); ovarypower = Math.Max(0, (int)(ovarypower * multiply));
if (ovarypower >= OvaryPowerThreshold)
{
RemoveClimactericEffect();
}
} }
@ -1327,14 +1368,9 @@ namespace RJW_Menstruation
Pawn.health.AddHediff(hediff, Genital_Helper.get_genitalsBPR(Pawn)); Pawn.health.AddHediff(hediff, Genital_Helper.get_genitalsBPR(Pawn));
} }
protected virtual void FollicularAction(bool climacteric) protected virtual void FollicularAction()
{ {
if (climacteric && !Configurations.EnableMenopause) if (!IsBreedingSeason())
{
RemoveClimactericEffect();
StayCurrentStage();
}
else if (!IsBreedingSeason())
{ {
estrusflag = false; estrusflag = false;
GoNextStage(Stage.Anestrus); GoNextStage(Stage.Anestrus);
@ -1342,12 +1378,7 @@ namespace RJW_Menstruation
} }
else if (curStageHrs >= currentIntervalHours) else if (curStageHrs >= currentIntervalHours)
{ {
GoOvulatoryStage(climacteric); GoOvulatoryStage();
}
else if (climacteric && ovarypower < OvaryPowerThreshold / 3 && Rand.Range(0.0f, 1.0f) < 0.2f) //skips ovulatory
{
estrusflag = false;
GoNextStage(Stage.ClimactericLuteal);
} }
else else
{ {
@ -1388,47 +1419,30 @@ namespace RJW_Menstruation
i++; i++;
} while (i < (int)eggnum); } while (i < (int)eggnum);
eggstack = 0; eggstack = 0;
if (Configurations.EnableMenopause && ovarypower < 1) if (EggHealth <= 0)
{ {
eggs.Clear(); eggs.Clear();
Hediff hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_Climacteric);
if (hediff != null) Pawn.health.RemoveHediff(hediff);
hediff = HediffMaker.MakeHediff(VariousDefOf.Hediff_Menopause, Pawn);
hediff.Severity = 0.2f;
Pawn.health.AddHediff(hediff, Genital_Helper.get_genitalsBPR(Pawn));
ovarypower = 0; ovarypower = 0;
GoNextStage(Stage.Young); GoNextStage(Stage.Young);
} }
else if (Configurations.EnableMenopause && ovarypower < OvaryPowerThreshold)
{
Hediff hediff = HediffMaker.MakeHediff(VariousDefOf.Hediff_Climacteric, Pawn);
hediff.Severity = Mathf.InverseLerp(OvaryPowerThreshold, 0, ovarypower);
Pawn.health.AddHediff(hediff, Genital_Helper.get_genitalsBPR(Pawn));
GoNextStage(Stage.ClimactericLuteal);
}
else else
{ {
GoNextStage(Stage.Luteal); GoNextStage(Stage.Luteal);
} }
} }
protected virtual void LutealAction(bool climacteric) protected virtual void LutealAction()
{ {
if (climacteric && !Configurations.EnableMenopause) if (curStageHrs > currentIntervalHours)
{
RemoveClimactericEffect();
StayCurrentStage();
}
else if (curStageHrs > currentIntervalHours)
{ {
eggs.Clear(); eggs.Clear();
if (Props.bleedingIntervalDays == 0) if (Props.bleedingIntervalDays == 0)
{ {
GoNextStage(climacteric ? Stage.ClimactericFollicular : Stage.Follicular); GoNextStage(Stage.Follicular);
} }
else if (climacteric && (ovarypower < OvaryPowerThreshold / 4 || (ovarypower < OvaryPowerThreshold / 3 && Rand.Range(0.0f, 1.0f) < 0.3f))) //skips bleeding else if (EggHealth < 1f / 4f || (EggHealth < 1f / 3f && Rand.Range(0.0f, 1.0f) < 0.3f)) //skips bleeding
{ {
GoNextStage(Stage.ClimactericFollicular); GoNextStage(Stage.Follicular);
} }
else else
{ {
@ -1436,7 +1450,7 @@ namespace RJW_Menstruation
{ {
AddCrampPain(); AddCrampPain();
} }
GoNextStage(climacteric ? Stage.ClimactericBleeding : Stage.Bleeding); GoNextStage(Stage.Bleeding);
} }
} }
else if (!eggs.NullOrEmpty()) else if (!eggs.NullOrEmpty())
@ -1461,24 +1475,19 @@ namespace RJW_Menstruation
} }
protected virtual void BleedingAction(bool climacteric) protected virtual void BleedingAction()
{ {
if (climacteric && !Configurations.EnableMenopause) if (curStageHrs >= currentIntervalHours)
{
RemoveClimactericEffect();
StayCurrentStage();
}
else if (curStageHrs >= currentIntervalHours)
{ {
Hediff hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_MenstrualCramp); Hediff hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_MenstrualCramp);
if (hediff != null) Pawn.health.RemoveHediff(hediff); if (hediff != null) Pawn.health.RemoveHediff(hediff);
int totalFollicularHours = PeriodRandomizer(climacteric ? Stage.ClimactericFollicular : Stage.Follicular, climacteric ? 6.0f : 1.0f); // The total amount of time for both bleeding and follicular int totalFollicularHours = PeriodRandomizer(Stage.Follicular); // The total amount of time for both bleeding and follicular
if (totalFollicularHours <= currentIntervalHours) // We've bled for so long that we completely missed the follicular phase if (totalFollicularHours <= currentIntervalHours) // We've bled for so long that we completely missed the follicular phase
GoOvulatoryStage(climacteric); GoOvulatoryStage();
else else
{ {
currentIntervalHours = totalFollicularHours - currentIntervalHours; // I.e., the remaining follicular hours equals the total minus the bleeding hours elapsed currentIntervalHours = totalFollicularHours - currentIntervalHours; // I.e., the remaining follicular hours equals the total minus the bleeding hours elapsed
GoNextStage(climacteric ? Stage.ClimactericFollicular : Stage.Follicular, false); GoNextStage(Stage.Follicular, false);
} }
} }
else else
@ -1514,17 +1523,13 @@ namespace RJW_Menstruation
{ {
if (curStageHrs >= currentIntervalHours) if (curStageHrs >= currentIntervalHours)
{ {
if (Pawn.health.capacities.GetLevel(xxx.reproduction) == 0) if (Pawn.health.capacities.GetLevel(xxx.reproduction) == 0 || EggHealth <= 0)
{ {
GoNextStage(Stage.Young); GoNextStage(Stage.Young);
} }
else if (!IsBreedingSeason()) else if (!IsBreedingSeason())
{ {
GoNextStage(Stage.Anestrus); GoNextStage(Stage.Anestrus);
}
else if (Configurations.EnableMenopause && ovarypower < OvaryPowerThreshold)
{
GoNextStage(Stage.ClimactericFollicular);
} }
else else
{ {
@ -1540,11 +1545,7 @@ namespace RJW_Menstruation
protected virtual void YoungAction() protected virtual void YoungAction()
{ {
if (!Configurations.EnableMenopause && ovarypower < 0 && ovarypower > -10000) if (Pawn.health.capacities.GetLevel(xxx.reproduction) <= 0 || EggHealth <= 0)
{
RemoveClimactericEffect();
}
if (Pawn.health.capacities.GetLevel(xxx.reproduction) <= 0)
{ {
StayCurrentStageConst(Stage.Young); StayCurrentStageConst(Stage.Young);
} }
@ -1634,14 +1635,18 @@ namespace RJW_Menstruation
protected void GoNextStage(Stage nextstage, bool calculateHours = true) protected void GoNextStage(Stage nextstage, bool calculateHours = true)
{ {
curStageHrs = 0; curStageHrs = 0;
float variabilityFactor = nextstage == Stage.ClimactericFollicular || nextstage == Stage.ClimactericLuteal || nextstage == Stage.ClimactericBleeding ? 6.0f : 1.0f; if (calculateHours) currentIntervalHours = PeriodRandomizer(nextstage);
if (calculateHours) currentIntervalHours = PeriodRandomizer(nextstage, variabilityFactor);
curStage = nextstage; curStage = nextstage;
} }
protected virtual void GoOvulatoryStage(bool climacteric) protected virtual void GoOvulatoryStage()
{ {
GoNextStage(Stage.Ovulatory); if (EggHealth < 1.0f / 3.0f && Rand.Range(0.0f, 1.0f) < 0.2f) // Skip ovulation if deep into climacteric
{
estrusflag = false;
GoNextStage(Stage.Luteal);
}
else GoNextStage(Stage.Ovulatory);
} }
//stage can be interrupted in other reasons //stage can be interrupted in other reasons
@ -1656,30 +1661,19 @@ namespace RJW_Menstruation
protected void GoFollicularOrBleeding() protected void GoFollicularOrBleeding()
{ {
bool climacteric = Configurations.EnableMenopause && ovarypower < OvaryPowerThreshold;
if (Props.bleedingIntervalDays == 0) if (Props.bleedingIntervalDays == 0)
{ {
GoNextStage(climacteric ? Stage.ClimactericFollicular : Stage.Follicular); GoNextStage(Stage.Follicular);
} }
else else
{ {
GoNextStage(climacteric ? Stage.ClimactericBleeding : Stage.Bleeding); GoNextStage(Stage.Bleeding);
} }
} }
protected void RemoveClimactericEffect() protected int PeriodRandomizer(Stage stage)
{
Hediff hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_Climacteric);
if (hediff != null) Pawn.health.RemoveHediff(hediff);
hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_Menopause);
if (hediff != null) Pawn.health.RemoveHediff(hediff);
if (curStage == Stage.ClimactericBleeding) curStage = Stage.Bleeding;
else if (curStage == Stage.ClimactericFollicular) curStage = Stage.Follicular;
else if (curStage == Stage.ClimactericLuteal) curStage = Stage.Luteal;
}
protected int PeriodRandomizer(Stage stage, float variabilityFactor = 1.0f)
{ {
float variabilityFactor = (EggHealth < 1.0f) ? 6.0f : 1.0f;
// Most cycle lengthening or shortening occurs in the follicular phase, so weight towards that // Most cycle lengthening or shortening occurs in the follicular phase, so weight towards that
switch (stage) switch (stage)
{ {

View file

@ -69,6 +69,7 @@
<Compile Include="IngestionOutcomeDoers.cs" /> <Compile Include="IngestionOutcomeDoers.cs" />
<Compile Include="Patch\GC_Patch.cs" /> <Compile Include="Patch\GC_Patch.cs" />
<Compile Include="Recipe_Surgery.cs" /> <Compile Include="Recipe_Surgery.cs" />
<Compile Include="StatParts.cs" />
<Compile Include="UI\Dialog_HybridCustom.cs" /> <Compile Include="UI\Dialog_HybridCustom.cs" />
<Compile Include="UI\Dialog_WombStatus.cs" /> <Compile Include="UI\Dialog_WombStatus.cs" />
<Compile Include="FilthMaker_Colored.cs" /> <Compile Include="FilthMaker_Colored.cs" />

View file

@ -0,0 +1,90 @@
using RimWorld;
using System.Collections.Generic;
using System.Linq;
using Verse;
namespace RJW_Menstruation
{
public abstract class StatPart_Menstruation_Effects : StatPart
{
public override void TransformValue(StatRequest req, ref float val)
{
if (req.Thing is Pawn pawn && ApplicableComps(pawn).Any())
val *= GetFactor(pawn);
}
protected abstract IEnumerable<HediffComp_Menstruation> ApplicableComps(Pawn pawn);
protected IEnumerable<HediffComp_Menstruation> AllComps(Pawn pawn)
{
return pawn.GetMenstruationComps();
}
protected abstract float GetFactor(Pawn pawn);
}
public abstract class StatPart_Climacteric_Effects : StatPart_Menstruation_Effects
{
public override string ExplanationPart(StatRequest req)
{
if (req.Thing is Pawn pawn && ApplicableComps(pawn).Any())
{
return $"{Translations.Stage_Climacteric.CapitalizeFirst()}: x{GetFactor(pawn).ToStringPercent()}";
}
else return null;
}
protected override IEnumerable<HediffComp_Menstruation> ApplicableComps(Pawn pawn)
{
return pawn.GetMenstruationComps().Where(comp => comp.EggHealth < 1f && comp.EggHealth > 0f);
}
}
public abstract class StatPart_Menopause_Effects : StatPart_Menstruation_Effects
{
public override string ExplanationPart(StatRequest req)
{
if (req.Thing is Pawn pawn && ApplicableComps(pawn).Any())
{
return $"{Translations.Stage_Menopause.CapitalizeFirst()}: x{GetFactor(pawn).ToStringPercent()}";
}
else return null;
}
protected override IEnumerable<HediffComp_Menstruation> ApplicableComps(Pawn pawn)
{
return pawn.GetMenstruationComps().Where(comp => comp.EggHealth <= 0f);
}
}
public class StatPart_Climacteric_SexFrequency : StatPart_Climacteric_Effects
{
protected override float GetFactor(Pawn pawn)
{
return AllComps(pawn).Average(comp => comp.SexFrequencyModifier());
}
}
public class StatPart_Climacteric_SexSatisfaction : StatPart_Climacteric_Effects
{
protected override float GetFactor(Pawn pawn)
{
return AllComps(pawn).Average(comp => comp.SexSatisfactionModifier());
}
}
public class StatPart_Menopause_SexFrequency : StatPart_Menopause_Effects
{
protected override float GetFactor(Pawn pawn)
{
return AllComps(pawn).Average(comp => comp.SexFrequencyModifier());
}
}
public class StatPart_Menopause_SexSatisfaction : StatPart_Menopause_Effects
{
protected override float GetFactor(Pawn pawn)
{
return AllComps(pawn).Average(comp => comp.SexSatisfactionModifier());
}
}
}

View file

@ -15,6 +15,7 @@ namespace RJW_Menstruation
public static readonly string Stage_Recover = "Stage_Recover".Translate(); public static readonly string Stage_Recover = "Stage_Recover".Translate();
public static readonly string Stage_None = "Stage_None".Translate(); public static readonly string Stage_None = "Stage_None".Translate();
public static readonly string Stage_Climacteric = "Stage_Climacteric".Translate(); public static readonly string Stage_Climacteric = "Stage_Climacteric".Translate();
public static readonly string Stage_Menopause = "Stage_Menopause".Translate();
public static readonly string Stage_Anestrus = "Stage_Anestrus".Translate(); public static readonly string Stage_Anestrus = "Stage_Anestrus".Translate();
public static readonly string Stage_Follicular_Desc = "Stage_Follicular_Desc".Translate(); public static readonly string Stage_Follicular_Desc = "Stage_Follicular_Desc".Translate();
public static readonly string Stage_Follicular_Induced_Desc = "Stage_Follicular_Induced_Desc".Translate(); public static readonly string Stage_Follicular_Induced_Desc = "Stage_Follicular_Induced_Desc".Translate();
@ -24,6 +25,7 @@ namespace RJW_Menstruation
public static readonly string Stage_Pregnant_Desc = "Stage_Pregnant_Desc".Translate(); public static readonly string Stage_Pregnant_Desc = "Stage_Pregnant_Desc".Translate();
public static readonly string Stage_Recover_Desc = "Stage_Recover_Desc".Translate(); public static readonly string Stage_Recover_Desc = "Stage_Recover_Desc".Translate();
public static readonly string Stage_None_Desc = "Stage_None_Desc".Translate(); public static readonly string Stage_None_Desc = "Stage_None_Desc".Translate();
public static readonly string Stage_Menopause_Desc = "Stage_Menopause_Desc".Translate();
public static readonly string Stage_Climacteric_Desc = "Stage_Climacteric_Desc".Translate(); public static readonly string Stage_Climacteric_Desc = "Stage_Climacteric_Desc".Translate();
public static readonly string Stage_Anestrus_Desc = "Stage_Anestrus_Desc".Translate(); public static readonly string Stage_Anestrus_Desc = "Stage_Anestrus_Desc".Translate();
public static readonly string Button_HealthTab = "Button_HealthTab".Translate(); public static readonly string Button_HealthTab = "Button_HealthTab".Translate();

View file

@ -17,8 +17,6 @@ namespace RJW_Menstruation
public static readonly ThingDef FilthMixture = DefDatabase<ThingDef>.GetNamed("FilthMixture"); public static readonly ThingDef FilthMixture = DefDatabase<ThingDef>.GetNamed("FilthMixture");
public static readonly HediffDef RJW_IUD = DefDatabase<HediffDef>.GetNamed("RJW_IUD"); public static readonly HediffDef RJW_IUD = DefDatabase<HediffDef>.GetNamed("RJW_IUD");
public static readonly HediffDef Hediff_MenstrualCramp = DefDatabase<HediffDef>.GetNamed("Hediff_MenstrualCramp"); public static readonly HediffDef Hediff_MenstrualCramp = DefDatabase<HediffDef>.GetNamed("Hediff_MenstrualCramp");
public static readonly HediffDef Hediff_Climacteric = DefDatabase<HediffDef>.GetNamed("Hediff_Climacteric");
public static readonly HediffDef Hediff_Menopause = DefDatabase<HediffDef>.GetNamed("Hediff_Menopause");
public static readonly HediffDef Hediff_Estrus = DefDatabase<HediffDef>.GetNamed("Hediff_Estrus"); public static readonly HediffDef Hediff_Estrus = DefDatabase<HediffDef>.GetNamed("Hediff_Estrus");
public static readonly HediffDef Hediff_Estrus_Concealed = DefDatabase<HediffDef>.GetNamed("Hediff_Estrus_Concealed"); public static readonly HediffDef Hediff_Estrus_Concealed = DefDatabase<HediffDef>.GetNamed("Hediff_Estrus_Concealed");
public static readonly HediffDef Hediff_ASA = DefDatabase<HediffDef>.GetNamed("Hediff_ASA"); public static readonly HediffDef Hediff_ASA = DefDatabase<HediffDef>.GetNamed("Hediff_ASA");

View file

@ -1,4 +1,5 @@
Version 1.0.7.5 Version 1.0.7.5
- Climacteric and menopause are now per-womb. Their effects on sex drive and satisfaction will be averaged.
Version 1.0.7.4 Version 1.0.7.4
- Fix errors when using other mods with bad HediffCompProperties. - Fix errors when using other mods with bad HediffCompProperties.