Merge 1.0.6.5

This commit is contained in:
lutepickle 2022-06-05 07:48:17 -07:00
commit 2367091ede
21 changed files with 461 additions and 241 deletions

Binary file not shown.

View file

@ -4,7 +4,7 @@
<ThingDef ParentName="MakeableDrugPillBase">
<defName>OvaryRegenerationPill</defName>
<label>Ovary regeneration pill</label>
<description>Recovers an ovary's health, restoring some quantity of eggs.&#10;Less effective on ovaries with few eggs remaining.&#10;Cannot recover menopause.</description>
<description>Recovers the ovaries' health, restoring some quantity of eggs.&#10;Less effective on ovaries with few eggs remaining.&#10;Cannot recover menopause.</description>
<graphicData>
<texPath>Things/Item/ORPill</texPath>
<graphicClass>Graphic_StackCount</graphicClass>
@ -139,7 +139,7 @@
<ThingDef ParentName="MakeableDrugPillBase">
<defName>Cyclosporine</defName>
<label>cyclosporine</label>
<description>An immunosuppressant.&#10;Can cure antisperm antibody, but harms the body's ability to fight off infection and disease for 24 hours.</description>
<description>An immunosuppressant.&#10;Can cure antisperm antibody, but reduces the body's ability to fight off infection and disease for 24 hours.</description>
<graphicData>
<texPath>Things/Item/Cyclosporine</texPath>
<graphicClass>Graphic_StackCount</graphicClass>

View file

@ -65,7 +65,7 @@
<defName>Hediff_Menopause</defName>
<label>Menopause</label>
<labelNoun>menopause</labelNoun>
<description>A condition caused by exhaustion of the ovaries' eggs. Without eggs, the womb can no longer produce children.</description>
<description>A condition caused by exhaustion of the ovaries' eggs. The womb can no longer produce children.</description>
<labelNounPretty>{0} has entered menopause</labelNounPretty>
<defaultLabelColor>(0.70,0.70,0.00)</defaultLabelColor>
<isBad>false</isBad>
@ -100,7 +100,7 @@
<defName>Hediff_Climacteric</defName>
<label>Climacteric</label>
<labelNoun>climacteric</labelNoun>
<description>The ovaries have produced their final eggs. Menopause will soon occur.</description>
<description>Ovulation has become irregular as the ovaries approach exhaustion. Menopause will soon occur.</description>
<defaultLabelColor>(0.70,0.70,0.00)</defaultLabelColor>
<isBad>false</isBad>
<tendable>false</tendable>
@ -178,7 +178,7 @@
<defName>Hediff_Estrus</defName>
<label>Estrus</label>
<labelNoun>estrus</labelNoun>
<description>A condition caused by a womb entering its most fertile phase of the menstrual cycle. Sexual arousal and desire increase dramatically as the body yearns to become pregnant.&#10;Increased chance of vaginal sex occurring and potentially lower standards in mate selection.</description>
<description>A condition caused by a womb entering the most fertile phase of its menstrual cycle. Sexual arousal and desire increase dramatically as the body yearns to become pregnant.&#10;Increased chance of vaginal sex occurring and potentially lower standards in mate selection.</description>
<defaultLabelColor>(1.00,0.60,0.75)</defaultLabelColor>
<isBad>false</isBad>
<tendable>false</tendable>

View file

