Compare commits

..

23 commits

Author SHA1 Message Date
lutepickle
b5df8b1dce Merge branch 'dev' 2026-06-08 09:30:22 -07:00
lutepickle
d8b98ca05e Fix patch to RJW tab with 6.1.4 2026-06-08 09:29:12 -07:00
lutepickle
a8caad85c6 Merge branch 'dev' 2026-05-17 12:25:36 -07:00
lutepickle
ef909091f8 Add GetFluids with 0 arguments that returns all fluids 2026-05-09 09:21:10 -07:00
lutepickle
8341d3f213 Rebuild 2026-04-16 20:55:04 -07:00
lutepickle
1600f0ea58 Update changelog 2026-04-12 10:12:41 -07:00
lutepickle
18d316c26b Merge branch 'feat/ghostclinic3YTB/render-womb-icon-column' into 'dev'
feat(rjw-menstruation): add sortable womb status column to RJW main tab

See merge request lutepickle/rjw_menstruation!18
2026-04-12 17:10:21 +00:00
ghostclinic3YTB
82216c5a7d feat(rjw-menstruation): add sortable womb status column to RJW main tab 2026-04-12 17:10:21 +00:00
lutepickle
c38464c806 Fix wrong filename when using udder for multiple breasts, or if no breast comp/BreastTex 2026-03-27 16:30:36 -07:00
lutepickle
714eba8e9c Check for bad amount of cum when loading as a failsafe 2026-03-21 20:36:14 -07:00
lutepickle
df134584d7 Have an interaction check failure fall back to rjw impregnate code to properly handle non-fertilization vaginal sex. 2026-03-05 20:45:58 -08:00
lutepickle
8b6d1f70c4 Merge branch 'dev' 2026-03-01 08:26:59 -08:00
lutepickle
0408e792e6 Rebuild 2026-03-01 08:26:45 -08:00
lutepickle
7998d18f3d Use RJW part getter for anuses and breasts to draw 2026-02-19 06:16:45 -08:00
lutepickle
9c0cc92f7d Override breast image with udders if >1 breasts. Also use default breast image if no comp 2026-02-17 11:50:31 -08:00
lutepickle
2bb35f0241 Pass comp to GetAnalIcon for Fluids submod 2026-02-17 05:51:03 -08:00
lutepickle
8d4f4ac3f1 Update Traditional Chinese translation by Hydrogen 2026-02-17 05:50:32 -08:00
lutepickle
c5d1a901c9 Merge branch 'dev' 2026-02-03 12:21:29 -08:00
lutepickle
0f5994dce4 Null test hediff in CheckForStateChange_Patch 2025-12-24 22:33:36 -08:00
lutepickle
325ccaa400 Rebuild for RJW 6.0.3 2025-12-22 10:10:46 -08:00
lutepickle
7041a25742 Process MenstruationModExtension in ThingDef and HediffDef 2025-11-26 21:57:53 -08:00
lutepickle
e0ceb0020d Separate baby image into own function for menstruation fluids mod 2025-10-27 07:11:52 -07:00
lutepickle
83b64f5d8d Add Hediff_MultiplePregnancy.PostMake for Eltoro's addons 2025-10-23 09:30:09 -07:00
23 changed files with 320 additions and 108 deletions

3
.gitignore vendored
View file

@ -343,3 +343,6 @@ healthchecksdb
*.psd *.psd
*.dds *.dds
*.pdn *.pdn
Directory.Build.props
Directory.Build.targets

Binary file not shown.

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<PawnColumnDef>
<defName>RJWMenstruation_Womb</defName>
<headerIcon>Womb/Womb</headerIcon>
<headerTip>Open womb status. Click the header to sort by womb presence and cycle stage.</headerTip>
<workerClass>RJW_Menstruation.MainTab.PawnColumnWorker_WombStatus</workerClass>
<sortable>true</sortable>
<width>34</width>
</PawnColumnDef>
</Defs>

View file

@ -166,4 +166,7 @@
<Description_Absorbed>已吸收</Description_Absorbed> <Description_Absorbed>已吸收</Description_Absorbed>
<!--Generated at: 2025-01-21--> <!--Generated at: 2025-01-21-->
<Stage_Anestrus_Periodic_Desc>子宮處於月經週期之外。經過足夠的時間後,月經週期會恢復。</Stage_Anestrus_Periodic_Desc> <Stage_Anestrus_Periodic_Desc>子宮處於月經週期之外。經過足夠的時間後,月經週期會恢復。</Stage_Anestrus_Periodic_Desc>
<!--Generated at: 2026-02-15-->
<Option_ShowInfertileIcon_Desc>對已經不育的子宮顯示子宮圖示</Option_ShowInfertileIcon_Desc>
<Option_ShowInfertileIcon_Label>仍然展示不育的子宮狀態</Option_ShowInfertileIcon_Label>
</LanguageData> </LanguageData>

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
<Operation Class="PatchOperationSequence">
<operations>
<li Class="PatchOperationInsert">
<xpath>/Defs/PawnTableDef[defName="RJW_PawnTable_Colonists"]/columns/li[text()="Pregnant"]</xpath>
<value>
<li>RJWMenstruation_Womb</li>
</value>
</li>
<li Class="PatchOperationInsert">
<xpath>/Defs/PawnTableDef[defName="RJW_PawnTable_Property"]/columns/li[text()="Pregnant"]</xpath>
<value>
<li>RJWMenstruation_Womb</li>
</value>
</li>
</operations>
</Operation>
</Patch>