@ -17,67 +17,16 @@
</ThoughtDef>
<ThoughtDef>
<defName>CameInsideF</defName>
<defName>HaterCameInsideM</defName>
<thoughtClass>Thought_MemorySocial</thoughtClass>
<durationDays>7.0</durationDays>
<durationDays>1.0</durationDays>
<stackLimit>5</stackLimit>
<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stackedEffectMultiplier>0.4</stackedEffectMultiplier>
<stages>
<li>
<label>{0} came inside</label>
<description>I'm worried I might get pregnant.</description>
<baseMoodEffect>-3</baseMoodEffect>
<baseOpinionOffset>-2</baseOpinionOffset>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>CameInsideFLowFert</defName>
<thoughtClass>Thought_MemorySocial</thoughtClass>
<durationDays>3.0</durationDays>
<stackLimit>5</stackLimit>
<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>{0} came inside</label>
<description>I'm worried I might get pregnant.&#10;The chance is low, but...</description>
<baseMoodEffect>-1</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>CameInsideFFetish</defName>
<thoughtClass>Thought_MemorySocial</thoughtClass>
<durationDays>3.0</durationDays>
<stackLimit>5</stackLimit>
<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>{0} came inside</label>
<description>I hope I get pregnant.</description>
<baseMoodEffect>10</baseMoodEffect>
<baseOpinionOffset>5</baseOpinionOffset>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>CameInsideFFetishSafe</defName>
<thoughtClass>Thought_MemorySocial</thoughtClass>
<durationDays>3.0</durationDays>
<stackLimit>5</stackLimit>
<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>{0} came inside</label>
<description>I don't think I'll get pregnant, but it's fun to fantasize.</description>
<baseMoodEffect>3</baseMoodEffect>
<label>came inside of {0}</label>
<description>I came inside of my rival!</description>
<baseMoodEffect>5</baseMoodEffect>
<baseOpinionOffset>1</baseOpinionOffset>
</li>
</stages>
@ -98,9 +47,9 @@
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>HaterCameInsideFSafe</defName>
<defName>CameInsideFFetish</defName>
<thoughtClass>Thought_MemorySocial</thoughtClass>
<durationDays>3.0</durationDays>
<stackLimit>5</stackLimit>
@ -109,9 +58,9 @@
<stages>
<li>
<label>{0} came inside</label>
<description>I probably won't get pregnant, but I still don't like it.</description>
<baseMoodEffect>-2</baseMoodEffect>
<baseOpinionOffset>-5</baseOpinionOffset>
<description>I hope I get pregnant.</description>
<baseMoodEffect>10</baseMoodEffect>
<baseOpinionOffset>5</baseOpinionOffset>
</li>
</stages>
</ThoughtDef>
@ -149,23 +98,74 @@
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>HaterCameInsideM</defName>
<defName>CameInsideFLowFert</defName>
<thoughtClass>Thought_MemorySocial</thoughtClass>
<durationDays>1.0</durationDays>
<durationDays>3.0</durationDays>
<stackLimit>5</stackLimit>
<stackedEffectMultiplier>0.4</stackedEffectMultiplier>
<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>came inside of {0}</label>
<description>I came inside of that bitch!</description>
<baseMoodEffect>5</baseMoodEffect>
<label>{0} came inside</label>
<description>I'm worried I might get pregnant.&#10;The chance is low, but...</description>
<baseMoodEffect>-1</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>CameInsideF</defName>
<thoughtClass>Thought_MemorySocial</thoughtClass>
<durationDays>7.0</durationDays>
<stackLimit>5</stackLimit>
<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>{0} came inside</label>
<description>I'm worried I might get pregnant.</description>
<baseMoodEffect>-3</baseMoodEffect>
<baseOpinionOffset>-2</baseOpinionOffset>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>CameInsideFFetishSafe</defName>
<thoughtClass>Thought_MemorySocial</thoughtClass>
<durationDays>3.0</durationDays>
<stackLimit>5</stackLimit>
<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>{0} came inside</label>
<description>I don't think I'll get pregnant, but it's fun to fantasize.</description>
<baseMoodEffect>3</baseMoodEffect>
<baseOpinionOffset>1</baseOpinionOffset>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>HaterCameInsideFSafe</defName>
<thoughtClass>Thought_MemorySocial</thoughtClass>
<durationDays>3.0</durationDays>
<stackLimit>5</stackLimit>
<stackedEffectMultiplier>0.1</stackedEffectMultiplier>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>{0} came inside</label>
<description>I probably won't get pregnant, but I still don't like it.</description>
<baseMoodEffect>-2</baseMoodEffect>
<baseOpinionOffset>-5</baseOpinionOffset>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>UnwantedPregnancy</defName>
<thoughtClass>Thought_Memory</thoughtClass>

View file

@ -14,6 +14,16 @@
<Stage_None>None</Stage_None>
<Stage_Climacteric>Climacteric</Stage_Climacteric>
<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_Induced_Desc>The ovaries are preparing to release an egg. Ovulation will occur if semen enters the womb.</Stage_Follicular_Induced_Desc>
<Stage_Ovulatory_Desc>The ovaries are releasing an egg into the womb.</Stage_Ovulatory_Desc>
<Stage_Luteal_Desc>The womb is prepared to recieve a fertilized egg. Pregnancy will result if one implants before the end of the stage.</Stage_Luteal_Desc>
<Stage_Bleeding_Desc>The womb is shedding its lining, along with any eggs that failed to implant.</Stage_Bleeding_Desc>
<Stage_Pregnant_Desc>A baby is growing inside the womb. With time and care, it will become a new resident of this world.</Stage_Pregnant_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_Climacteric_Desc>The ovaries have neared exhaustion and the menstrual cycle has become irregular.</Stage_Climacteric_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_MilkTooltip>Lactate self</Button_MilkTooltip>
<Dialog_WombInfo01>State</Dialog_WombInfo01>
@ -28,6 +38,8 @@
<Dialog_DoCleanWomb_Tooltip>Gather cum into bucket</Dialog_DoCleanWomb_Tooltip>
<Dialog_DontCleanWomb_Tooltip>Store cum in womb</Dialog_DontCleanWomb_Tooltip>
<Dialog_FatherUnknown>Unknown</Dialog_FatherUnknown>
<Option1_Label_1>Enable womb icon</Option1_Label_1>
<Option1_Label_2>Enable button in health tab</Option1_Label_2>
@ -109,7 +121,7 @@
<Option_EstrusRelationship_Label>Hookup minimum opinion in estrus</Option_EstrusRelationship_Label>
<EstimatedCumLifespan>Estimated sperm lifespan</EstimatedCumLifespan>
<EstimatedEggLifespan>Estimated egg lifespan</EstimatedEggLifespan>
<FertilityDesc>Chance of fertilization in the next hour: {0}%&#10;The chance of pregnancy of a fertilized egg.&#10;The white overlay indicates fertilization chance of sperm in womb.</FertilityDesc>
<FertilityDesc>Implantation chance of fertilized eggs.&#10;Chance of fertilization this hour: {0}%</FertilityDesc>
<Button_ResetToDefault>Reset to default</Button_ResetToDefault>
<Gizmo_GatherCum>Gather cum</Gizmo_GatherCum>

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View file

@ -16,7 +16,7 @@ namespace RJW_Menstruation.Interactions
private bool WillingAndAble(Pawn fucker, Pawn fucked, bool visible)
{
return
HediffComp_Menstruation.IsInEstrus(fucked, visible)
fucked.IsInEstrus(visible)
&&
PregnancyHelper.CanImpregnate(fucker, fucked);
}

View file

@ -40,6 +40,8 @@ namespace RJW_Menstruation
public const float VARIANT = 0.2f;
public const int TICKINTERVAL = 3750;
public const float MAX_BREAST_INCREMENT = 0.10f;
public const float BREAST_GROWTH_START = 1f / 6f;
public const float BREAST_GROWTH_END = 1f / 3f;
public CompProperties_Breast Props;
@ -282,7 +284,7 @@ namespace RJW_Menstruation
// Scenario B: Pregnant, grow in the second half of first trimester
else if (parent.pawn.IsPregnant())
{
float pregnancySize = Mathf.InverseLerp(1f / 6f, 1f / 3f, parent.pawn.GetPregnancyProgress()) * MAX_BREAST_INCREMENT;
float pregnancySize = Mathf.InverseLerp(BREAST_GROWTH_START, BREAST_GROWTH_END, parent.pawn.GetPregnancyProgress()) * MAX_BREAST_INCREMENT;
if (breastSizeIncreased > pregnancySize)
{
debugGrowthStatus = "Shrinking due to being oversize for pregnancy";

View file

@ -20,6 +20,22 @@ namespace RJW_Menstruation
public class HediffComp_InducedOvulator : HediffComp_Menstruation
{
public override string GetCurStageDesc
{
get
{
switch (CurrentVisibleStage)
{
case Stage.Follicular:
return Translations.Stage_Follicular_Induced_Desc;
case Stage.ClimactericFollicular:
return Translations.Stage_Follicular_Induced_Desc + " " + Translations.Stage_Climacteric_Desc;
default:
return base.GetCurStageDesc;
}
}
}
protected override void FollicularAction()
{
if (!IsBreedingSeason())
@ -29,8 +45,40 @@ namespace RJW_Menstruation
}
if (curStageHrs >= FollicularIntervalHours)
{
GoNextStage(Stage.Luteal);
estrusflag = false;
lutealIntervalhours = PeriodRandomizer(lutealIntervalhours, Props.deviationFactor);
GoNextStage(Stage.Luteal);
}
else
{
curStageHrs += Configurations.CycleAcceleration;
if (!estrusflag && curStageHrs > FollicularIntervalHours - Props.estrusDaysBeforeOvulation * 24)
{
estrusflag = true;
SetEstrus(Props.eggLifespanDays + Props.estrusDaysBeforeOvulation);
}
StayCurrentStage();
}
}
protected override void ClimactericFollicularAction()
{
if (!Configurations.EnableMenopause)
{
RemoveClimactericEffect();
StayCurrentStage();
}
else if (curStageHrs >= (follicularIntervalhours - bleedingIntervalhours) * CycleFactor)
{
estrusflag = false;
lutealIntervalhours = PeriodRandomizer(lutealIntervalhours, Props.deviationFactor);
GoNextStage(Stage.ClimactericLuteal);
}
else if (ovarypower < OvaryPowerThreshold / 3 && Rand.Range(0.0f, 1.0f) < 0.2f) // Might randomly skip to luteal early)
{
estrusflag = false;
lutealIntervalhours = PeriodRandomizer(lutealIntervalhours, Props.deviationFactor * 6);
GoNextStage(Stage.ClimactericLuteal);
}
else
{
@ -47,7 +95,13 @@ namespace RJW_Menstruation
protected override void AfterCumIn(Pawn cummer)
{
base.AfterCumIn(cummer);
if (curStage == Stage.Follicular || curStage == Stage.ClimactericFollicular) curStage = Stage.Ovulatory;
switch (curStage)
{
case Stage.Follicular:
case Stage.ClimactericFollicular:
curStage = Stage.Ovulatory;
break;
}
}
public override bool IsDangerDay

View file

@ -65,7 +65,7 @@ namespace RJW_Menstruation
const float minmakefilthvalue = 1.0f;
//const int ovarypowerthreshold = 72;
public static readonly int tickInterval = 2500; // an hour
public const int tickInterval = GenDate.TicksPerHour;
public CompProperties_Menstruation Props;
public Stage curStage = Stage.Follicular;
public int curStageHrs = 0;
@ -302,6 +302,43 @@ namespace RJW_Menstruation
}
}
public virtual string GetCurStageDesc
{
get
{
switch (CurrentVisibleStage)
{
case Stage.Follicular:
return Translations.Stage_Follicular_Desc;
case Stage.Ovulatory:
return Translations.Stage_Ovulatory_Desc;
case Stage.Luteal:
return Translations.Stage_Luteal_Desc;
case Stage.Bleeding:
return Translations.Stage_Bleeding_Desc;
case Stage.Fertilized:
return Translations.Stage_Luteal_Desc;
case Stage.Pregnant:
return Translations.Stage_Pregnant_Desc;
case Stage.Recover:
return Translations.Stage_Recover_Desc;
case Stage.None:
case Stage.Young:
return Translations.Stage_None_Desc;
case Stage.ClimactericFollicular:
return Translations.Stage_Follicular_Desc + " " + Translations.Stage_Climacteric_Desc;
case Stage.ClimactericLuteal:
return Translations.Stage_Luteal_Desc + " " + Translations.Stage_Climacteric_Desc;
case Stage.ClimactericBleeding:
return Translations.Stage_Bleeding_Desc + " " + Translations.Stage_Climacteric_Desc;
case Stage.Anestrus:
return Translations.Stage_Anestrus_Desc;
default:
return "";
}
}
}
public string WombTex
{
get
@ -382,6 +419,15 @@ namespace RJW_Menstruation
return -1;
}
}
public IEnumerable<Pawn> GetCummersAndFertilizers()
{
if (!cums.NullOrEmpty())
foreach (Cum cum in cums)
yield return cum.pawn;
if (!eggs.NullOrEmpty())
foreach (Egg egg in eggs)
yield return egg.fertilizer;
}
public bool IsEggExist
{
get
@ -1025,12 +1071,6 @@ namespace RJW_Menstruation
}
}
public static bool IsInEstrus(Pawn pawn, bool visible = true)
{
if (pawn.Dead) return false;
return pawn.health?.hediffSet?.HasHediff(visible ? VariousDefOf.Hediff_Estrus : VariousDefOf.Hediff_Estrus_Concealed) ?? false;
}
public void SetEstrus(int days)
{
HediffDef estrusdef = Props.concealedEstrus ? VariousDefOf.Hediff_Estrus_Concealed : VariousDefOf.Hediff_Estrus;
@ -1056,39 +1096,57 @@ namespace RJW_Menstruation
switch (GenLocalDate.Season(map))
{
case Season.Spring:
if ((Props.breedingSeason & SeasonalBreed.Spring) != 0) return true;
break;
return (Props.breedingSeason & SeasonalBreed.Spring) != 0;
case Season.Summer:
case Season.PermanentSummer:
if ((Props.breedingSeason & SeasonalBreed.Summer) != 0) return true;
break;
return (Props.breedingSeason & SeasonalBreed.Summer) != 0;
case Season.Fall:
if ((Props.breedingSeason & SeasonalBreed.Fall) != 0) return true;
break;
return (Props.breedingSeason & SeasonalBreed.Fall) != 0;
case Season.Winter:
case Season.PermanentWinter:
if ((Props.breedingSeason & SeasonalBreed.Winter) != 0) return true;
break;
return (Props.breedingSeason & SeasonalBreed.Winter) != 0;
default:
return false;
}
return false;
}
protected Pawn Fertilize()
{
if (cums.NullOrEmpty()) return null;
foreach (Cum cum in cums)
List<Cum> eligibleCum = cums.FindAll(cum => cum.FertVolume > 0 && cum.pawn != null && (RJWPregnancySettings.bestial_pregnancy_enabled || xxx.is_animal(parent.pawn) == xxx.is_animal(cum.pawn)));
if (eligibleCum.Count == 0) return null;
float totalFertPower = 0;
foreach (Cum cum in eligibleCum)
totalFertPower += cum.FertVolume;
if (Rand.Range(0.0f, 1.0f) > totalFertPower * Configurations.FertilizeChance * Props.basefertilizationChanceFactor)
return null;
parent.pawn.records.AddTo(VariousDefOf.AmountofFertilizedEggs, 1);
float selection = Rand.Range(0.0f, totalFertPower);
foreach (Cum cum in eligibleCum)
{
float rand = Rand.Range(0.0f, 1.0f);
if (cum.pawn != null && !cum.notcum && rand < cum.FertVolume * cum.fertFactor * Configurations.FertilizeChance * Props.basefertilizationChanceFactor)
selection -= cum.FertVolume;
if (selection <= 0) return cum.pawn;
}
// We shouldn't reach here, but floating point errors exist, so just to be sure, select whomever came the most
float mostCum = 0;
Pawn mostCummer = null;
foreach (Cum cum in eligibleCum)
{
if(cum.FertVolume > mostCum)
{
if (!RJWPregnancySettings.bestial_pregnancy_enabled && (xxx.is_animal(parent.pawn) ^ xxx.is_animal(cum.pawn))) continue;
parent.pawn.records.AddTo(VariousDefOf.AmountofFertilizedEggs, 1);
return cum.pawn;
mostCum = cum.FertVolume;
mostCummer = cum.pawn;
}
}
return null;
return mostCummer;
}
@ -1427,6 +1485,31 @@ namespace RJW_Menstruation
}
}
protected virtual void RecoverAction()
{
if (curStageHrs >= recoveryIntervalhours)
{
if (Configurations.EnableMenopause && ovarypower < OvaryPowerThreshold)
{
GoNextStage(Stage.ClimactericFollicular);
}
else if (parent.pawn.health.capacities.GetLevel(xxx.reproduction) == 0)
{
GoNextStage(Stage.Young);
}
else
{
follicularIntervalhours = PeriodRandomizer(follicularIntervalhours, Props.deviationFactor);
GoNextStage(Stage.Follicular);
}
}
else
{
curStageHrs += Configurations.CycleAcceleration;
StayCurrentStage();
}
}
protected virtual void YoungAction()
{
if (!Configurations.EnableMenopause && ovarypower < 0 && ovarypower > -10000)
@ -1440,6 +1523,97 @@ namespace RJW_Menstruation
else GoNextStage(Stage.Follicular);
}
protected virtual void ClimactericFollicularAction()
{
if (!Configurations.EnableMenopause)
{
RemoveClimactericEffect();
StayCurrentStage();
}
else if (curStageHrs >= (follicularIntervalhours - bleedingIntervalhours) * CycleFactor)
{
GoNextStage(Stage.Ovulatory);
}
else if (ovarypower < OvaryPowerThreshold / 3 && Rand.Range(0.0f, 1.0f) < 0.2f) //skips ovulatory
{
lutealIntervalhours = PeriodRandomizer(lutealIntervalhours, Props.deviationFactor * 6);
GoNextStage(Stage.ClimactericLuteal);
}
else
{
curStageHrs += Configurations.CycleAcceleration;
StayCurrentStage();
}
}
protected virtual void ClimactericLutealAction()
{
if (!Configurations.EnableMenopause)
{
RemoveClimactericEffect();
StayCurrentStage();
}
else if (!eggs.NullOrEmpty())
{
FertilizationCheck();
EggDecay();
if (Implant()) GoNextStage(Stage.Pregnant);
else
{
curStageHrs += Configurations.CycleAcceleration;
StayCurrentStage();
}
}
else if (curStageHrs <= lutealIntervalhours)
{
curStageHrs += Configurations.CycleAcceleration;
StayCurrentStage();
}
else
{
eggs.Clear();
if (Props.bleedingIntervalDays == 0)
{
follicularIntervalhours = PeriodRandomizer(follicularIntervalhours, Props.deviationFactor * 6);
GoNextStage(Stage.ClimactericFollicular);
}
else if (ovarypower < OvaryPowerThreshold / 4 || (ovarypower < OvaryPowerThreshold / 3 && Rand.Range(0.0f, 1.0f) < 0.3f)) //skips bleeding
{
follicularIntervalhours = PeriodRandomizer(follicularIntervalhours, Props.deviationFactor * 6);
GoNextStage(Stage.ClimactericFollicular);
}
else
{
bleedingIntervalhours = PeriodRandomizer(bleedingIntervalhours, Props.deviationFactor);
if (crampPain >= 0.05f)
{
AddCrampPain();
}
GoNextStage(Stage.ClimactericBleeding);
}
}
}
protected virtual void ClimactericBleedingAction()
{
if (!Configurations.EnableMenopause)
{
RemoveClimactericEffect();
StayCurrentStage();
}
else if (curStageHrs >= bleedingIntervalhours)
{
follicularIntervalhours = PeriodRandomizer(follicularIntervalhours, Props.deviationFactor * 6);
GoNextStage(Stage.ClimactericFollicular);
}
else
{
if (curStageHrs < bleedingIntervalhours / 6) for (int i = 0; i < Configurations.CycleAcceleration; i++) BleedOut();
curStageHrs += Configurations.CycleAcceleration;
StayCurrentStage();
}
}
protected virtual void AnestrusAction()
{
if (IsBreedingSeason())
@ -1478,10 +1652,13 @@ namespace RJW_Menstruation
}
else if (parent.pawn.relations.OpinionOf(cummer) <= -5)
{
parent.pawn.needs.mood.thoughts.memories.RemoveMemoriesOfDefWhereOtherPawnIs(VariousDefOf.CameInsideF, cummer);
parent.pawn.needs.mood.thoughts.memories.RemoveMemoriesOfDefWhereOtherPawnIs(VariousDefOf.HaterCameInsideFEstrus, cummer);
parent.pawn.needs.mood.thoughts.memories.TryGainMemory(VariousDefOf.HaterCameInsideF, cummer);
}
else if (IsInEstrus(parent.pawn) && parent.pawn.relations.OpinionOf(cummer) < RJWHookupSettings.MinimumRelationshipToHookup)
else if (parent.pawn.IsInEstrus() && parent.pawn.relations.OpinionOf(cummer) < RJWHookupSettings.MinimumRelationshipToHookup)
{
parent.pawn.needs.mood.thoughts.memories.RemoveMemoriesOfDefWhereOtherPawnIs(VariousDefOf.CameInsideF, cummer);
parent.pawn.needs.mood.thoughts.memories.TryGainMemory(VariousDefOf.HaterCameInsideFEstrus, cummer);
}
else if (!parent.pawn.relations.DirectRelationExists(PawnRelationDefOf.Spouse, cummer) && !parent.pawn.relations.DirectRelationExists(PawnRelationDefOf.Fiance, cummer))
@ -1534,30 +1711,7 @@ namespace RJW_Menstruation
action = PregnantAction;
break;
case Stage.Recover:
action = delegate
{
if (curStageHrs >= recoveryIntervalhours)
{
if (Configurations.EnableMenopause && ovarypower < OvaryPowerThreshold)
{
GoNextStage(Stage.ClimactericFollicular);
}
else if (parent.pawn.health.capacities.GetLevel(xxx.reproduction) == 0)
{
GoNextStage(Stage.Young);
}
else
{
follicularIntervalhours = PeriodRandomizer(follicularIntervalhours, Props.deviationFactor);
GoNextStage(Stage.Follicular);
}
}
else
{
curStageHrs += Configurations.CycleAcceleration;
StayCurrentStage();
}
};
action = RecoverAction;
break;
case Stage.None:
action = delegate
@ -1569,99 +1723,13 @@ namespace RJW_Menstruation
action = YoungAction;
break;
case Stage.ClimactericFollicular:
action = delegate
{
if (!Configurations.EnableMenopause)
{
RemoveClimactericEffect();
StayCurrentStage();
}
else if (curStageHrs >= (follicularIntervalhours - bleedingIntervalhours) * CycleFactor)
{
GoNextStage(Stage.Ovulatory);
}
else if (ovarypower < OvaryPowerThreshold / 3 && Rand.Range(0.0f, 1.0f) < 0.2f) //skips ovulatory
{
follicularIntervalhours = PeriodRandomizer(follicularIntervalhours, Props.deviationFactor * 6);
GoNextStage(Stage.ClimactericFollicular);
}
else
{
curStageHrs += Configurations.CycleAcceleration;
StayCurrentStage();
}
};
action = ClimactericFollicularAction;
break;
case Stage.ClimactericLuteal:
action = delegate
{
if (!Configurations.EnableMenopause)
{
RemoveClimactericEffect();
StayCurrentStage();
}
else if (!eggs.NullOrEmpty())
{
FertilizationCheck();
EggDecay();
if (Implant()) GoNextStage(Stage.Pregnant);
else
{
curStageHrs += Configurations.CycleAcceleration;
StayCurrentStage();
}
}
else if (curStageHrs <= lutealIntervalhours)
{
curStageHrs += Configurations.CycleAcceleration;
StayCurrentStage();
}
else
{
eggs.Clear();
if (Props.bleedingIntervalDays == 0)
{
follicularIntervalhours = PeriodRandomizer(follicularIntervalhours, Props.deviationFactor * 6);
GoNextStage(Stage.ClimactericFollicular);
}
else if (ovarypower < OvaryPowerThreshold / 4 || (ovarypower < OvaryPowerThreshold / 3 && Rand.Range(0.0f, 1.0f) < 0.3f)) //skips bleeding
{
follicularIntervalhours = PeriodRandomizer(follicularIntervalhours, Props.deviationFactor * 6);
GoNextStage(Stage.ClimactericFollicular);
}
else
{
bleedingIntervalhours = PeriodRandomizer(bleedingIntervalhours, Props.deviationFactor);
if (crampPain >= 0.05f)
{
AddCrampPain();
}
GoNextStage(Stage.ClimactericBleeding);
}
}
};
action = ClimactericLutealAction;
break;
case Stage.ClimactericBleeding:
action = delegate
{
if (!Configurations.EnableMenopause)
{
RemoveClimactericEffect();
StayCurrentStage();
}
else if (curStageHrs >= bleedingIntervalhours)
{
follicularIntervalhours = PeriodRandomizer(follicularIntervalhours, Props.deviationFactor * 6);
GoNextStage(Stage.ClimactericFollicular);
}
else
{
if (curStageHrs < bleedingIntervalhours / 6) for (int i = 0; i < Configurations.CycleAcceleration; i++) BleedOut();
curStageHrs += Configurations.CycleAcceleration;
StayCurrentStage();
}
};
action = ClimactericBleedingAction;
break;
case Stage.Anestrus:
action = AnestrusAction;