Binary file not shown.

View file

@ -13,8 +13,7 @@ namespace RJW_Menstruation_Quirks
{ {
public override bool Satisfied(Pawn pawn) public override bool Satisfied(Pawn pawn)
{ {
List<Hediff> genitalsList = pawn.GetGenitalsList(); return pawn.GetGenitalsList().Any(genital => (genital.def as HediffDef_SexPart)?.genitalFamily == GenitalFamily.Penis);
return genitalsList.Any(genital => (genital.def as HediffDef_SexPart)?.genitalFamily == GenitalFamily.Penis);
} }
} }

View file

@ -169,6 +169,13 @@ namespace RJW_Menstruation
Scribe_Values.Look(ref useCustomColor, "useCustomColor", false); Scribe_Values.Look(ref useCustomColor, "useCustomColor", false);
Scribe_Values.Look(ref customColor, "customColor", default); Scribe_Values.Look(ref customColor, "customColor", default);
Scribe_Defs.Look(ref filthDef, "filthDef"); Scribe_Defs.Look(ref filthDef, "filthDef");
if (Scribe.mode == LoadSaveMode.PostLoadInit &&
(Single.IsInfinity(FertVolume) || Single.IsNaN(FertVolume) || volume < 0f))
{
Log.Error($"Invalid amount of {pawn}'s cum in a womb");
volume = 0;
fertility = 0;
}
} }
public void MakeThinner(float speed) public void MakeThinner(float speed)

View file