View file

@ -155,33 +155,55 @@ namespace RJW_Menstruation
return wombtex;
}
public static Texture2D GetEggIcon(this HediffComp_Menstruation comp)
public static Texture2D GetEggIcon(this HediffComp_Menstruation comp, bool includeOvary)
{
if (comp.parent.pawn.IsPregnant(Configurations.InfoDetail != Configurations.DetailLevel.All))
{
if (comp.parent.pawn.GetPregnancyProgress() < 0.2f) return ContentFinder<Texture2D>.Get("Eggs/Egg_Implanted00", true);
else return ContentFinder<Texture2D>.Get("Womb/Empty", true);
}
else if (!comp.IsEggExist) return ContentFinder<Texture2D>.Get("Womb/Empty", true);
else
switch(comp.curStage)
{
int fertstage = comp.IsFertilized;
if (fertstage >= 0)
{
if (fertstage < 1) return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilized00", true);
else if (fertstage < 24) return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilized01", true);
else return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilized02", true);
}
else if (comp.IsEggFertilizing) return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilizing01", true);
else return ContentFinder<Texture2D>.Get("Eggs/Egg", true);
case HediffComp_Menstruation.Stage.Follicular:
case HediffComp_Menstruation.Stage.ClimactericFollicular:
if (!includeOvary) break;
if (comp is HediffComp_InducedOvulator) break;
if (comp.curStageHrs > comp.FollicularIntervalHours - 30) // Approximate time for ovulation to occur
return ContentFinder<Texture2D>.Get("Ovaries/Ovary_01", true);
else break;
case HediffComp_Menstruation.Stage.Ovulatory:
if (!includeOvary) break;
return ContentFinder<Texture2D>.Get("Ovaries/Ovary_02", true);
case HediffComp_Menstruation.Stage.Luteal:
case HediffComp_Menstruation.Stage.ClimactericLuteal:
if (!comp.IsEggExist) break;
int fertstage = comp.IsFertilized;
if (fertstage >= 0)
{
if (fertstage <= comp.CycleFactor) return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilizing02", true);
if (fertstage <= 18) return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilized00", true);
else if (fertstage <= 54) return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilized01", true);
else return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilized02", true);
}
else if (comp.IsEggFertilizing)
{
if (comp.GetFertilityChance() < 0.5f)
return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilizing00", true);
else
return ContentFinder<Texture2D>.Get("Eggs/Egg_Fertilizing01", true);
}
else return ContentFinder<Texture2D>.Get("Eggs/Egg", true);
}
return ContentFinder<Texture2D>.Get("Womb/Empty", true);
}
public static void DrawEggOverlay(this HediffComp_Menstruation comp, Rect wombRect)
public static void DrawEggOverlay(this HediffComp_Menstruation comp, Rect wombRect, bool includeOvary)
{
Rect rect = new Rect(wombRect.xMax - wombRect.width / 3, wombRect.y, wombRect.width / 3, wombRect.width / 3);
GUI.color = Color.white;
GUI.DrawTexture(rect, comp.GetEggIcon(), ScaleMode.ScaleToFit);
GUI.DrawTexture(rect, comp.GetEggIcon(includeOvary), ScaleMode.ScaleToFit);
}
@ -257,7 +279,11 @@ namespace RJW_Menstruation
}
else return (hediff.p_end_tick - hediff.p_start_tick) / GenDate.TicksPerHour;
}
public static bool IsInEstrus(this Pawn pawn, bool visible = true)
{
if (pawn.Dead) return false;
return pawn.health?.hediffSet?.HasHediff(visible ? VariousDefOf.Hediff_Estrus : VariousDefOf.Hediff_Estrus_Concealed) ?? false;
}
}
}