@ -126,7 +126,7 @@ namespace RJW_Menstruation
protected int? opcache = null; protected int? opcache = null;
protected float antisperm = 0.0f; protected float antisperm = 0.0f;
// RJW pregnancy, or Biotech pregnancy/labor/laborpushing // RJW pregnancy, or Biotech pregnancy/labor/laborpushing
protected Hediff pregnancy = null; protected Hediff pregnancy = null; // Remove, instead reference per-genital pregnancy list
protected int eggLifeSpanTicks = GenDate.DaysToTicks(2); protected int eggLifeSpanTicks = GenDate.DaysToTicks(2);
protected EstrusLevel estrusLevel = EstrusLevel.Visible; protected EstrusLevel estrusLevel = EstrusLevel.Visible;
@ -313,7 +313,7 @@ namespace RJW_Menstruation
{ {
StatDefOf.Fertility.Worker.ClearCacheForThing(Pawn); // No effect for now, but a future RW update might add caching for this StatDefOf.Fertility.Worker.ClearCacheForThing(Pawn); // No effect for now, but a future RW update might add caching for this
calculatingOvulationChance = true; calculatingOvulationChance = true;
ovulationChance *= PawnCapacityUtility.CalculateCapacityLevel(Pawn.health.hediffSet, xxx.reproduction); ovulationChance *= PawnCapacityUtility.CalculateCapacityLevel(Pawn.health.hediffSet, xxx.reproduction); // Add genital fertility
} }
finally finally
{ {
@ -672,7 +672,16 @@ namespace RJW_Menstruation
} }
} }
public void Notify_UpdatedGenes() private void ProcessExtension(MenstruationModExtension extension)
{
eggLifeSpanTicks = (int)(eggLifeSpanTicks * extension.eggLifeTimeFactor);
if (extension.alwaysEstrus) estrusLevel = EstrusLevel.Visible;
else if (extension.neverEstrus) estrusLevel = EstrusLevel.None;
ovulationFactor *= extension.ovulationFactor;
if (extension.noBleeding) noBleeding = true;
}
public void DirtyStats()
{ {
eggLifeSpanTicks = GenDate.DaysToTicks(Props.eggLifespanDays); eggLifeSpanTicks = GenDate.DaysToTicks(Props.eggLifespanDays);
estrusLevel = Props.concealedEstrus ? EstrusLevel.Concealed : EstrusLevel.Visible; estrusLevel = Props.concealedEstrus ? EstrusLevel.Concealed : EstrusLevel.Visible;
@ -680,19 +689,31 @@ namespace RJW_Menstruation
noBleeding = false; noBleeding = false;
opcache = null; opcache = null;
if (Pawn.genes == null || !ModsConfig.BiotechActive) return; MenstruationModExtension thingExtension = Pawn.def.GetModExtension<MenstruationModExtension>();
foreach (MenstruationModExtension extension in Pawn.genes.GenesListForReading.Where(gene => gene.Active).Select(gene => gene.def.GetModExtension<MenstruationModExtension>()).Where(ext => ext != null)) if (thingExtension != null)
{ ProcessExtension(thingExtension);
eggLifeSpanTicks = (int)(eggLifeSpanTicks * extension.eggLifeTimeFactor);
if (extension.alwaysEstrus) estrusLevel = EstrusLevel.Visible; if (Pawn.genes != null && ModsConfig.BiotechActive)
else if (extension.neverEstrus) estrusLevel = EstrusLevel.None; foreach (MenstruationModExtension geneExtension in Pawn.genes.GenesListForReading.Where(gene => gene.Active).Select(gene => gene.def.GetModExtension<MenstruationModExtension>()).Where(ext => ext != null))
ovulationFactor *= extension.ovulationFactor; ProcessExtension(geneExtension);
if (extension.noBleeding) noBleeding = true;
} foreach (MenstruationModExtension hediffExtension in Pawn.health.hediffSet.hediffs.Select(hediff => hediff.def.GetModExtension<MenstruationModExtension>()).Where(ext => ext != null))
ProcessExtension(hediffExtension);
if (eggLifeSpanTicks < 0) eggLifeSpanTicks = 0; if (eggLifeSpanTicks < 0) eggLifeSpanTicks = 0;
if (ovulationFactor < 0f) ovulationFactor = 0f; if (ovulationFactor < 0f) ovulationFactor = 0f;
} }
public void Notify_UpdatedGenes()
{
DirtyStats();
}
public void Notify_HediffsChanged()
{
DirtyStats();
}
public bool ShouldSimulate() public bool ShouldSimulate()
{ {
if (!Pawn.ShouldCycle()) return false; if (!Pawn.ShouldCycle()) return false;
@ -861,6 +882,11 @@ namespace RJW_Menstruation
return cums?.Find(cum => !cum.notcum && cum.pawn == pawn); return cums?.Find(cum => !cum.notcum && cum.pawn == pawn);
} }
public IEnumerable<Cum> GetFluids()
{
return cums ?? Enumerable.Empty<Cum>();
}
public IEnumerable<Cum> GetFluids(Pawn pawn) public IEnumerable<Cum> GetFluids(Pawn pawn)
{ {
return cums?.Where(cum => cum.pawn == pawn) ?? Enumerable.Empty<Cum>(); return cums?.Where(cum => cum.pawn == pawn) ?? Enumerable.Empty<Cum>();
@ -1229,7 +1255,7 @@ namespace RJW_Menstruation
protected virtual void PreInitialize() protected virtual void PreInitialize()
{ {
Notify_UpdatedGenes(); DirtyStats();
} }
protected virtual void PostInitialize() protected virtual void PostInitialize()
@ -1455,7 +1481,7 @@ namespace RJW_Menstruation
try try
{ {
if (Configurations.Debug) Log.Message($"Implanting fertilized egg of {Pawn} into {parent}, father {egg.fertilizer}"); if (Configurations.Debug) Log.Message($"Implanting fertilized egg of {Pawn} into {parent}, father {egg.fertilizer}");
if (pregnancy == null) if (pregnancy == null) // Support pregnancy list, maybe split off into function
{ {
Configurations.PregnancyType usePregnancy = xxx.is_human(Pawn) ? Configurations.PregnancySource : Configurations.PregnancyType.MultiplePregnancy; Configurations.PregnancyType usePregnancy = xxx.is_human(Pawn) ? Configurations.PregnancySource : Configurations.PregnancyType.MultiplePregnancy;
switch (usePregnancy) switch (usePregnancy)
@ -1473,7 +1499,7 @@ namespace RJW_Menstruation
case Configurations.PregnancyType.MultiplePregnancy: case Configurations.PregnancyType.MultiplePregnancy:
if (Configurations.Debug) Log.Message($"Creating new menstruation pregnancy"); if (Configurations.Debug) Log.Message($"Creating new menstruation pregnancy");
pregnancy = Hediff_BasePregnancy.Create<Hediff_MultiplePregnancy>(Pawn, egg.fertilizer); pregnancy = Hediff_BasePregnancy.Create<Hediff_MultiplePregnancy>(Pawn, egg.fertilizer); // Add fertility comp of mother
pregnant = true; pregnant = true;
deadeggs.Add(egg); deadeggs.Add(egg);
break; break;
@ -1830,6 +1856,7 @@ namespace RJW_Menstruation
protected virtual void ThoughtCumInside(Pawn cummer) protected virtual void ThoughtCumInside(Pawn cummer)
{ {
const int haterThreshold = -5;
MemoryThoughtHandler cummerMemories = cummer?.needs?.mood?.thoughts.memories; MemoryThoughtHandler cummerMemories = cummer?.needs?.mood?.thoughts.memories;
MemoryThoughtHandler pawnMemories = Pawn?.needs?.mood?.thoughts.memories; MemoryThoughtHandler pawnMemories = Pawn?.needs?.mood?.thoughts.memories;
@ -1837,7 +1864,7 @@ namespace RJW_Menstruation
if (cummer.IsProPregnancy(out Precept preceptm) || (cummer.IsTeratophile() != (Pawn.GetStatValue(StatDefOf.PawnBeauty) >= 0))) if (cummer.IsProPregnancy(out Precept preceptm) || (cummer.IsTeratophile() != (Pawn.GetStatValue(StatDefOf.PawnBeauty) >= 0)))
{ {
if (cummer.relations.OpinionOf(Pawn) <= -5) if (cummer.relations.OpinionOf(Pawn) <= haterThreshold)
cummerMemories.TryGainMemory(VariousDefOf.HaterCameInsideM, Pawn); cummerMemories.TryGainMemory(VariousDefOf.HaterCameInsideM, Pawn);
else if (preceptm != null) else if (preceptm != null)
cummerMemories.TryGainMemory(VariousDefOf.CameInsideMIdeo, Pawn, preceptm); cummerMemories.TryGainMemory(VariousDefOf.CameInsideMIdeo, Pawn, preceptm);
@ -1851,14 +1878,14 @@ namespace RJW_Menstruation
{ {
if (preceptf != null) if (preceptf != null)
{ {
if (Pawn.relations.OpinionOf(cummer) <= -5) if (Pawn.relations.OpinionOf(cummer) <= haterThreshold)
pawnMemories.TryGainMemory(VariousDefOf.HaterCameInsideFIdeo, cummer, preceptf); pawnMemories.TryGainMemory(VariousDefOf.HaterCameInsideFIdeo, cummer, preceptf);
else else
pawnMemories.TryGainMemory(VariousDefOf.CameInsideFIdeo, cummer, preceptf); pawnMemories.TryGainMemory(VariousDefOf.CameInsideFIdeo, cummer, preceptf);
} }
else pawnMemories.TryGainMemory(VariousDefOf.CameInsideFFetish, cummer); else pawnMemories.TryGainMemory(VariousDefOf.CameInsideFFetish, cummer);
} }
else if (Pawn.relations.OpinionOf(cummer) <= -5) else if (Pawn.relations.OpinionOf(cummer) <= haterThreshold)
pawnMemories.TryGainMemory(VariousDefOf.HaterCameInsideF, cummer); pawnMemories.TryGainMemory(VariousDefOf.HaterCameInsideF, cummer);
else if (Pawn.IsInEstrus() && Pawn.relations.OpinionOf(cummer) < RJWHookupSettings.MinimumRelationshipToHookup) else if (Pawn.IsInEstrus() && Pawn.relations.OpinionOf(cummer) < RJWHookupSettings.MinimumRelationshipToHookup)
pawnMemories.TryGainMemory(VariousDefOf.HaterCameInsideFEstrus, cummer); pawnMemories.TryGainMemory(VariousDefOf.HaterCameInsideFEstrus, cummer);
@ -1872,7 +1899,7 @@ namespace RJW_Menstruation
{ {
if (Pawn.IsProPregnancy(out Precept _)) if (Pawn.IsProPregnancy(out Precept _))
pawnMemories.TryGainMemory(VariousDefOf.CameInsideFFetishSafe, cummer); pawnMemories.TryGainMemory(VariousDefOf.CameInsideFFetishSafe, cummer);
else if (Pawn.relations.OpinionOf(cummer) <= -5) else if (Pawn.relations.OpinionOf(cummer) <= haterThreshold)
pawnMemories.TryGainMemory(VariousDefOf.HaterCameInsideFSafe, cummer); pawnMemories.TryGainMemory(VariousDefOf.HaterCameInsideFSafe, cummer);
} }
} }

View file

@ -87,35 +87,27 @@ namespace RJW_Menstruation
return 1.0f - Mathf.Pow(1.0f - Configurations.FertilizeChance, comp.TotalFertCum * comp.Props.basefertilizationChanceFactor); return 1.0f - Mathf.Pow(1.0f - Configurations.FertilizeChance, comp.TotalFertCum * comp.Props.basefertilizationChanceFactor);
} }
public static string GetSingleBabyImage(HediffComp_Menstruation comp, Hediff pregnancy)
{
ThingDef babydef;
HediffComp_PregeneratedBabies babiescomp = pregnancy?.TryGetComp<HediffComp_PregeneratedBabies>();
if (pregnancy.IsMechanoidPregnant()) babydef = (pregnancy as Hediff_BasePregnancy)?.babies?.FirstOrDefault()?.def ?? VariousDefOf.Scyther;
else if (pregnancy is Hediff_BasePregnancy preg) babydef = preg.babies?.FirstOrDefault()?.def ?? ThingDefOf.Human;
else if (babiescomp?.HasBaby ?? false) babydef = babiescomp.PeekBaby().def;
else babydef = comp.Pawn.def;
return babydef.GetModExtension<PawnDNAModExtension>()?.fetusTexPath ?? "Fetus/Fetus_Default";
}
public static Texture2D GetPregnancyIcon(this HediffComp_Menstruation comp, Hediff hediff) public static Texture2D GetPregnancyIcon(this HediffComp_Menstruation comp, Hediff hediff)
{ {
float gestationProgress = comp.StageProgress; float gestationProgress = comp.StageProgress;
ThingDef babydef;
int babycount; int babycount;
HediffComp_PregeneratedBabies babiescomp = hediff?.TryGetComp<HediffComp_PregeneratedBabies>(); if (hediff is Hediff_BasePregnancy preg) babycount = preg.babies?.Count ?? 1;
if (hediff.IsMechanoidPregnant()) else babycount = hediff?.TryGetComp<HediffComp_PregeneratedBabies>()?.BabyCount ?? 1;
{
babydef = (hediff as Hediff_BasePregnancy)?.babies?.FirstOrDefault()?.def ?? VariousDefOf.Scyther;
babycount = 1;
}
else if (hediff is Hediff_BasePregnancy preg)
{
babydef = preg.babies?.FirstOrDefault()?.def ?? ThingDefOf.Human;
babycount = preg.babies?.Count ?? 1;
}
else if (babiescomp?.HasBaby ?? false)
{
babydef = babiescomp.PeekBaby().def;
babycount = babiescomp.BabyCount;
}
else
{
babydef = comp.Pawn.def;
babycount = 1;
}
string fetustex = babydef.GetModExtension<PawnDNAModExtension>()?.fetusTexPath ?? "Fetus/Fetus_Default"; string fetustex = GetSingleBabyImage(comp, hediff);
string icon; string icon;
if (gestationProgress < 0.2f) icon = comp.WombTex + "_Implanted"; if (gestationProgress < 0.2f) icon = comp.WombTex + "_Implanted";
else if (gestationProgress < 0.4f) icon = fetustex + "00"; else if (gestationProgress < 0.4f) icon = fetustex + "00";
@ -316,11 +308,11 @@ namespace RJW_Menstruation
return ContentFinder<Texture2D>.Get(icon, true); return ContentFinder<Texture2D>.Get(icon, true);
} }
public static Texture2D GetAnalIcon(this Pawn pawn) // comp used by Menstruation Fluids
public static Texture2D GetAnalIcon(this Pawn pawn, HediffComp_Menstruation comp)
{ {
Hediff hediff = pawn.health.hediffSet.hediffs.FirstOrDefault(h => VariousDefOf.AllAnuses.Contains(h.def)) ?? if (!pawn.GetAnusList().Any()) return ContentFinder<Texture2D>.Get("Genitals/Anal00", true);
pawn.health.hediffSet.hediffs.FirstOrDefault(h => h.def.defName.ToLower().Contains("anus")); Hediff hediff = pawn.GetAnusList().MaxBy(a => a.Severity);
if (hediff == null) return ContentFinder<Texture2D>.Get("Genitals/Anal00", true);
string icon = ((CompProperties_Anus)hediff.GetAnusComp()?.props)?.analTex ?? "Genitals/Anal"; string icon = ((CompProperties_Anus)hediff.GetAnusComp()?.props)?.analTex ?? "Genitals/Anal";
float severity = hediff.Severity; float severity = hediff.Severity;

View file

@ -10,6 +10,12 @@ namespace RJW_Menstruation
{ {
protected Dictionary<Pawn, Pawn> enzygoticSiblings = new Dictionary<Pawn, Pawn>(); // Each pawn and who they split from protected Dictionary<Pawn, Pawn> enzygoticSiblings = new Dictionary<Pawn, Pawn>(); // Each pawn and who they split from
// used by Eltoro's addons
public override void PostMake()
{
base.PostMake();
}
public override void DiscoverPregnancy() public override void DiscoverPregnancy()
{ {
PregnancyThought(); PregnancyThought();

View file

@ -0,0 +1,138 @@
using RimWorld;
using UnityEngine;
using Verse;
namespace RJW_Menstruation.MainTab
{
public class PawnColumnWorker_WombStatus : PawnColumnWorker
{
private const float CellIconSize = 24f;
private const float ProgressBarHeight = 2f;
private const float IconScale = 0.85f;
private const int HasVisibleWombOffset = 100;
public override void DoCell(Rect rect, Pawn pawn, PawnTable table)
{
HediffComp_Menstruation comp = GetDisplayComp(pawn);
if (comp == null) return;
Gizmo_Womb gizmo = Pawn_GetGizmos.CreateGizmo_WombStatus(pawn, comp);
Rect iconRect = new Rect(
rect.x + (rect.width - CellIconSize) / 2f,
rect.y + Mathf.Max((rect.height - CellIconSize) / 2f, 0f),
CellIconSize,
CellIconSize);
DrawCellIcon(iconRect, gizmo);
if (Mouse.IsOver(iconRect) && !gizmo.defaultDesc.NullOrEmpty())
{
TooltipHandler.TipRegion(iconRect, gizmo.defaultDesc);
}
if (Widgets.ButtonInvisible(iconRect, doMouseoverSound: false))
{
Dialog_WombStatus.ToggleWindow(pawn, comp);
}
}
public override int GetMinWidth(PawnTable table)
{
return 30;
}
public override int GetMaxWidth(PawnTable table)
{
return GetMinWidth(table);
}
public override int GetMinCellHeight(Pawn pawn)
{
return 30;
}
public override int Compare(Pawn a, Pawn b)
{
int result = GetSortValue(a).CompareTo(GetSortValue(b));
if (result != 0) return result;
return string.CompareOrdinal(a.LabelShortCap, b.LabelShortCap);
}
private static HediffComp_Menstruation GetDisplayComp(Pawn pawn)
{
if (!pawn.ShowStatus() || !pawn.ShouldCycle()) return null;
HediffComp_Menstruation comp = pawn.GetFirstMenstruationComp();
if (comp == null) return null;
if (!Configurations.ShowInfertileIcon &&
(comp.CurrentVisibleStage == HediffComp_Menstruation.Stage.Infertile ||
comp.CurrentVisibleStage == HediffComp_Menstruation.Stage.None))
{
return null;
}
return comp;
}
private static int GetSortValue(Pawn pawn)
{
if (!pawn.ShowStatus() || !pawn.ShouldCycle()) return int.MinValue;
HediffComp_Menstruation comp = pawn.GetFirstMenstruationComp();
if (comp == null) return int.MinValue + 1;
return HasVisibleWombOffset + GetStageSortValue(comp.CurrentVisibleStage);
}
private static int GetStageSortValue(HediffComp_Menstruation.Stage stage)
{
switch (stage)
{
case HediffComp_Menstruation.Stage.Luteal:
return 9;
case HediffComp_Menstruation.Stage.Ovulatory:
return 8;
case HediffComp_Menstruation.Stage.Follicular:
return 7;
case HediffComp_Menstruation.Stage.Pregnant:
return 6;
case HediffComp_Menstruation.Stage.Bleeding:
return 5;
case HediffComp_Menstruation.Stage.Recover:
return 4;
case HediffComp_Menstruation.Stage.Anestrus:
return 3;
case HediffComp_Menstruation.Stage.Infertile:
return 2;
case HediffComp_Menstruation.Stage.None:
return 1;
default:
return 0;
}
}
private static void DrawCellIcon(Rect rect, Gizmo_Womb gizmo)
{
Texture baseIcon = gizmo.icon ?? BaseContent.BadTex;
Texture overlay = gizmo.icon_overlay ?? BaseContent.BadTex;
Widgets.DrawTextureFitted(rect, baseIcon, IconScale);
Color oldColor = GUI.color;
GUI.color = gizmo.cumcolor;
Widgets.DrawTextureFitted(rect, overlay, IconScale);
GUI.color = Color.white;
if (Configurations.DrawEggOverlay)
{
gizmo.comp.DrawEggOverlay(rect, false);
}
Rect progressRect = new Rect(rect.x + 2f, rect.y, rect.width - 4f, ProgressBarHeight);
Widgets.FillableBar(progressRect, gizmo.comp.StageProgress, gizmo.comp.GetStageTexture);
GUI.color = oldColor;
}
}
}

View file

@ -204,6 +204,17 @@ namespace RJW_Menstruation
} }
} }
[HarmonyPatch(typeof(Pawn_HealthTracker), nameof(Pawn_HealthTracker.CheckForStateChange))]
public class CheckForStateChange_Patch
{
public static void Postfix(Pawn ___pawn, Hediff hediff)
{
if (hediff == null || !hediff.def.HasModExtension<MenstruationModExtension>()) return;
foreach (HediffComp_Menstruation comp in ___pawn.GetMenstruationComps())
comp.Notify_HediffsChanged();
}
}
[HarmonyPatch(typeof(Pawn_GeneTracker), "Notify_GenesChanged")] [HarmonyPatch(typeof(Pawn_GeneTracker), "Notify_GenesChanged")]
public class Notify_GenesChanged_Patch public class Notify_GenesChanged_Patch
{ {

View file

@ -46,7 +46,7 @@ namespace RJW_Menstruation
} }
private static Gizmo CreateGizmo_WombStatus(Pawn pawn, HediffComp_Menstruation comp) internal static Gizmo_Womb CreateGizmo_WombStatus(Pawn pawn, HediffComp_Menstruation comp)
{ {
if (!comp.loaded) if (!comp.loaded)
comp.Initialize(); comp.Initialize();

View file

@ -23,7 +23,7 @@ namespace RJW_Menstruation
if (sextype != xxx.rjwSextype.Vaginal && sextype != xxx.rjwSextype.DoublePenetration) return true; if (sextype != xxx.rjwSextype.Vaginal && sextype != xxx.rjwSextype.DoublePenetration) return true;
if (!mother.ShouldCycle()) return true; if (!mother.ShouldCycle()) return true;
if (!InteractionCanCausePregnancy(props)) return false; if (!InteractionCanCausePregnancy(props)) return true;
List<Hediff> pawnparts = Genital_Helper.get_PartsHediffList(father, Genital_Helper.get_genitalsBPR(father)); List<Hediff> pawnparts = Genital_Helper.get_PartsHediffList(father, Genital_Helper.get_genitalsBPR(father));

View file

@ -90,6 +90,7 @@
<Compile Include="HediffComps\HediffComp_Breast.cs" /> <Compile Include="HediffComps\HediffComp_Breast.cs" />
<Compile Include="Hediff_MultiplePregnancy.cs" /> <Compile Include="Hediff_MultiplePregnancy.cs" />
<Compile Include="JobDrivers.cs" /> <Compile Include="JobDrivers.cs" />
<Compile Include="MainTab\PawnColumnWorker_WombStatus.cs" />
<Compile Include="UI\Gizmo_Womb.cs" /> <Compile Include="UI\Gizmo_Womb.cs" />
<Compile Include="Patch\Harmony.cs" /> <Compile Include="Patch\Harmony.cs" />
<Compile Include="HediffComps\HediffComp_Menstruation.cs" /> <Compile Include="HediffComps\HediffComp_Menstruation.cs" />
@ -178,4 +179,4 @@
</Content> </Content>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View file

@ -390,7 +390,7 @@ namespace RJW_Menstruation
Rect genitalAnusLabelRect = new Rect(rect.x, rect.y + fontheight + genitalRectHeight, genitalRectWidth, fontheight); Rect genitalAnusLabelRect = new Rect(rect.x, rect.y + fontheight + genitalRectHeight, genitalRectWidth, fontheight);
vagina = pawn.GetGenitalIcon(comp); vagina = pawn.GetGenitalIcon(comp);
anal = pawn.GetAnalIcon(); anal = pawn.GetAnalIcon(comp);
GUI.color = new Color(1.00f, 0.47f, 0.47f, 1); GUI.color = new Color(1.00f, 0.47f, 0.47f, 1);
GUI.Box(rect, "", boxstyle); GUI.Box(rect, "", boxstyle);
GUI.color = Utility.SafeSkinColor(pawn); GUI.color = Utility.SafeSkinColor(pawn);

View file

@ -188,60 +188,9 @@ namespace RJW_Menstruation
public static void DrawBreastIcon(this Pawn pawn, Rect rect) public static void DrawBreastIcon(this Pawn pawn, Rect rect)
{ {
Hediff hediff = pawn.health.hediffSet.hediffs.FirstOrDefault(h => VariousDefOf.AllBreasts.Contains(h.def));
Texture2D breast, nipple, areola; Texture2D breast, nipple, areola;
if (hediff != null) int breastCount = pawn.GetBreastList().Count();
{ if (breastCount == 0)
HediffComp_Breast comp = hediff.TryGetComp<HediffComp_Breast>();
string icon;
if (comp != null) icon = comp.BreastTex ?? "Breasts/Breast_Breast";
else
{
breast = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00", false);
nipple = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00_Nipple00", false);
areola = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00_Areola00", false);
GUI.color = SafeSkinColor(pawn);
GUI.DrawTexture(rect, breast, ScaleMode.ScaleToFit);
GUI.color = Color.white;
GUI.DrawTexture(rect, areola, ScaleMode.ScaleToFit);
GUI.DrawTexture(rect, nipple, ScaleMode.ScaleToFit);
return;
}
if (hediff.Severity < 0.20f) icon += "_Breast00";
else if (hediff.Severity < 0.40f) icon += "_Breast01";
else if (hediff.Severity < 0.60f) icon += "_Breast02";
else if (hediff.Severity < 0.80f) icon += "_Breast03";
else if (hediff.Severity < 1.00f) icon += "_Breast04";
else icon += "_Breast05";
string nippleicon, areolaicon;
float nipplesize, areolasize;
nipplesize = comp.NippleSize;
areolasize = comp.AreolaSize;
nippleicon = icon + "_Nipple0" + GetNippleIndex(nipplesize);
areolaicon = icon + "_Areola0" + GetAreolaIndex(areolasize);
breast = ContentFinder<Texture2D>.Get(icon, false);
areola = ContentFinder<Texture2D>.Get(areolaicon, false);
nipple = ContentFinder<Texture2D>.Get(nippleicon, false);
GUI.color = SafeSkinColor(pawn);
GUI.DrawTexture(rect, breast, ScaleMode.ScaleToFit);
GUI.color = comp.NippleColor;
GUI.DrawTexture(rect, areola, ScaleMode.ScaleToFit);
GUI.DrawTexture(rect, nipple, ScaleMode.ScaleToFit);
if (Configurations.Debug) TooltipHandler.TipRegion(rect, comp.DebugInfo());
}
else
{ {
breast = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00", false); breast = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00", false);
nipple = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00_Nipple00", false); nipple = ContentFinder<Texture2D>.Get("Breasts/Breast_Breast00_Nipple00", false);
@ -251,10 +200,42 @@ namespace RJW_Menstruation
GUI.DrawTexture(rect, breast, ScaleMode.ScaleToFit); GUI.DrawTexture(rect, breast, ScaleMode.ScaleToFit);
GUI.color = Color.white; GUI.color = Color.white;
GUI.DrawTexture(rect, areola, ScaleMode.ScaleToFit); GUI.DrawTexture(rect, areola, ScaleMode.ScaleToFit);
GUI.DrawTexture(rect, nipple, ScaleMode.ScaleToFit); GUI.DrawTexture(rect, nipple, ScaleMode.ScaleToFit);
return;
} }
Hediff hediff = pawn.GetBreastList().MaxBy(h => h.Severity);
HediffComp_Breast comp = hediff.TryGetComp<HediffComp_Breast>();
string icon;
if (breastCount > 1) icon = "Breasts_Udder/Breast";
else icon = comp?.BreastTex ?? "Breasts/Breast";
if (hediff.Severity < 0.20f) icon += "_Breast00";
else if (hediff.Severity < 0.40f) icon += "_Breast01";
else if (hediff.Severity < 0.60f) icon += "_Breast02";
else if (hediff.Severity < 0.80f) icon += "_Breast03";
else if (hediff.Severity < 1.00f) icon += "_Breast04";
else icon += "_Breast05";
string nippleicon, areolaicon;
float nipplesize, areolasize;
nipplesize = comp?.NippleSize ?? 0.4f;
areolasize = comp?.AreolaSize ?? 0.4f;
nippleicon = icon + "_Nipple0" + GetNippleIndex(nipplesize);
areolaicon = icon + "_Areola0" + GetAreolaIndex(areolasize);
breast = ContentFinder<Texture2D>.Get(icon, false);
areola = ContentFinder<Texture2D>.Get(areolaicon, false);
nipple = ContentFinder<Texture2D>.Get(nippleicon, false);
GUI.color = SafeSkinColor(pawn);
GUI.DrawTexture(rect, breast, ScaleMode.ScaleToFit);
GUI.color = comp?.NippleColor ?? Color.white;
GUI.DrawTexture(rect, areola, ScaleMode.ScaleToFit);
GUI.DrawTexture(rect, nipple, ScaleMode.ScaleToFit);
if (Configurations.Debug && comp != null) TooltipHandler.TipRegion(rect, comp.DebugInfo());
} }
public static int GetNippleIndex(float nipplesize) public static int GetNippleIndex(float nipplesize)
@ -358,7 +339,7 @@ namespace RJW_Menstruation
} }
public static string GetBreastLabel(this Pawn pawn) public static string GetBreastLabel(this Pawn pawn)
{ {
Hediff hediff = pawn.health.hediffSet.hediffs.FirstOrDefault(h => VariousDefOf.AllBreasts.Contains(h.def)); Hediff hediff = pawn.health.hediffSet.hediffs.Where(h => VariousDefOf.AllBreasts.Contains(h.def)).MaxByWithFallback(h => h.Severity);
if (hediff != null) return hediff.LabelBase.CapitalizeFirst() + "\n(" + hediff.LabelInBrackets + ")"; if (hediff != null) return hediff.LabelBase.CapitalizeFirst() + "\n(" + hediff.LabelInBrackets + ")";
else return ""; else return "";
} }

View file

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

View file

@ -1,3 +1,17 @@
Version 1.6.2.4
- Fix error on startup and missing womb status in RJW tab with RJW 6.1.4.
Version 1.6.2.3
- Fix multiple breasts not appearing in the menstruation UI.
- Status of wombs now appears in RJW main tab, contributed by GhostClinic.
Version 1.6.2.2
- Pawns with multiple breasts will now display an udder in the menstruation UI.
- Updated Traditional Chinese translation by Hydrogen.
Version 1.6.2.1
- Modifiers in MenstruationModExtensions in ThingDefs and HediffDefs now function.
Version 1.6.2.0 Version 1.6.2.0
- Added support for adding the MenstruationModExtension to ThingDefs and HediffDefs. - Added support for adding the MenstruationModExtension to ThingDefs and HediffDefs.
- This can be used to disable the menstrual cycle on pawns of particular types and with particular hediffs. - This can be used to disable the menstrual cycle on pawns of particular types and with particular hediffs.