View file

@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Linq;
using HarmonyLib;
using Verse;
using RimWorld;
using RimWorld.Planet;
namespace RJW_Menstruation.Patch
{
[HarmonyPatch(typeof(WorldPawnGC), "GetCriticalPawnReason")]
public static class GetCriticalPawnReason_Patch
{
readonly public static HashSet<Pawn> cummedPawns = new HashSet<Pawn>();
public static void Postfix(ref string __result, Pawn pawn)
{
if (!__result.NullOrEmpty()) return;
if (cummedPawns.Contains(pawn))
__result = "Has cum or fertilized egg in a womb";
}
}
[HarmonyPatch(typeof(WorldPawnGC), "AccumulatePawnGCData")]
public static class PawnGCPass_Patch
{
public static void Prefix()
{
GetCriticalPawnReason_Patch.cummedPawns.Clear();
// foreach(Pawn p in PawnsFinder.All_AliveOrDead)
foreach(Pawn p in PawnsFinder.AllMapsCaravansAndTravelingTransportPods_Alive_OfPlayerFaction.Union(PawnsFinder.AllMapsCaravansAndTravelingTransportPods_Alive_PrisonersOfColony))
{
HediffComp_Menstruation comp = p.GetMenstruationComp();
if (comp is null) continue;
GetCriticalPawnReason_Patch.cummedPawns.UnionWith(comp.GetCummersAndFertilizers());
}
}
}
}

View file

@ -168,15 +168,15 @@ namespace RJW_Menstruation
}
public static void Postfix(ref float __result, Pawn fucker, Pawn fucked)
{
if (HediffComp_Menstruation.IsInEstrus(fucker, true) && PregnancyHelper.CanImpregnate(fucked, fucker))
if (fucker.IsInEstrus(true) && PregnancyHelper.CanImpregnate(fucked, fucker))
{
__result *= (1f + GetNetFertility(fucker, fucked) / 4);
}
else if (HediffComp_Menstruation.IsInEstrus(fucker, false) && PregnancyHelper.CanImpregnate(fucked, fucker))
else if (fucker.IsInEstrus(false) && PregnancyHelper.CanImpregnate(fucked, fucker))
{
__result *= (1f + GetNetFertility(fucker, fucked) / 40);
}
else if(xxx.is_animal(fucker) && HediffComp_Menstruation.IsInEstrus(fucked, true) && PregnancyHelper.CanImpregnate(fucker, fucked))
else if(xxx.is_animal(fucker) && fucked.IsInEstrus(true) && PregnancyHelper.CanImpregnate(fucker, fucked))
{
__result *= 1.25f;
}
@ -188,7 +188,7 @@ namespace RJW_Menstruation
{
private static float FuckabilityThreshold(Pawn pawn, Pawn partner)
{
return (Configurations.EstrusOverridesHookupSettings && HediffComp_Menstruation.IsInEstrus(pawn) && PregnancyHelper.CanImpregnate(partner, pawn))
return (Configurations.EstrusOverridesHookupSettings && pawn.IsInEstrus() && PregnancyHelper.CanImpregnate(partner, pawn))
? Configurations.EstrusFuckabilityToHookup : RJWHookupSettings.MinimumFuckabilityToHookup;
}
@ -217,12 +217,12 @@ namespace RJW_Menstruation
{
private static float AttractivenessThreshold(Pawn pawn, Pawn partner)
{
return (Configurations.EstrusOverridesHookupSettings && HediffComp_Menstruation.IsInEstrus(pawn) && PregnancyHelper.CanImpregnate(partner, pawn))
return (Configurations.EstrusOverridesHookupSettings && pawn.IsInEstrus() && PregnancyHelper.CanImpregnate(partner, pawn))
? Configurations.EstrusAttractivenessToHookup : RJWHookupSettings.MinimumAttractivenessToHookup;
}
private static float RelationshipThreshold(Pawn pawn, Pawn partner)
{
return (Configurations.EstrusOverridesHookupSettings && HediffComp_Menstruation.IsInEstrus(pawn) && PregnancyHelper.CanImpregnate(partner, pawn))
return (Configurations.EstrusOverridesHookupSettings && pawn.IsInEstrus() && PregnancyHelper.CanImpregnate(partner, pawn))
? Configurations.EstrusRelationshipToHookup : RJWHookupSettings.MinimumRelationshipToHookup;
}

View file

@ -66,6 +66,7 @@
<Compile Include="HediffComps\HediffComp_InducedOvulator.cs" />
<Compile Include="HediffComps\MenstruationUtility.cs" />
<Compile Include="IngestionOutcomeDoers.cs" />
<Compile Include="Patch\GC_Patch.cs" />
<Compile Include="Recipe_Surgery.cs" />
<Compile Include="UI\Dialog_HybridCustom.cs" />
<Compile Include="UI\Dialog_WombStatus.cs" />

View file

@ -17,6 +17,16 @@ namespace RJW_Menstruation
public static readonly string Stage_None = "Stage_None".Translate();
public static readonly string Stage_Climacteric = "Stage_Climacteric".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_Induced_Desc = "Stage_Follicular_Induced_Desc".Translate();
public static readonly string Stage_Ovulatory_Desc = "Stage_Ovulatory_Desc".Translate();
public static readonly string Stage_Luteal_Desc = "Stage_Luteal_Desc".Translate();
public static readonly string Stage_Bleeding_Desc = "Stage_Bleeding_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_None_Desc = "Stage_None_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 Button_HealthTab = "Button_HealthTab".Translate();
public static readonly string Button_MilkTooltip = "Button_MilkTooltip".Translate();
public static readonly string Dialog_DoCleanWomb_Tooltip = "Dialog_DoCleanWomb_Tooltip".Translate();

View file

@ -242,7 +242,7 @@ namespace RJW_Menstruation
if (Configurations.DrawEggOverlay)
{
comp.DrawEggOverlay(wombRect);
comp.DrawEggOverlay(wombRect, true);
}
@ -257,6 +257,7 @@ namespace RJW_Menstruation
GUI.Box(wombInfoRect, Translations.Dialog_WombInfo01 + ": " + comp.GetCurStageLabel, buttonstyle);
Widgets.FillableBar(progressRect, comp.StageProgress, comp.GetStageTexture);
GUI.color = Color.white;
TooltipHandler.TipRegion(wombInfoRect, comp.GetCurStageDesc);
fontstyleright.normal.textColor = Color.red;

View file

@ -32,7 +32,7 @@ namespace RJW_Menstruation
GUI.color = color;
Widgets.DrawTextureFitted(rect, overay, iconDrawScale * 0.85f, iconProportions, iconTexCoords, iconAngle, buttonMat);
GUI.color = Color.white;
if (Configurations.DrawEggOverlay) comp.DrawEggOverlay(rect);
if (Configurations.DrawEggOverlay) comp.DrawEggOverlay(rect, false);
Rect progressRect = new Rect(rect.x + 2f, rect.y, rect.width - 4f, progressbarHeight);
Widgets.FillableBar(progressRect, comp.StageProgress, comp.GetStageTexture);

View file

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

View file

@ -1,3 +1,11 @@
Version 1.0.6.5
- Handle climacteric induced ovulators a bit better.
- Compatibility update for Sexperience 1.0.4.2
- Add a brief description when mousing over the current phase in the womb dialog.
- Add an ovary image to the womb status dialog (but not the little icon) when ovulation is imminent or occuring.
- Redone algorithm for paternity selection upon an egg being fertilized, to make for a fairer contest when there is lots of sperm from multiple people.
- NPC pawns with cum inside a pawn of your faction (or a prisoner you're holding) won't be removed by the garbage collector early.
Version 1.0.6.4
- Fix a bug with pawns not being generated.
- Fix ovary initialization for races with invalid litter sizes.