code:
using RimWorld;
using rjw;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Verse;
using Verse.Sound;

namespace RJW_Menstruation
{
    public class Dialog_WombStatus : Window
    {
        public Pawn pawn;
        private HediffComp_Menstruation comp;
        private const float windowMargin = 20f;
        private const float pawnRectWidth = 150f;
        private const float pawnRectHeight = 150f;
        private const float wombRectHeight = 300f;
        private const float wombRectWidth = 300f;
        private const float fontheight = 30;
        private const float genitalRectWidth = 102;
        private const float genitalRectHeight = 140;
        private const float breastRectWidth = 102;
        private const float breastRectHeight = 100;

        private static bool naked = false;

        private Texture2D womb;
        private Texture2D cum;
        private Texture2D vagina;
        private Texture2D anal;
        private Color cumcolor;

        private static GUIStyle fontstylecenter = null;
        private static GUIStyle fontstyleright = null;
        private static GUIStyle fontstyleleft = null;
        private static GUIStyle boxstyle = null;
        private static GUIStyle buttonstyle = null;

        public Pawn Pawn
        {
            get
            {
                return pawn;
            }
        }
        public HediffComp_Menstruation Comp
        {
            get
            {
                return comp;
            }
        }

        public override Vector2 InitialSize
        {
            get
            {
                float width = 450f + 2 * windowMargin;
                float height = 780f + 2 * windowMargin;
                if (!Configurations.DrawWombStatus) height -= wombRectHeight;
                if (!Configurations.DrawVaginaStatus || pawn.IsAnimal()) width -= 150f;
                return new Vector2(width, height);
            }
        }

        public Dialog_WombStatus(Pawn pawn, HediffComp_Menstruation comp)
        {
            this.pawn = pawn;
            this.comp = comp;
        }

        public void ChangePawn(Pawn pawn, HediffComp_Menstruation comp)
        {

            if (this.pawn.IsAnimal() && !pawn.IsAnimal()) windowRect.width += 150f;
            else if (!this.pawn.IsAnimal() && pawn.IsAnimal()) windowRect.width -= 150f;
            this.pawn = pawn;
            this.comp = comp;
        }

        public static void ToggleWindow(Pawn pawn, HediffComp_Menstruation comp)
        {
            Dialog_WombStatus window = (Dialog_WombStatus)Find.WindowStack.Windows.FirstOrDefault(x => x.GetType().Equals(typeof(Dialog_WombStatus)));
            if (window != null)
            {
                List<Pawn> pawns = Find.Selector.SelectedPawns.FindAll(x => x.ShouldShowWombGizmo());
                if (Input.GetKey(VariousDefOf.OpenStatusWindowKey.MainKey) && !pawns.NullOrEmpty() && pawns.Count > 1)
                {
                    int index = pawns.IndexOf(window.pawn);
                    SoundDefOf.TabOpen.PlayOneShotOnCamera();
                    Pawn newpawn = pawns[(index + 1) % pawns.Count];
                    window.ChangePawn(newpawn, newpawn.GetFirstMenstruationComp());
                }
                else if (window.pawn != pawn)
                {
                    SoundDefOf.TabOpen.PlayOneShotOnCamera();
                    window.ChangePawn(pawn, comp);
                }
                else Find.WindowStack.TryRemove(typeof(Dialog_WombStatus), true);
            }
            else
            {
                SoundDefOf.InfoCard_Open.PlayOneShotOnCamera();
                Find.WindowStack.Add(new Dialog_WombStatus(pawn, comp));
            }

        }

        public override void DoWindowContents(Rect inRect)
        {
            soundClose = SoundDefOf.InfoCard_Close;
            //closeOnClickedOutside = true;
            absorbInputAroundWindow = false;
            forcePause = false;
            preventCameraMotion = false;
            draggable = true;
            //resizeable = true;

            if (Event.current.type == EventType.KeyDown && (Event.current.keyCode == KeyCode.Return || Event.current.keyCode == KeyCode.Escape))
            {
                Event.current.Use();
            }

            Rect windowRect = inRect.ContractedBy(windowMargin);
            Rect mainRect = new Rect(windowRect.x, windowRect.y, windowRect.width, windowRect.height);
            Rect closeRect = new Rect(windowRect.xMax, 0f, 20f, 20f);
            MainContents(mainRect);
            if (Widgets.CloseButtonFor(closeRect))
            {
                Close();
            }
            closeRect.x -= 20f;

        }

        public override void PreOpen()
        {
            base.PreOpen();
            if (fontstylecenter == null) fontstylecenter = new GUIStyle() { alignment = TextAnchor.MiddleCenter };
            if (fontstyleright == null) fontstyleright = new GUIStyle() { alignment = TextAnchor.MiddleRight };
            if (fontstyleleft == null) fontstyleleft = new GUIStyle() { alignment = TextAnchor.MiddleLeft };
            if (boxstyle == null) boxstyle = new GUIStyle(GUI.skin.textArea);
            if (buttonstyle == null) buttonstyle = new GUIStyle(GUI.skin.button);
        }

        private void MainContents(Rect mainRect)
        {

            boxstyle.hover = boxstyle.normal;
            boxstyle.onHover = boxstyle.normal;
            boxstyle.onNormal = boxstyle.normal;

            buttonstyle.onHover = buttonstyle.onNormal;
            buttonstyle.hover = buttonstyle.normal;
            boxstyle.border.left = 4; boxstyle.border.right = 4; boxstyle.border.bottom = 4; boxstyle.border.top = 4;

            fontstyleleft.normal.textColor = Color.white;

            float preginfoheight = 0f;
            Hediff hediff = comp.Pregnancy;
            if (hediff != null && Utility.ShowFetusImage(hediff))
            {
                womb = comp.GetPregnancyIcon(hediff);
                if (hediff is Hediff_MultiplePregnancy m)
                {
                    if (m.GestationProgress < 0.2f) cum = comp.GetCumIcon();
                    else cum = ContentFinder<Texture2D>.Get(("Womb/Empty"), true);
                    Pawn fetus = comp.GetFetus();
                    if (fetus != null && Utility.ShowFetusInfo())
                    {
                        string feinfo = PregnancyCommon.GetBabyInfo(m.babies);
                        string fainfo = PregnancyCommon.GetFatherInfo(m.babies, m.pawn, m.is_parent_known) + "  ";
                        if (feinfo.Length + fainfo.Length > 45)
                        {
                            preginfoheight = fontheight + 2;
                            buttonstyle.alignment = TextAnchor.UpperLeft;
                            fontstyleright.alignment = TextAnchor.LowerRight;
                        }
                        else
                        {
                            preginfoheight = fontheight;
                            buttonstyle.alignment = TextAnchor.MiddleLeft;

                        }
                        Rect preginfo = new Rect(0f, mainRect.yMax - wombRectHeight - 2, wombRectWidth, preginfoheight);
                        fontstyleright.normal.textColor = Color.white;
                        GUI.Box(preginfo, feinfo, buttonstyle);
                        GUI.Label(preginfo, fainfo, fontstyleright);
                    }

                }
                else if (hediff is Hediff_BasePregnancy b)
                {
                    if (b.GestationProgress < 0.2f) cum = comp.GetCumIcon();
                    else cum = ContentFinder<Texture2D>.Get(("Womb/Empty"), true);
                    Pawn fetus = comp.GetFetus();
                    if (fetus != null && Utility.ShowFetusInfo())
                    {
                        preginfoheight = fontheight;
                        Rect preginfo = new Rect(0f, mainRect.yMax - wombRectHeight - 2, wombRectWidth, preginfoheight);
                        fontstyleright.normal.textColor = Color.white;
                        fontstyleright.alignment = TextAnchor.MiddleRight;
                        buttonstyle.alignment = TextAnchor.MiddleLeft;

                        string father;

                        if (!b.is_parent_known && Configurations.InfoDetail != Configurations.DetailLevel.All)
                            father = Translations.Dialog_FatherUnknown;
                        else
                            father = b.father.LabelShort;

                        GUI.Box(preginfo, b.babies.Count + " " + fetus.def.label + " " + Translations.Dialog_WombInfo02, buttonstyle);
                        GUI.Label(preginfo, Translations.Dialog_WombInfo03 + ": " + father + "  ", fontstyleright);
                    }
                }
                else if (hediff is HediffWithParents p)
                {
                    if (p is Hediff_Pregnant hp && hp.Severity < 0.2f) cum = comp.GetCumIcon();
                    else cum = ContentFinder<Texture2D>.Get("Womb/Empty", true);
                    HediffComp_PregeneratedBabies babiescomp = p.TryGetComp<HediffComp_PregeneratedBabies>();
                    if (Utility.ShowFetusInfo())
                    {
                        string feinfo = PregnancyCommon.GetBabyInfo(babiescomp?.babies);
                        string fainfo = PregnancyCommon.GetFatherInfo(babiescomp?.babies, babiescomp.Pawn, true) + "  ";    // Keep all parents known, for now

                        if (feinfo == "Null") feinfo = "1 " + (p.Mother ?? pawn).def.label + " " + Translations.Dialog_WombInfo02;
                        if (fainfo == "Null  ")
                        {
                            string father = p.Father?.LabelShort ?? Translations.Dialog_FatherUnknown;
                            fainfo = Translations.Dialog_WombInfo03 + ": " + father + "  ";
                        }

                        if (feinfo.Length + fainfo.Length > 45)
                        {
                            preginfoheight = fontheight + 2;
                            buttonstyle.alignment = TextAnchor.UpperLeft;
                            fontstyleright.alignment = TextAnchor.LowerRight;
                        }
                        else
                        {
                            preginfoheight = fontheight;
                            buttonstyle.alignment = TextAnchor.MiddleLeft;

                        }

                        Rect preginfo = new Rect(0f, mainRect.yMax - wombRectHeight - 2, wombRectWidth, preginfoheight);
                        fontstyleright.normal.textColor = Color.white;
                        GUI.Box(preginfo, feinfo, buttonstyle);
                        GUI.Label(preginfo, fainfo, fontstyleright);
                    }
                }
                else cum = ContentFinder<Texture2D>.Get(("Womb/Empty"), true);
            }
            else
            {
                womb = comp.GetWombIcon();
                cum = comp.GetCumIcon();
            }

            Rect pawnRect = new Rect(0, 0, pawnRectWidth, pawnRectHeight);
            Widgets.DrawTextureFitted(pawnRect, PortraitsCache.Get(pawn, pawnRect.size, Rot4.South, default, 1, true, true, false, !naked), 1.0f);
            if (Widgets.ButtonInvisible(pawnRect))
            {
                naked = !naked;
            }
            Rect pawnLabelRect = new Rect(0, pawnRectHeight, pawnRectWidth, fontheight - 10);
            Rect pawnLabel2Rect = new Rect(0, pawnRectHeight + fontheight - 10, pawnRectWidth, fontheight - 10);
            fontstylecenter.normal.textColor = pawn.DrawColor;
            GUI.Label(pawnLabelRect, pawn.Name?.ToStringFull ?? pawn.Label, fontstylecenter);
            if (pawn.story != null) GUI.Label(pawnLabel2Rect, pawn.ageTracker.AgeBiologicalYears + ", " + pawn.story.Title, fontstylecenter);
            GUI.color = Color.white;

            float wombrecth = 0;
            if (Configurations.DrawWombStatus)
            {
                wombrecth = wombRectHeight;
                cumcolor = comp.GetCumMixtureColor;
                Rect wombRect = new Rect(0f, mainRect.yMax - wombRectHeight + preginfoheight, wombRectWidth, wombRectWidth * 0.9f);
                DrawWomb(wombRect);

                if (Configurations.DrawEggOverlay)
                {
                    comp.DrawEggOverlay(wombRect, true);
                }

            }

            Rect wombInfoRect = new Rect(0f, mainRect.yMax - wombrecth - fontheight - 2, wombRectWidth, fontheight - 4f);
            Rect progressRect = new Rect(wombInfoRect.x, wombInfoRect.yMax, wombRectWidth, 4f);
            buttonstyle.normal.textColor = Color.white;
            //boxstyle.normal.background = Texture2D.whiteTexture;
            buttonstyle.alignment = TextAnchor.MiddleLeft;
            GUI.backgroundColor = new Color(0.24f, 0.29f, 0.35f, 1);
            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;
            fontstyleright.alignment = TextAnchor.MiddleRight;
            //if (comp.GetFertilization) GUI.Label(wombInfoRect, Translations.Dialog_WombInfo05 + "  ", fontstyleright);
            //else if (comp.GetEggFertilizing) GUI.Label(wombInfoRect, Translations.Dialog_WombInfo06 + "  ", fontstyleright);
            //else if (comp.GetEgg) GUI.Label(wombInfoRect, Translations.Dialog_WombInfo07 + "  ", fontstyleright);
            GUI.Label(wombInfoRect, comp.GetFertilizingInfo + "  ", fontstyleright);

            //Widgets.Label(wombInfoRect,Translations.Dialog_WombInfo01 + ": " + comp.GetCurStageLabel);

            Rect cumlistTitle, cumlistRect;
            if (Configurations.DrawVaginaStatus && !pawn.IsAnimal())
            {
                Rect genitalRect = new Rect(pawnRectWidth + 24, pawnRectHeight + 2 * fontheight, genitalRectWidth, genitalRectHeight + fontheight * 2);
                Rect breastRect = new Rect(pawnRectWidth + 24, 40f, breastRectWidth, breastRectHeight + fontheight);
                DrawVagina(genitalRect, comp);
                DrawBreast(breastRect);
                cumlistTitle = new Rect(wombRectWidth + 4f, 0, 150f, fontheight);
                cumlistRect = new Rect(wombRectWidth + 4f, fontheight, 150f, mainRect.yMax - fontheight + preginfoheight + 3);
            }
            else
            {
                cumlistTitle = new Rect(pawnRectWidth, 0, 150f, fontheight);
                cumlistRect = new Rect(pawnRectWidth, fontheight, 150f, mainRect.yMax - wombRectHeight - fontheight);
            }

            Rect infoRect = new Rect(0, pawnRectHeight + 2 * fontheight, pawnRectWidth, pawnRect.yMax + 2 * fontheight - wombInfoRect.y);
            DrawInfos(infoRect);

            GUI.Label(cumlistTitle, Translations.Dialog_WombInfo04);
            DrawCumlist(cumlistRect);

        }

        private void DrawCumlist(Rect rect)
        {
            Listing_Standard cumlist = new Listing_Standard
            {
                maxOneColumn = true,
                ColumnWidth = wombRectWidth - pawnRectWidth
            };
            cumlist.Begin(rect);
            Listing_Standard cumlistsection = cumlist.BeginSection(rect.height - fontheight - 12f);
            foreach (string s in comp.GetCumsInfo)
            {
                cumlistsection.Label(s);
            }
            cumlist.EndSection(cumlistsection);
            cumlist.End();
        }

        private void DrawWomb(Rect rect)
        {
            GUI.color = new Color(1.00f, 0.47f, 0.47f, 1);
            GUI.Box(rect, "", boxstyle);
            //GUI.color = Color.white;
            //Widgets.DrawTextureFitted(wombRect, womb,1.0f);
            //GUI.color = cumcolor;
            //Widgets.DrawTextureFitted(wombRect, cum,1.0f);
            GUI.DrawTexture(rect, womb, ScaleMode.ScaleToFit, true, 0, Color.white, 0, 0);
            GUI.DrawTexture(rect, cum, ScaleMode.ScaleToFit, true, 0, cumcolor, 0, 0);

            GUI.color = Color.white;

        }

        private void DrawVagina(Rect rect, HediffComp_Menstruation comp)
        {
            Rect genitalIconRect = new Rect(rect.x, rect.y + fontheight, genitalRectWidth, genitalRectHeight);
            Rect genitalVaginaLabelRect = new Rect(rect.x, rect.y + 10f, genitalRectWidth, fontheight);
            Rect genitalAnusLabelRect = new Rect(rect.x, rect.y + fontheight + genitalRectHeight, genitalRectWidth, fontheight);

            vagina = pawn.GetGenitalIcon(comp);
            anal = pawn.GetAnalIcon();
            GUI.color = new Color(1.00f, 0.47f, 0.47f, 1);
            GUI.Box(rect, "", boxstyle);
            GUI.color = Utility.SafeSkinColor(pawn);
            //Widgets.DrawTextureFitted(genitalIconRect, anal, 1.0f);
            //Widgets.DrawTextureFitted(genitalIconRect, vagina, 1.0f);
            GUI.DrawTexture(genitalIconRect, anal, ScaleMode.ScaleToFit);
            GUI.DrawTexture(genitalIconRect, vagina, ScaleMode.ScaleToFit);

            GUI.color = Color.white;
            GUI.Label(genitalVaginaLabelRect, pawn.GetVaginaLabel(), fontstylecenter);
            GUI.Label(genitalAnusLabelRect, pawn.GetAnusLabel(), fontstylecenter);
        }

        private void DrawBreast(Rect rect)
        {
            Rect BreastIconRect = new Rect(rect.x, rect.y + fontheight, breastRectWidth, breastRectHeight);
            Rect BreastLabelRect = new Rect(rect.x, rect.y, breastRectWidth, fontheight);
            Rect MilkGaugeRect = new Rect(rect.x, rect.yMax, breastRectWidth, 20f);

            GUI.color = new Color(1.00f, 0.47f, 0.47f, 1);
            GUI.Box(rect, "", boxstyle);

            pawn.DrawBreastIcon(BreastIconRect);

            GUI.color = Color.white;
            GUI.Label(BreastLabelRect, pawn.GetBreastLabel(), fontstylecenter);

            pawn.DrawMilkBars(MilkGaugeRect);

        }

        private void DrawInfos(Rect rect)
        {
            Rect lineRect = new Rect(rect.x, rect.y, rect.width, 20f);
            float statvalue;
            const float height = 24f;
            statvalue = pawn.GetStatValue(xxx.sex_drive_stat);
            FillableBarLabeled(lineRect, "  " + xxx.sex_drive_stat.LabelCap.CapitalizeFirst() + " " + statvalue.ToStringPercent(), statvalue / 2, TextureCache.OvulatoryTexture, Texture2D.blackTexture, xxx.sex_drive_stat.description);
            lineRect.y += height;

            statvalue = pawn.GetStatValue(xxx.vulnerability_stat);
            FillableBarLabeled(lineRect, "  " + xxx.vulnerability_stat.LabelCap.CapitalizeFirst() + " " + statvalue.ToStringPercent(), statvalue / 2, TextureCache.BleedingTexture, Texture2D.blackTexture, xxx.vulnerability_stat.description);
            lineRect.y += height;

            statvalue = pawn.records.GetValue(xxx.CountOfBirthHuman);
            FillableBarLabeled(lineRect, "  " + xxx.CountOfBirthHuman.LabelCap.CapitalizeFirst() + " " + statvalue, statvalue / 10, TextureCache.FollicularTexture, Texture2D.blackTexture, xxx.CountOfBirthHuman.description);
            lineRect.y += height;

            statvalue = pawn.records.GetValue(xxx.CountOfBirthAnimal);
            FillableBarLabeled(lineRect, "  " + xxx.CountOfBirthAnimal.LabelCap.CapitalizeFirst() + " " + statvalue, statvalue / 20, TextureCache.AnimalTexture, Texture2D.blackTexture, xxx.CountOfBirthAnimal.description);
            lineRect.y += height;

            statvalue = pawn.records.GetValue(xxx.CountOfBirthEgg);
            FillableBarLabeled(lineRect, "  " + xxx.CountOfBirthEgg.LabelCap.CapitalizeFirst() + " " + statvalue, statvalue / 100, TextureCache.RecoverTexture, Texture2D.blackTexture, xxx.CountOfBirthEgg.description);
            lineRect.y += height * 3;

            if (ModsConfig.BiotechActive && xxx.is_human(pawn))
            {
                statvalue = comp.OvulationChance;
                FillableBarLabeled(lineRect, "  " + Translations.OvulationChanceLabel(statvalue.ToStringPercent()), statvalue, TextureCache.LutealTexture, Texture2D.blackTexture, Translations.OvulationChanceDesc);
            }
            lineRect.y += height;

            statvalue = Configurations.ImplantationChance * comp.ImplantChance;
            float fertchance = comp.GetFertilityChance();
            FillableBarLabeled(lineRect, "  " + xxx.reproduction.LabelCap.CapitalizeFirst() + " " + statvalue.ToStringPercent(), statvalue, TextureCache.LutealTexture, Texture2D.blackTexture, Translations.FertilityDesc(string.Format("{0:0.##}", fertchance * 100)));
            Rect overlayRect = new Rect(lineRect.x, lineRect.y, lineRect.width * Math.Min(1.0f, fertchance), lineRect.height);
            GUI.DrawTexture(overlayRect, TextureCache.FertChanceTex);
            lineRect.y += height;
        }

        private void FillableBarLabeled(Rect rect, string label, float fillPercent, Texture2D filltexture, Texture2D bgtexture, string tooltip = null)
        {
            Widgets.FillableBar(rect, Math.Min(fillPercent, 1.0f), filltexture, bgtexture, true);
            GUI.Label(rect, label, fontstyleleft);
            Widgets.DrawHighlightIfMouseover(rect);
            if (tooltip != null) TooltipHandler.TipRegion(rect, tooltip);
        }

    }
}


code:
using UnityEngine;
using Verse;

namespace RJW_Menstruation
{
    public class Gizmo_Womb : Command_Action
    {
        public Texture2D icon_overlay;
        public Color cumcolor;
        public HediffComp_Menstruation comp;

        public const float progressbarHeight = 2f;

        public override void DrawIcon(Rect rect, Material buttonMat, GizmoRenderParms parms)
        {
            Texture badTex = icon;
            Texture2D overlay = icon_overlay;
            Color color = cumcolor;

            if (badTex == null)
            {
                badTex = BaseContent.BadTex;
            }
            if (overlay == null)
            {
                overlay = BaseContent.BadTex;
            }
            if (color == null) color = Color.white;
            rect.position += new Vector2(iconOffset.x * rect.size.x, iconOffset.y * rect.size.y);
            GUI.color = IconDrawColor;
            Widgets.DrawTextureFitted(rect, badTex, this.iconDrawScale * 0.85f, this.iconProportions, this.iconTexCoords, this.iconAngle, buttonMat);
            GUI.color = color;
            Widgets.DrawTextureFitted(rect, overlay, iconDrawScale * 0.85f, iconProportions, iconTexCoords, iconAngle, buttonMat);
            GUI.color = Color.white;
            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);

        }

        public override bool GroupsWith(Gizmo other)
        {
            if (other is Gizmo_Womb womb && womb.comp != this.comp) return false;
            else return base.GroupsWith(other);
        }

    }
}

license: unknown


code:
using RimWorld;
using rjw;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Verse;
using Verse.Sound;

namespace RJW_Menstruation
{
    public static class Colors
    {
        public static Color blood = new Color(0.78f, 0, 0);
        //public static Color nippleblack = new Color(0.215f, 0.078f, 0); // 81,20,0
        public static ColorInt white = new ColorInt(255, 255, 255, 255);

        public static Color CMYKLerp(Color a, Color b, float t)
        {
            RGBtoCMYK(a, out float ac, out float am, out float ay, out float ak);
            RGBtoCMYK(b, out float bc, out float bm, out float by, out float bk);

            return CMYKtoRGB(Mathf.Lerp(ac, bc, t), Mathf.Lerp(am, bm, t), Mathf.Lerp(ay, by, t), Mathf.Lerp(ak, bk, t));
        }

        public static void RGBtoCMYK(Color rgb, out float c, out float m, out float y, out float k)
        {
            k = 1 - Math.Max(rgb.r, Math.Max(rgb.g, rgb.b));
            c = (1 - rgb.r - k) / (1 - k);
            m = (1 - rgb.g - k) / (1 - k);
            y = (1 - rgb.b - k) / (1 - k);

        }

        public static Color CMYKtoRGB(float c, float m, float y, float k)
        {
            return new Color((1 - c) * (1 - k), (1 - m) * (1 - k), (1 - y) * (1 - k));
        }

    }

    public static class Utility
    {
        public static PawnKindDef GetRacesPawnKind(Pawn pawn)
        {
            if (pawn == null) return null;
            if (pawn.kindDef?.race == pawn.def) return pawn.kindDef;
            return VariousDefOf.AllKinds.Find(kind => kind.race == pawn.def && kind.defName.Contains("Colonist")) ??
                VariousDefOf.AllKinds.Find(kind => kind.race == pawn.def) ??
                pawn.RaceProps?.AnyPawnKind ??
                pawn.kindDef;
        }

        public static HediffComp_SexPart GetPenisSexPart(this Pawn pawn, List<Hediff> hediffs)
        {
            List<HediffComp_SexPart> parts = hediffs.Select(hed => hed.TryGetComp<HediffComp_SexPart>()).Where(p => p != null).ToList();

            return
                parts.Where(p => p.Def.genitalFamily == GenitalFamily.Penis).RandomElementWithFallback() ??
                parts.Where(p => p.Def.genitalFamily == GenitalFamily.FemaleOvipositor).RandomElementWithFallback() ??
                parts.Where(p => p.Def.genitalFamily == GenitalFamily.MaleOvipositor).RandomElementWithFallback();
        }

        public static float GetCumVolume(this Pawn pawn)
        {
            List<Hediff> hediffs = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn));
            if (hediffs.NullOrEmpty()) return 0;
            else return pawn.GetCumVolume(hediffs);
        }

        public static float GetCumVolume(this Pawn pawn, List<Hediff> hediffs)
        {
            if (hediffs.NullOrEmpty()) return 0.0f;
            return pawn.GetCumVolume(pawn.GetPenisSexPart(hediffs));
        }

        public static float GetCumVolume(this Pawn pawn, HediffComp_SexPart part)
        {
            if (part == null) return 0.0f;

            float res = VariationRange(part.FluidAmount, 0.2f);
            if (pawn.IsMessy()) res *= Rand.Range(4.0f, 8.0f);

            return res;
        }

        public static HediffComp_Breast GetBreastComp(this Pawn pawn)
        {
            return pawn.health.hediffSet.hediffs.FirstOrDefault((Hediff h) => VariousDefOf.AllBreasts.Contains(h.def))?.TryGetComp<HediffComp_Breast>();
        }

        public static HediffComp_Breast GetBreastComp(this Hediff hediff)
        {
            if (hediff is Hediff_NaturalSexPart)
            {
                return hediff.TryGetComp<HediffComp_Breast>();
            }
            return null;
        }

        public static List<ThingComp> GetMilkComps(this Pawn pawn)
        {
            List<ThingComp> milkcomp = pawn.AllComps.FindAll(x => x is CompMilkable || x.GetType().ToString().ToLower().Contains("milkable"));
            return milkcomp;
        }

        public static bool HasMenstruationComp(this Pawn pawn)
        {
            return pawn.GetMenstruationComps().Any();
        }

        public static bool HasMenstruationComp(this Hediff hediff)
        {
            if ((hediff is ISexPartHediff) && hediff.TryGetComp<HediffComp_Menstruation>() != null)
                return true;
            else return false;
        }

        public static bool IsRJWPregnant(this Pawn pawn)
        {
            return pawn.health.hediffSet.GetFirstHediff<Hediff_BasePregnancy>() != null;
        }

        public static bool IsBiotechPregnant(this Pawn pawn)
        {
            if (!ModsConfig.BiotechActive) return false;
            foreach (HediffDef def in pawn.health.hediffSet.hediffs.Select(hediff => hediff.def))
            {
                if (def == HediffDefOf.PregnantHuman || def == HediffDefOf.PregnancyLabor || def == HediffDefOf.PregnancyLaborPushing)
                    return true;
            }
            return false;
        }

        public static float GetFarthestPregnancyProgress(this Pawn pawn)
        {
            if (ModsConfig.BiotechActive)
            {
                foreach (Hediff hediff in pawn.health.hediffSet.hediffs)
                {
                    if (hediff.def == HediffDefOf.PregnancyLabor || hediff.def == HediffDefOf.PregnancyLaborPushing)
                        return 1.0f;
                    if (hediff.def == HediffDefOf.PregnantHuman)
                        return hediff.Severity;
                }
            }
            List<Hediff_BasePregnancy> pregnancies = new List<Hediff_BasePregnancy>();
            pawn.health.hediffSet.GetHediffs(ref pregnancies);
            return pregnancies.MaxByWithFallback(hediff => hediff.GestationProgress)?.GestationProgress ?? 0;
        }

        public static float GetPregnancyProgress(this HediffComp_Menstruation comp)
        {
            if (comp.Pregnancy == null) return 0;
            else return comp.StageProgress;
        }

        public static Pawn GetFetus(this HediffComp_Menstruation comp)
        {
            if (comp.Pregnancy == null) return null;
            if (comp.Pregnancy is Hediff_BasePregnancy rjw_preg)
            {
                if (!rjw_preg.babies.NullOrEmpty()) return rjw_preg.babies.First();
                else
                {
                    Log.Error("Baby not exist: baby was not created or removed. Remove pregnancy.");
                    rjw_preg.Miscarry();
                    return null;
                }
            }
            HediffComp_PregeneratedBabies babiescomp = comp.Pregnancy.TryGetComp<HediffComp_PregeneratedBabies>();
            return babiescomp?.PeekBaby();
        }

        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;
            if (hediff != null)
            {
                HediffComp_Breast comp = hediff.TryGetComp<HediffComp_Breast>();
                string icon;
                if (comp != null) icon = comp.Props?.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);
                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);
            }

        }

        public static int GetNippleIndex(float nipplesize)
        {
            if (nipplesize < 0.25f) return 0;
            else if (nipplesize < 0.50f) return 1;
            else if (nipplesize < 0.75f) return 2;
            else return 3;
        }

        public static int GetAreolaIndex(float nipplesize)
        {
            if (nipplesize < 0.15f) return 0;
            else if (nipplesize < 0.30f) return 1;
            else if (nipplesize < 0.45f) return 2;
            else if (nipplesize < 0.70f) return 3;
            else return 4;
        }

        public static void DrawMilkBars(this Pawn pawn, Rect rect)
        {
            //List<ThingComp> milkcomp = pawn.AllComps.FindAll(x => x is CompMilkable || x.GetType().ToString().ToLower().Contains("milkable"));
            ThingComp milkcomp = null;
            float res = 0;
            if (VariousDefOf.Hediff_Heavy_Lactating_Permanent != null)
            {
                if (pawn.health.hediffSet.HasHediff(VariousDefOf.Hediff_Heavy_Lactating_Permanent)) milkcomp = pawn.AllComps.FirstOrDefault(x => x.GetType().ToString().ToLower().Contains("hypermilkable"));
                else milkcomp = pawn.AllComps.FirstOrDefault(x => x.GetType().ToString().ToLower().Contains("milkable"));
            }
            else
            {
                milkcomp = pawn.GetComp<CompMilkable>();
            }

            if (milkcomp == null) return;
            if (milkcomp is CompMilkable milkable)
            {
                bool active = (bool)milkcomp.GetPropertyValue("Active");
                if (active)
                {
                    CompMilkable m = milkable;
                    res = Math.Max(m.Fullness, res);
                    Widgets.FillableBar(rect, Math.Min(res, 1.0f), TextureCache.MilkTexture, Texture2D.blackTexture, true);
                    DrawMilkBottle(rect, pawn, VariousDefOf.Job_LactateSelf, m.Fullness);
                }
            }
            else
            {
                bool active = (bool)milkcomp.GetPropertyValue("Active");
                if (active)
                {
                    float fullness = (float)milkcomp.GetMemberValue("fullness");
                    res = Math.Max(fullness, res);
                    Widgets.FillableBar(rect, Math.Min(res, 1.0f), TextureCache.MilkTexture, Texture2D.blackTexture, true);
                    DrawMilkBottle(rect, pawn, VariousDefOf.Job_LactateSelf_MC, fullness);
                }
            }
        }

        public static void DrawMilkBottle(Rect rect, Pawn pawn, JobDef milkjob, float fullness)
        {
            Texture2D texture;
            Rect buttonrect = new Rect(rect.x, rect.y, rect.height, rect.height);
            if (fullness <= 0.0f) return;

            if (fullness < 0.3f) texture = ContentFinder<Texture2D>.Get("Milk/Milkbottle_Small", false);
            else if (fullness < 0.7f) texture = ContentFinder<Texture2D>.Get("Milk/Milkbottle_Medium", false);
            else texture = ContentFinder<Texture2D>.Get("Milk/Milkbottle_Large", false);
            GUIContent icon = new GUIContent(texture);
            GUIStyle style = GUIStyle.none;
            style.normal.background = texture;
            string tooltip = Translations.Button_MilkTooltip;

            TooltipHandler.TipRegion(buttonrect, tooltip);
            if (GUI.Button(buttonrect, icon, style))
            {
                if (fullness < 0.1f
                    || !pawn.IsColonistPlayerControlled
                    || pawn.Downed) SoundDefOf.ClickReject.PlayOneShotOnCamera();
                else
                {
                    SoundDefOf.Click.PlayOneShotOnCamera();
                    pawn.jobs.TryTakeOrderedJob(new Verse.AI.Job(milkjob, pawn));
                }
            }
            Widgets.DrawHighlightIfMouseover(buttonrect);
        }

        public static string GetVaginaLabel(this Pawn pawn)
        {
            Hediff hediff = pawn.health.hediffSet.hediffs.Find(h => VariousDefOf.AllVaginas.Contains(h.def));
            return hediff.LabelBase.CapitalizeFirst() + "\n(" + hediff.LabelInBrackets + ")" + "\n" + xxx.CountOfSex.LabelCap.CapitalizeFirst() + ": " + pawn.records.GetAsInt(xxx.CountOfSex);
        }
        public static string GetAnusLabel(this Pawn pawn)
        {
            Hediff hediff = pawn.health.hediffSet.hediffs.FirstOrDefault(h => VariousDefOf.AllAnuses.Contains(h.def)) ??
                Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_anusBPR(pawn)).FirstOrDefault(h => h.def.defName.ToLower().Contains("anus"));
            if (hediff != null) return hediff.LabelBase.CapitalizeFirst() + "\n(" + hediff.LabelInBrackets + ")";
            else return "";
        }
        public static string GetBreastLabel(this Pawn pawn)
        {
            Hediff hediff = pawn.health.hediffSet.hediffs.FirstOrDefault(h => VariousDefOf.AllBreasts.Contains(h.def));
            if (hediff != null) return hediff.LabelBase.CapitalizeFirst() + "\n(" + hediff.LabelInBrackets + ")";
            else return "";
        }

        public static bool ShowFetusImage(this Hediff hediff)
        {
            if (Configurations.InfoDetail == Configurations.DetailLevel.All) return true;
            else if (Configurations.InfoDetail == Configurations.DetailLevel.Hide) return false;
            else if (hediff.Visible) return true;
            else return false;
        }

        public static bool ShowFetusInfo()
        {
            if (Configurations.InfoDetail == Configurations.DetailLevel.All || Configurations.InfoDetail == Configurations.DetailLevel.OnReveal) return true;
            else return false;
        }

        public static bool ShowStatus(this Pawn pawn)
        {
            if (pawn.Faction != null && Configurations.ShowFlag != Configurations.PawnFlags.None)
            {
                if (pawn.Faction.IsPlayer)
                {
                    if ((Configurations.ShowFlag & Configurations.PawnFlags.Colonist) != 0) return true;
                }
                else if (pawn.IsPrisonerOfColony)
                {
                    if ((Configurations.ShowFlag & Configurations.PawnFlags.Prisoner) != 0) return true;
                }
                else if (pawn.Faction.PlayerRelationKind == FactionRelationKind.Ally)
                {
                    if ((Configurations.ShowFlag & Configurations.PawnFlags.Ally) != 0) return true;
                }
                else if (pawn.Faction.PlayerRelationKind == FactionRelationKind.Hostile)
                {
                    if ((Configurations.ShowFlag & Configurations.PawnFlags.Hostile) != 0) return true;
                }
                else if ((Configurations.ShowFlag & Configurations.PawnFlags.Neutral) != 0) return true;
                else return false;
            }
            else if ((Configurations.ShowFlag & Configurations.PawnFlags.Neutral) != 0) return true;

            return false;
        }

        public static Pawn GetFather(Pawn pawn, Pawn mother)
        {
            Pawn res = pawn.GetFather();
            if (res != null) return res;
            else res = pawn.relations?.GetFirstDirectRelationPawn(PawnRelationDefOf.Parent, x => x != mother);
            return res;
        }

        public static float RandGaussianLike(float min, float max, int iterations = 3)
        {
            float res = 0;
            for (int i = 0; i < iterations; i++)
            {
                res += Rand.Value;
            }
            res /= iterations;

            return res * (max - min) + min;

        }

        public static float LerpMultiple(this float a, float b, float t, float num)
        {
            float tmult = Mathf.Pow(1 - t, num);
            return tmult * a + (1 - tmult) * b;
        }

        public static float VariationRange(this float num, float variant)
        {
            return num * Rand.Range(1.0f - variant, 1.0f + variant);
        }

        public static bool ShouldShowWombGizmo(this Pawn pawn)
        {
            if (!Configurations.EnableWombIcon) return false;
            if (pawn.Drafted && !Configurations.EnableDraftedIcon) return false;
            if (!pawn.ShouldCycle()) return false;
            return true;
        }

        // Apparently with some mods, even doing pawn.story?.SkinColor can throw a null reference, so we're stuck doing this
        public static Color SafeSkinColor(Pawn pawn)
        {
            try
            {
                return pawn.story?.SkinColor ?? Color.white;
            }
            catch (NullReferenceException)
            {
                return Color.white;
            }
            catch (InvalidOperationException)   // And sometimes it can try to pull the value of a Nullable without checking, too
            {
                return Color.white;
            }
        }

        public static ThingDef BloodDef(Pawn pawn)
        {
            if (pawn == null) return ThingDefOf.Filth_Blood;
            if (Configurations.VEFActivated)
            {
                ThingDef VEBloodDef = VECompatibility.VEGeneBloodDef(pawn);
                if (VEBloodDef != null) return VEBloodDef;
            }
            if (pawn.Dead && pawn.IsShambler) return MutantDefOf.Shambler.bloodDef;
            if (pawn.IsMutant)
            {
                ThingDef MutantBloodDef = pawn.mutant.Def.bloodDef;
                if (MutantBloodDef != null) return MutantBloodDef;
            }
            return pawn.RaceProps?.BloodDef ?? ThingDefOf.Filth_Blood;
        }
    }
}


code:
using RimWorld;
using rjw;
using System;
using System.Collections.Generic;
using System.Linq;
using Verse;

namespace RJW_Menstruation
{
    public static class VariousDefOf
    {

        public static readonly ThingDef CumFilth = DefDatabase<ThingDef>.GetNamed("FilthCum");
        public static readonly ThingDef GirlCumFilth = DefDatabase<ThingDef>.GetNamed("FilthGirlCum");
        public static readonly ThingDef Tampon = DefDatabase<ThingDef>.GetNamed("Absorber_Tampon");
        public static readonly ThingDef Tampon_Dirty = DefDatabase<ThingDef>.GetNamed("Absorber_Tampon_Dirty");
        public static readonly ThingDef FilthMixture = DefDatabase<ThingDef>.GetNamed("FilthMixture");
        public static readonly ThingDef Scyther = DefDatabase<ThingDef>.GetNamed("Mech_Scyther");
        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_Estrus = DefDatabase<HediffDef>.GetNamed("Hediff_Estrus");
        public static readonly HediffDef Hediff_Estrus_Concealed = DefDatabase<HediffDef>.GetNamed("Hediff_Estrus_Concealed");
        public static readonly HediffDef Hediff_AffectedByPheromones = DefDatabase<HediffDef>.GetNamed("Hediff_AffectedByPheromones");
        public static readonly HediffDef Hediff_ASA = DefDatabase<HediffDef>.GetNamed("Hediff_ASA");
        public static readonly StatDef MaxAbsorbable = DefDatabase<StatDef>.GetNamed("MaxAbsorbable");
        public static readonly NeedDef SexNeed = DefDatabase<NeedDef>.GetNamed("Sex");
        public static readonly JobDef VaginaWashing = DefDatabase<JobDef>.GetNamed("VaginaWashing");
        public static readonly JobDef Job_LactateSelf = DefDatabase<JobDef>.GetNamed("LactateSelf");
        public static readonly ThoughtDef LeakingFluids = DefDatabase<ThoughtDef>.GetNamed("LeakingFluids");
        public static readonly ThoughtDef CameInsideF = DefDatabase<ThoughtDef>.GetNamed("CameInsideF");
        public static readonly ThoughtDef CameInsideFLowFert = DefDatabase<ThoughtDef>.GetNamed("CameInsideFLowFert");
        public static readonly ThoughtDef CameInsideFFetish = DefDatabase<ThoughtDef>.GetNamed("CameInsideFFetish");
        public static readonly ThoughtDef CameInsideFFetishSafe = DefDatabase<ThoughtDef>.GetNamed("CameInsideFFetishSafe");
        public static readonly ThoughtDef HaterCameInsideFSafe = DefDatabase<ThoughtDef>.GetNamed("HaterCameInsideFSafe");
        public static readonly ThoughtDef HaterCameInsideF = DefDatabase<ThoughtDef>.GetNamed("HaterCameInsideF");
        public static readonly ThoughtDef HaterCameInsideFEstrus = DefDatabase<ThoughtDef>.GetNamed("HaterCameInsideFEstrus");
        public static readonly ThoughtDef CameInsideM = DefDatabase<ThoughtDef>.GetNamed("CameInsideM");
        public static readonly ThoughtDef HaterCameInsideM = DefDatabase<ThoughtDef>.GetNamed("HaterCameInsideM");
        public static readonly ThoughtDef UnwantedPregnancy = DefDatabase<ThoughtDef>.GetNamed("UnwantedPregnancy");
        public static readonly ThoughtDef UnwantedPregnancyMild = DefDatabase<ThoughtDef>.GetNamed("UnwantedPregnancyMild");
        public static readonly ThoughtDef TookContraceptivePill = DefDatabase<ThoughtDef>.GetNamed("TookContraceptivePill");
        public static readonly ThoughtDef HateTookContraceptivePill = DefDatabase<ThoughtDef>.GetNamed("HateTookContraceptivePill");
        public static readonly ThoughtDef EggRestorationReceived = DefDatabase<ThoughtDef>.GetNamed("EggRestorationReceived");
        public static readonly CompProperties_Menstruation HumanVaginaCompProperties = Genital_Helper.average_vagina.CompProps<CompProperties_Menstruation>();
        public static readonly KeyBindingDef OpenStatusWindowKey = DefDatabase<KeyBindingDef>.GetNamed("OpenStatusWindow");
        public static readonly RecordDef AmountofCreampied = DefDatabase<RecordDef>.GetNamed("AmountofCreampied");
        public static readonly RecordDef AmountofFertilizedEggs = DefDatabase<RecordDef>.GetNamed("AmountofFertilizedEggs");
        public static readonly TaleDef TaleCameInside = DefDatabase<TaleDef>.GetNamed("CameInside");
        public static readonly BodyPartDef Nose = DefDatabase<BodyPartDef>.GetNamed("Nose");

        private static List<ThingDef> allraces = null;
        private static List<PawnKindDef> allkinds = null;
        private static HashSet<HediffDef> allvaginas = null;
        private static HashSet<HediffDef> allanuses = null;
        private static HashSet<HediffDef> allbreasts = null;
        private static HashSet<GeneDef> egglayergenes = null;

        public static List<ThingDef> AllRaces
        {
            get
            {
                if (allraces != null) return allraces;
                allraces = DefDatabase<ThingDef>.AllDefsListForReading.Where(thingdef => (thingdef.race?.IsFlesh ?? false) && !thingdef.IsCorpse).ToList();

                return allraces;
            }
        }
        public static List<PawnKindDef> AllKinds
        {
            get
            {
                if (allkinds != null) return allkinds;
                allkinds = DefDatabase<PawnKindDef>.AllDefsListForReading.Where(pawnkinddef => pawnkinddef.race != null).ToList();

                return allkinds;
            }
        }
        private static HashSet<HediffDef> GetCompHashSet(Type type)
        {
            return DefDatabase<HediffDef>.AllDefsListForReading.Where(hediffdef => hediffdef.comps?.Any(comp => type.IsAssignableFrom(comp.compClass)) ?? false).ToHashSet();
        }
        public static HashSet<HediffDef> AllVaginas
        {
            get
            {
                if (allvaginas != null) return allvaginas;
                allvaginas = GetCompHashSet(typeof(HediffComp_Menstruation));
                return allvaginas;
            }
        }
        public static HashSet<HediffDef> AllAnuses
        {
            get
            {
                if (allanuses != null) return allanuses;
                allanuses = GetCompHashSet(typeof(HediffComp_Anus));
                return allanuses;
            }
        }
        public static HashSet<HediffDef> AllBreasts
        {
            get
            {
                if (allbreasts != null) return allbreasts;
                allbreasts = GetCompHashSet(typeof(HediffComp_Breast));
                return allbreasts;
            }
        }
        public static HashSet<GeneDef> EggLayerGenes
        {
            get
            {
                if (egglayergenes != null) return egglayergenes;
                egglayergenes = DefDatabase<GeneDef>.AllDefsListForReading.Where(geneDef => geneDef.GetModExtension<MenstruationModExtension>()?.disableCycle ?? false).ToHashSet();

                return egglayergenes;
            }
        }

        // Defs from Milkable Colonists
        public static readonly HediffDef Hediff_Lactating_Drug = DefDatabase<HediffDef>.GetNamedSilentFail("Lactating_Drug");
        public static readonly HediffDef Hediff_Lactating_Natural = DefDatabase<HediffDef>.GetNamedSilentFail("Lactating_Natural");
        public static readonly HediffDef Hediff_Lactating_Permanent = DefDatabase<HediffDef>.GetNamedSilentFail("Lactating_Permanent");
        public static readonly HediffDef Hediff_Heavy_Lactating_Permanent = DefDatabase<HediffDef>.GetNamedSilentFail("Heavy_Lactating_Permanent");
        public static readonly JobDef Job_LactateSelf_MC = DefDatabase<JobDef>.GetNamedSilentFail("LactateSelf_MC");

        // Defs from Sexperience Ideology
        public static readonly PreceptDef Pregnancy_Elevated = DefDatabase<PreceptDef>.GetNamedSilentFail("Pregnancy_Elevated");
        public static readonly PreceptDef Pregnancy_Holy = DefDatabase<PreceptDef>.GetNamedSilentFail("Pregnancy_Holy");
        public static readonly PreceptDef Pregnancy_Required = DefDatabase<PreceptDef>.GetNamedSilentFail("Pregnancy_Required");
        // Related thoughts
        public static readonly ThoughtDef CameInsideMIdeo = DefDatabase<ThoughtDef>.GetNamed("CameInsideMIdeo");
        public static readonly ThoughtDef CameInsideFIdeo = DefDatabase<ThoughtDef>.GetNamed("CameInsideFIdeo");
        public static readonly ThoughtDef HaterCameInsideFIdeo = DefDatabase<ThoughtDef>.GetNamed("HaterCameInsideFIdeo");
        public static readonly ThoughtDef HateTookContraceptivePillIdeo = DefDatabase<ThoughtDef>.GetNamed("HateTookContraceptivePillIdeo");
    }

}


code:
<?xml version="1.0" encoding="utf-8"?>
<packages />


code:
<?xml version="1.0" encoding="utf-8"?>
<ModMetaData>
	<packageId>rjw.menstruation</packageId>
	<name>RJW Menstruation Cycle</name>
	<author>lutepickle</author>
  <url>https://gitgud.io/lutepickle/rjw_menstruation/</url>
	<supportedVersions>

1.2

1.3

1.4

1.5

	</supportedVersions>
	<modDependencies>

			<packageId>brrainz.harmony</packageId>
			<displayName>Harmony</displayName>
			<steamWorkshopUrl>steam://url/CommunityFilePage/2009463077</steamWorkshopUrl>
			<downloadUrl>https://github.com/pardeike/HarmonyRimWorld/releases/latest</downloadUrl>

			<packageId>rim.job.world</packageId>
			<displayName>RimJobWorld</displayName>
			<downloadUrl>https://gitgud.io/Ed86/rjw</downloadUrl>

	</modDependencies>
	<loadAfter>

brrainz.harmony

erdelf.HumanoidAlienRaces

Mlie.AnimalGenetics

rim.job.world

Abraxas.RJW.RaceSupport

rjw.milk.humanoid

	</loadAfter>
  <incompatibleWithByVersion>
    <v1.4>

conit.thebirdsandthebees

    </v1.4>
    <v1.5>

conit.thebirdsandthebees

    </v1.5>
  </incompatibleWithByVersion>
	<description>Adds menstruation mechanics to vaginas:

Wombs cycle between follicular, luteal, and bleeding phases
Tracks eggs ovulated and cum in wombs to determine pregnancy
Womb icon and status window
Estrus and pheromone effects
Race-specific fetus images for many vanilla animals
Pregnancies from multiple eggs and different fathers
Identical siblings
Breast and nipple changes during pregnancy
Bleeding, pain, and mood debuffs during periods
Tampons, pads, and pain relievers
Climacteric and menopause effects
Fertility pills to produce more eggs and induce ovulation
Hybrid offspring editor ingame

Original mod by moreorganstodump, then updated for RJW 4.9 by c0ffee and adopted by lutepickle.
	</description>
</ModMetaData>


code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Manifest>
	<identifier>RJW Menstruation</identifier>
	<version>1.5.0.5</version>
	<dependencies>
	</dependencies>
	<incompatibleWith />
	<loadAfter>

UnlimitedHugs.HugsLib

brrainz.harmony

rim.job.world

Abraxas.RJW.RaceSupport

rjw.milk.humanoid

Mlie.AnimalGenetics

	</loadAfter>
	<suggests>
	</suggests>
  <manifestUri>https://gitgud.io/lutepickle/rjw_menstruation/-/raw/main/About/Manifest.xml</manifestUri>
  <downloadUri>https://gitgud.io/lutepickle/rjw_menstruation</downloadUri>
</Manifest>


code:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<loadFolders>
	<v1.2>

1.2

1.2/RJW Menstruation Race Support

1.2/MilkModule

	</v1.2>
	<v1.3>

1.3

1.3/RJW Menstruation Race Support

1.3/MilkModule

	</v1.3>
	<v1.4>

1.4

1.4/RJW Menstruation Race Support

	</v1.4>
  <v1.5>

1.5

1.5/RJW Menstruation Race Support

  </v1.5>
</loadFolders>


code:
Version 1.5.0.5
 - Updated Traditional Chinese translation by Hydrogen.

Version 1.5.0.4
 - Compatibilty update for RJW 5.6.0
 - Requires RJW 5.6.0
 - Fix for corpses appearing in the hybrid selection.
 - Fix errors when trying to implant an egg with an animal father into a Biotech pregnancy.
 - More accurate description of anestrus for periodic ovulators.

Version 1.5.0.3
 - Fix for spurious error related to CatBreasts on startup.
 - More reliable detection of modded penises during sex.

Version 1.5.0.2
 - Compatibility update for RJW 5.5.0
 - Requires RJW 5.5.0
 - Fix error during labor if the mother is also the father.
 - Fix fetus image for foxes.

Version 1.5.0.1
 - Fix error getting blood color of pawns without genes.

Version 1.5.0.0
 - Support for RimWorld 1.5. All future changes to Menstruation will only be for RimWorld 1.5.
 - Updated Traditional Chinese translation by Hydrogen.
 - Added Russian translation by Angra Mainyu.
 - Inactive genes will no longer be applied to wombs.
 - Menstrual blood will now use blood colors from Vanilla Expanded Genes.
 - Fix babies becoming the wrong pawnkind in some scenarios.

Version 1.0.9.4
 - Added graphics for the menstruation genes with thanks to Alpenglow.
 - Pawns in estrus now give their pheromones to their caravan-mates.
 - Pawns with the egglaying genes from Erin's Corvyia and Outland - Genetics no longer have a menstrual cycle.

Version 1.0.9.3
 - The biosculptor egg restoration cycle will now give more eggs to races that ovulate more than one egg at a time.
 - All pawns can now use all menstruation genes, regardless of gender or having a womb.
 - Egglaying animals no longer have a menstrual cycle.
 - Fix bug preventing absorbers from becoming dirty.

Version 1.0.9.2
 - Updated Traditional Chinese translation by Hydrogen.
 - Fixed the no bleeding gene having positive metabolic efficiency instead of negative.
 - Fixed ovulation chance not accounting for genes or precepts.
 - Better handle wombs that are not in the genitals body part.
 - Handle errors more gracefully when starting a pregnancy.
 - Fix implanting multiple eggs in an animal when configured to use Biotech pregnancies.
 - An equipped tampon or pad will now show how much fluid it has absorbed in its tooltip.
 - Passive absorption will now make a tampon or pad dirty after enough time, even if no fluid was added.
 - It will take a cloth tampon about 2 days to become dirty passively. A cloth pad will take about 10 days.
 - An absorber that was force worn will no longer be forced once it becomes dirty.
 - Pawns without a menstrual cycle will no longer equip absorbers.
 - Egglaying races no longer have a menstrual cycle, regardless of vagina type.
 - Pawns with the egglaying genes from Alpha Genes, VE Saurids, or Phytokin no longer have a menstrual cycle.
 - The womb status button will now appear in a pawn's health tab when using Compact Hediffs, with thanks to Fern.
 - Tampons and pads are now allowed by default in the worker, soldier, and slave starting outfits.

Version 1.0.9.1
 - Japanese translation for most text by Lokuzt.
 - New womb, cum, and fetus graphics by Euldrop.
 - Add new ideology-related thoughts with the sexperience-ideology mod.
 - New pheromone system: Pawns in visible estrus will increase the sex drive of nearby males. Can be disabled in the options.
 - Using the egg restoration biosculptor cycle will give a small mood buff.
 - Fix some errors related to precum.
 - Periodic ovulators that don't bleed will properly enter anestrus after their luteal stage.
 - Climacteric/menopausal pawns will have their sex need slow properly when the womb's tick rate is non-default.

Version 1.0.9.0
 - Fix errors when opening the womb dialog of some low fertility pawns.
 - Updated Traditional Chinese translation by Hydrogen.
 - New options to update wombs more or less often, defaulting to every hour.
 - When using the sexperience-ideology mod, pawns with pro-pregnancy precepts will have thoughts more agreeable with potential pregnancies.
 - More generous egg allocation for newly spawned periodic ovulators.
 - Menstruation-related genes will now stay on females during initial pawn setup.

Version 1.0.8.9
 - Fix bug that sent pawns into menopause very early. Please use the recalculate ovary power dev action to restore lost eggs.

Version 1.0.8.8
 - Fix pawns skipping straight to menopause instead of going through climacteric stages.
 - Fix father appearing as "Null" in womb dialog for some Biotech pregnancies.
 - Fix Biotech multiple pregnancy births not being tracked in the mother's statistics.
 - Other bug fixes
 - Rework ovulation mechanics. A pawn's implantation chance is now dependent only on their age and climacteric effects.
 - All other fertility-altering effects instead change the odds of ovulation occuring, rolled per-egg. This chance appears in the womb dialog.
 - If the chance of ovulation goes above 100%, the implantation chance is increased.
 - Drugs that increase the number of eggs ovulated are still guaranteed to work.
 - If Biotech is disabled or not installed, the old fertility system will apply instead.

Version 1.0.8.7
 - Fix missing texture when using Milkable Colonists.
 - Fix estrus and egg lifespan lasting far longer than intended.
 - Canine vaginas now use the new periodic ovulator cycle.
 - Hovering over a vagina hediff will show the current state in the tooltip.

Version 1.0.8.6
 - Updated Traditional Chinese translation by Hydrogen.
 - Fix error when trying to terminate a non-Biotech pregnancy.
 - Properly give the opportunity to name a newborn with Biotech and multiple pregnancy.
 - Added several menstruation-related genes, with a placeholder graphic for now.
 - Added experimental support for twins and hybrids with Biotech pregnancies, disabled by default.

Version 1.0.8.5
 - Added biosculpter recipe to restore 1 year's worth of eggs, with icon by DestinyPlayer.
 - Vaginal sex with the "avoid pregnancy" relation will (usually) pull out prevent cum from entering the womb if there's a risk of pregnancy.
 - Impregnation fetishists are significantly less likely to pull out.
 - Some males will release small amounts of semen into a womb during vaginal sex before their actual ejaculation.
 - Babies born from multiple pregnancy will properly produce the prompt to name them.
 - Hopefully improve compatibility with xenotype inhertiance-altering mods for multiple pregnancy.
 - Pawns that have stopped aging will no longer have larger breasts during and after pregnancy.
 - Experimental "periodic ovulator" cycle type added, currently not used. See Patches/Hediffs_Private_Parts_Animal.xml for an example.

Version 1.0.8.4
 - Fix Biotech xenotype inheritance for single-child pregnancies.
 - Fix error in Traditional Chinese translation.
 - New option in the mod settings to hide the womb icon for drafted pawns.
 - Newborns should now be baseliners if there are no xenotypes to inherit.
 - The Biotech terminate pregnancy recipe can now terminate a menstruation pregnancy, too.

Version 1.0.8.3
 - Compatibility update for RJW 5.3.0.9
 - Requires RJW 5.3.0.9
 - Re-added support for Animal Genetics (Continued).

Version 1.0.8.2
 - Compatibility update for RJW 5.3.0.7
 - Requires RJW 5.3.0.7
 - Updated race support patches for new and removed vaginas.
 - The Biotech extract ovum operation will now remove an egg from a pawn's ovaries.
 - A pawn's womb should now recognize an implanted embryo.

Version 1.0.8.1
 - Added the option for humans to start Biotech pregnancies if the DLC is enabled. If set, non-humans will use the old multiple pregnancy instead.
 - Babies conceived through the multiple pregnancy option will now properly inherit xenotypes.
 - Properly track Biotech pregnancy through labor.
 - Pawns that are genetically sterile will no longer produce fertile cum, nor have a menstrual cycle.
 - Biotech IUDs will now reduce pregnancy chances the same as an RJW IUD. Using both will not stack.
 - A biotech pregnancy will pause before going into labor if another womb already is in labor.
 - Fix disabling menopause not actually disabling menopause.
 - Fix errors in womb dialog for Biotech pregnancies with null father.
 - Properly detect AsmodeusRex's race support.

Version 1.0.8.0
 - Support for RimWorld 1.4. All future changes to Menstruation will only be for Rimworld 1.4.
 - Existing Biotech pregnancies will appear in a womb, but no support yet for starting a Biotech pregnancy.
 - Identical twins will have identical genes.
 - Biotech: A human will lactate upon giving birth with multiple pregnancy.
 - Updated Traditional Chinese translation by Hydrogen.

Version 1.0.7.5
 - Requires RJW 5.2.2.
 - High resolution graphics and new fetus graphics provided by Glux.
 - Fix error when one womb's concealed estrus is overwritten by another womb's visible estrus.
 - Fix error after the game is loaded with an NPC in estrus off-map.
 - Fix udders not appearing in the womb dialog with RJW 5.2.2.
 - Fix missing texture error when insect egged with multiple sizes.
 - Don't show an implanted egg if the fetus is supposed to be hidden.
 - Properly calculate cramp pain falloff again.
 - Climacteric and menopause are now per-womb, appearing in the womb dialog instead of as hediffs. Any old hediffs should disappear upon loading the save.
 - Added new property to vaginas to multiply the number of eggs available. Archotech vaginas will have quadruple the normal amount.
 - Add new surgery to lighten and darken nipples.
 - When a pregnancy starts, its gestation will be advanced to include the time since fertilization.
 - Support for Animal Genetics (Continued) when using multiple pregnancy.

Version 1.0.7.4
 - Fix errors when using other mods with bad HediffCompProperties.
 - Fix egg appearing to be fertilized in womb display when it is not.
 - Fix post-birth recovery being instant or very short.
 - Fix womb gizmo error when insect egged.
 - Induced ovulators will start with a lower number of eggs, but still enough for a long breeding life. IUDs or sex with poor fertility partners may result in early menopause.
 - Pawns on caravans and in transport pods will have their wombs simulated.
 - Updated max size areola images by wruf.
 - Substantially reduce the speed of nipple variance during milking and respect the max nipple increment setting.
 - Possible titles for newborns removed to match RJW 5.1.0.
 - Improve compatibility with RJW 5.1.0 for multiple wombs.
 - Better handling of estrus for multiple wombs.
 - Induced ovulators will end estrus immediately upon reaching luteal if not induced. One that is induced will have their estrus only last as long as an unfertilized egg would.

Version 1.0.7.3
 - Fix null reference error upon birth of female pawns.
 - Properly display multiple icons for pawns with multiple wombs.
 - Fix only a single womb being able to become pregnant at a time. Requires multiple pregnancy enabled in the options.
 - Show the 'about to ovulate' icon in the womb dialog for induced ovulators during vaginal sex.
 - Display more insect eggs in a womb when someone has more, with new graphics by Euldrop.

Version 1.0.7.2
 - Fix errors when trying to open dev actions when HAR is not installed.
 - Fix "error processing breasts" for pawns with vanilla pregnancy (e.g. animals).
 - Removing a vagina won't end a mechanoid implant anymore.

Version 1.0.7.1
 - Null reference error fix for multiple wombs when one is pregnant.
 - Fix the progress bar on pregnancy again. Also make undiscovered pregnancies a little more subtle.
 - Nipple size/transition system rewritten to be simpler under the hood. Should work with existing saves, but you might find sizes to be different, especially for very large or very small breasts.
 - Replaced HugsLib-based scheduler with normal ticking. This should reduce some 'phantom cycle' bugs.
 - Redone calculation to determine low eggs remaining. This should cause climacteric to be applied at a more appropriate time in the pawn's life, especially for those with very long cycles.
 - Identical twins conceived after this update will have identical sex part sizes, properties, etc. upon being born.
 - Identical twins of HAR races will have identical coloration, part variations, and masking.
 - For modders:
 - The function Hediff_MultiplePregnancy.ProcessIdenticalSibling is called on every identical sibling when born except the first. Any race-specfic genetic properties can be patched in there.
 - Any mods that add comps to RJW parts should copy what they need to on a postfix to Hediff_MultiplePregnancy.CopyBodyPartProperties, e.g. how menstruation itself does in that function.

Version 1.0.7.0
 - Not save compatible with previous versions. Expect glitches and many red errors if you try. However, things should stabilize eventually.
 - Designed for RJW 5.0.0, but should work with previous versions.
 - Sexperience module/womb cleaning removed due to conflicts with separated cum module.

 - Support for multiple wombs, including each having a separate pregnancy.
 - More reliably generate a baby's race correctly when using pawnkind diversification mods.
 - Overhauled many things under the hood.
 - Cycle randomization completely redone. Everyone now has a (hidden) cycle speed and cycle variability.
 - Ovary initialization redone. All pawns now get a total number of eggs based on their age and racial properties.
 - Coming inside someone with an IUD will give the same total amount of fluid as without, just at a lower fertility.
 - The chance to fertilize has been changed to an exponential curve instead of a linear one. This will increase the chances of pregnancy at low amounts of semen and slightly reduce it at high amounts.
 - Semen now has a fertility percentage instead of "fertile volume".
 - The exact time between fertilization and implantation has been adjusted.
 - Removing a vagina will end any pregnancy it has in progress. Please wait until the baby is born first.
 - Your colonists can create artwork of someone being born.
 - They can also create artwork of someone coming inside someone else.

 - Default values changed to account for the new math. The new defaults will have the same odds of pregnancy with a 10ml ejaculation at ovulation (in a human) as before:
 - Fertilization chance from 10%/mL to 15%
 - Cum decay from 30%/hour to 15%
 - Fertility decay from 20%/hour to 5%

Version 1.0.6.6
 - Ovipostors add on average 1.5x as much cum to a womb than before.
 - The womb tick timing is now more consistent across a save and load, and also spread out across pawns.
 - Babies of bestial relations get a mother/father relationship to their parents instead of the old sire one.
 - Fix error when an egg fertilized by a nonexistent/garbage collected pawn (e.g. in an NPC's womb) tries to implant.
 - Another hybrid fix for invalid races.
 - Fix an implanted egg icon showing for mechanoid pregnancies.

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.
 - A whole mess of spelling, grammar, and description updates.

Version 1.0.6.3
 - Fix pawn generation for races with a single lifestage.
 - Show womb gizmo for males with vaginas, too.
 - Originally, the casual hookup override only applied to a pawn searching for a partner. It will now also apply to a partner deciding whether to accept a hookup.
 - Message feedback added to debug actions.
 - Show the status button in the health tab for pawns with more than one genital.
 - Known issue: The status button will be next to the first genital instead of the vagina.

Version 1.0.6.2
 - Fix error/crash when a pawn in estrus (with hookup override enabled) looks for partners.
 - Teratophiles get the "I came inside" mood buff for ugly partners instead of pretty ones.
 - Locked absorbers (e.g. that guests have) won't get dirty or cause infections.

Version 1.0.6.1
 - Requires RJW 4.9.6 or later
 - Fix errors when a hybrid refers to an invalid race.
 - A pawn in estrus will prefer partners and sex types that would result in pregnancy.
 - Optional (default disabled) alternative casual hookup settings for a pawn in visible estrus.
 - Babies born to slaves will have the right faction.
 - Respect RJW's bestiality pregnancy relations setting.

 - Contributed by amevarashi:
 - Fix womb cleaning job if no buckets on the map.
 - Fix futa impregnations.
 - Hide some details for hidden pregnancies.
 - Keep father unknown if the RJW paternity operation hasn't been performed.
 - Add option to remove the gather cum gizmo.

Version 1.0.6.0
 - adopted by lutepickle
 - Induced ovulators will now go into estrus on every cycle, not just the one after they've been cum in. Hope you have birth control.
 - Induced ovulators will properly recognize when they might get pregnant (e.g. for the mood debuff).
 - The progress bar works again when pregnant.
 - A baby will have their chronological age set to when they're born, not when they're conceived.
 - The womb display will show the correct fertilization chance if they have a modifier to it.
 - The 10 hour infection grace period for dirty tampons now starts when it gets dirty, not when the clean one is inserted. Arguably not a bug, but that was a hideous level of micromanagement needed before.
 - When a pawn's body size changes (e.g. going from teenager to adult), ensure that any pregnancy-related breast growth is retained.
 - Prevent NaN ml of fluid in a womb when bleed rate is set to 0.

 - Only put sperm in the womb when the one with the penis orgasms, instead of either person. Also put their full load in instead of 30% of it.
 - Lower default fertilization chance to 10%/ml (from 15%/ml) to account for the bigger loads.
 - A non-pregnant womb could hold 500x what the vagina def has listed. I think that's utterly ridiculous (and makes the capacity all but meaningless), but there's some out there who'd want that sort of thing, so as a compromise, an "overfilled" vagina will leak at up to double the normal rate. Think water pressure.
 - A vagina will never leak while knotted. (Though sperm decay will still diminish fertilization chances with time.)
 - Babies will inherit their parents' traits in the same way as stock RJW, except enzygotic (i.e. identical) twins now get the same inherited traits.
 - Babies take on their mother's last name instead of their father's.
 - Impregnation fetishes only apply when someone is in the right part of their cycle to get pregnant. Call it their Spermy Sense.
 - Breasts now grow and shrink at a more realistic rate during and after pregnancy.
 - Udder breasts now display in the womb dialog.
 - Fixed the typo on the "consealed" estrus hediff. You'll probably get a couple red errors when loading a pre-change save, but they are safe to ignore.
 - Added some dev actions to set a pawn to a particular part of their cycle, and one to recalculate eggs based on their age.

Version 1.0.5.9
 - minor bug fixes

Version 1.0.5.8
 - requires RJW 4.8.1 or later
 - added toggle for gather cums in womb into a cum bucket
 - fixed nudity pawns get mood debuff from tampons(pads will get debuffs)
 - added blue breasts for hydraulic and bionic breasts
 - now pads provide tiny armor rate to genitals

Version 1.0.5.7
 - requires RJW 4.8.1 or later
 - minor bug fixes

Version 1.0.5.6
 - requires RJW 4.8.0.3
 - fixed womb gizmo not worked properly

Version 1.0.5.5
 - not compatible with RJW 4.8.0 or later
 - clicking vagina and anus image will show origin state
 - fixed loadfolders.xml for other platforms
 - added load orders
 - added stage progress bar

Version 1.0.5.4
 - lactating cause nipple morph
 - clicking breast image will show nipple's origin state(before & after)
 - fixed animal pregnancy error
 - added cum effects
   - use IngestionOutcomeDoer
   - might you can make aphrodisiac cum with this
   - added antisperm antibody
   - added cyclosporine which cures antisperm antibody
 - sexperience integrations
   - added ability to gather cums in womb using cumbucket

Version 1.0.5.3
 - now impregnate on every orgasm
 - added egg lifespan setting
 - changed initial ovary calculation
   - now use infertile age instead of minimum sex age
 - added vagina morph option after birth

Version 1.0.5.2
 - 1.3 support
 - added tooltips on status window
 - clicking pawn in status window will show naked body
 - removed duplicated dll
 - more descriptions for mod settings

----Last update for 1.2----
Version 1.0.4.4a
 - added records
 - fixed errors on initializing

Version 1.0.4.4
 - ovary regeneration pill can restore climacteric (not menopause)
 - menstrual blood uses race's blood def
 - added estimated sperm lifespan in modsetting
 - fixed errors on pregnancy
 - changed cum calculation method

Version 1.0.4.3
 - fixed errors on pregnancy
 - added surgeries for nipple/areola
 - changed cum calculate method
   - cum's fertility will remain
   - IUD will diminish cum's fertility
 - changed default settings
   - fertilization chance raised 5% to 15%
   - cum decay ratio raised 15% to 30%

Version 1.0.4.2a
 - fixed hybrid custom UI

Version 1.0.4.2
 - fixed errors on hybrid custom
 - fixed errors on pregnancy

Version 1.0.4.1

 - fixed errors when the race mods are uninstalled
 - minor bug fixes
 - removed mechanoids from hybrid table
 - increased probability weight range of custom hybrid
 - breasts size increase gradually after pregnancy about one cup

Version 1.0.4.0
 - minor bug fixes
 - cums will get maximum thickness initially and become thinner gradually
 - added in-game custom hybrid editor
   - you can customize hybrid definition easily
   - this will override definitions from xml files
   - removed hybrid priority option(father's definition will be prioritized)

Version 1.0.3.2
 - fixed self-lactating not work properly
 - pawns having impregnation fetish or lover get less mood penalty on pregnancy
 - minor bug fixes
 - contraptive pills decreases mood debuffs from creampie (breeders will get reversed effect)

Version 1.0.3.1
*Note* Remove previous version before installing
 - fixed problems that pawns get climacteric stage after pregnancy even the menopause setting is off
 - now implantation chance is independent with rjw pregnancy settings
 - fixed broken vagina support
 - breasts support for race support
 - minor bug fixes

Version 1.0.3.0
 - added various fetus images (thanks to Glux)
 - added twin fetus image
 - male insects can impregnate female
 - now insects egg display on womb icon
 - added breast to status window
   - added milk status bar(milkable colonists compatible)
   - added self lactating button
     - self lactating enlarges nipple
   - pawns will get different size of nipple tips, areolas and colors
 - added status bars
   - you can check when the pawn get breeder/incubator quirk with this
 - fixed problems when cycle acceleration is too high

Version 1.0.2.0
 - support for RJW Race Support
 - fixed erros with pawns that the litter size curve is not defined

Version 1.0.1.15
 - added more descrption on the mod options
 - sick thought of in period removed
 - pain offset of in period decreased
 - added pain reliever
 - added description for tampon about infection
 - infection chance of dirty tampon decreased 2% to 1%

Version 1.0.1.14
 - requires RJW 4.6.1 or later
 - fixed interspecies factor applied to normal pregnancy

Version 1.0.1.13
 - requires RJW 4.6.1 or later
 - added induced ovulator
   - fenline and rodent vagina ovulate after sex in follicular stage
 - minor bug fix
Version 1.0.1.12
 - requires RJW 4.6.1 or later
 - added HybridExtension attribute to PawnDNAModExtension
   - this will overrides RJW's hybrid definitions
   - supports more detailed hybrid definition
 - fixed bugs when menopause option off
Version 1.0.1.11
 - added a button for opening status window in health tab
   - added option for this
 - added option for select which pawn displays status
 - fixed erros when pawn's anus missing
 - added breedingSeason and estrusDaysBeforeOvulation attributes to CompProperties_Menstruation
 - added patch for dog, cat, horse , narrow, rodent vagina
Version 1.0.1.10
 - added option for adjusting bleeding amount
 - added hotkey for opening status window
Version 1.0.1.9
 - added estrus effects
   - estrus increases pawn's sex drive greatly
 - added consealedEstrus attribute to CompProperties_Menstruation
   - if consealedEstrus set as true, the pawn will get less effective estrus
 - hyperfertility pills induce esturs
 - now initial ovarypower is affected by pawn's life expectancy and litter size
Version 1.0.1.8
 - fixed problems with animal status window
 - fixed RMB menu crash
 - added egg overlay
 - default implantation chance changed to 65%
 - now fertilized eggs are implanted after 7 days later
Version 1.0.1.7
 - added chinese translations
 - major bug fixes
 - minor bug fixes
Version 1.0.1.6
 - fixed bugs when display fetus image
 - fixed futa female was not set as parent
Version 1.0.1.5
 - DNADef is obsoleted and replaced to ModExtention
Version 1.0.1.4
 - fixed bugs that in period hediff not disappear in time
 - fixed enable menopause setting was not saved
 - now cum filths are generated as a single mixture filth
 - dirty tampons and wet pads are now untradable
 - DNAdef is obsoleted and replaced with modextention
Version 1.0.1.3
 - requires RJW 4.6.1 or later
 - max absorbable statbase added to vanilla fabrics.
 - added thoughts for cum inside
   - male pawn get mood buff if his partner is not ugly or he has breeder or impregnation fetish quirk
   - female pawn get mood buff if she has breeder or impregnation fetish quirk
   - female pawn get mood debuff if she is in fertile window or hates her partner
 - added thought for leaking fluids
   - absorbers can prevent this
 - added thought for pregnancy
   - female pawn without breeder quirk get mood debuff when pregnant without spouse or fiance
 - mestrual blood color is determined by race's blood color
 - absorber's color change gradually
 - fixed bugs with enzygotic twins
   - enzigotic twins will get same appearance
   - added HAR compatibllity
 - removed unused textures
Version 1.0.1.2
 - requires RJW 4.6.1 or later
 - reduced sex satisfaction debuffs
 - if pawn is climacteric or menopause sex need recover to 50%.
 - added vaginal washing
 - fixed bugs absorber does not work properly
 - used absorbers are colored fluid's color
Version 1.0.1.1
 - requires RJW 4.6.1 or later
 - added superovulation inducing agent
 - cumflations (no effects yet)
 - added tampon and sanitary pad can absorb fluids.
   - tampon blocks fluids completely. however, keep wearing dirty tampon can cause infection.
   - pad blocks fluids for a while, but if exceed over the absorbable, fluids leak again.
 - fixed erros when male pawn take hyperfertility pills.

Version 1.0.1.0
 - requires RJW 4.6.1 or later
 - added multiple pregnancy
   - added options for twins
     - if you turn off both twin options, you will get only one baby on every pregnancy.
   - male's litter curve size does not affect to number of offspring
   - female can get multiple offsprings with multiple races.

Version 1.0.0.10
 - fixed cycle acceleration option was not saved.
 - cum capacity decreased greatly.
 - blood amount during in period decreased.

Version 1.0.0.9
 - update for RJW 4.6.0 (if you didn't update RJW, you don't need to update this mod)
   - removed patch file for IUD.

Version 1.0.0.8
 - added option for disable menopause.

Version 1.0.0.7
 - fixed errors when attatch new vagina.
 - ovulation stage produces multiple eggs and number of eggs are determined by race's litter size curve.
   - but still, only one egg can proceed to pregnancy.
 - added new attribute ovaryPower to CompProperties_Menstruation.
   - default value is almost unlimited that never comes menopause.
   - every ovulation decreases ovaryPower.
   - when ovaryPower is low, climacteric begins.
   - during in climacteric, cycles become irregular and lose fertility in progress.
   - ovulation using hyperfertility pills consumes ovaryPower double times.
   - hyperfertility pills decrease additional ovaryPower (abuse of hyperfertility pills will cause premature menopause)
   - climacteric and menopause decrease sex drive and satisfaction.
 - added ovary regeneration pill that can prevent climacteric.
   - ovary regeneration pill increases 30% of ovaryPower. (no limit, cannot cure climacteric)
 - in period hediff decrease sex drive and satisfaction.

Version 1.0.0.6
 - if pawn is fertility stat is 0, stage is fixed at none.
 - added option for fetus information level.
   - depend on information level, pregnant stage display as luteal stage
 - rewrote misspelled DNADef attribute and mod title in mod settings

Version 1.0.0.5
 - womb cum capacity is affected by pawn's bodysize
 - changed cum volume calculate method.
   - cum volume is affected by pawn's bodysize
   - generic cum volume decreased.
   - if pawn has messy quirk, cum volume increases 4~8times.
 - cum textures are dependent on womb texture

Version 1.0.0.4
 - fixed errors when runtimeGC removed pawns in cum list.
 - added menstrual cramp - now pawns will get mood debuff during in period
 - merged some stages into one stage

Version 1.0.0.3
 - fixed sometimes hediffcomp stops working.
 - changed initializing method
 - added patches for generic vagina and dragon vagina

Version 1.0.0.2
 - add options for turn on/off vagina/womb image in status window

Version 1.0.0.1
 - supports for other type of vagina
 - custom images support for vagina&anus


color-case: upper

element-case: lower

quotes: single

sort-order-fallback: abc

sort-order: position z-index top right bottom left

sort-order: display visibility float clear overflow overflow-x overflow-y -ms-overflow-x -ms-overflow-y -webkit-overflow-scrolling clip zoom -webkit-align-content -ms-flex-line-pack align-content -webkit-box-align -moz-box-align -webkit-align-items align-items -ms-flex-align -webkit-align-self -ms-flex-item-align -ms-grid-row-align align-self -webkit-box-flex -webkit-flex -moz-box-flex -ms-flex flex -webkit-flex-flow -ms-flex-flow flex-flow -webkit-flex-basis -ms-flex-preferred-size flex-basis -webkit-box-orient -webkit-box-direction -webkit-flex-direction -moz-box-orient -moz-box-direction -ms-flex-direction flex-direction -webkit-flex-grow -ms-flex-positive flex-grow -webkit-flex-shrink -ms-flex-negative flex-shrink -webkit-flex-wrap -ms-flex-wrap flex-wrap -webkit-box-pack -moz-box-pack -ms-flex-pack -webkit-justify-content justify-content -webkit-box-ordinal-group -webkit-order -moz-box-ordinal-group -ms-flex-order order

sort-order: -webkit-box-sizing -moz-box-sizing box-sizing width min-width max-width height min-height max-height margin margin-top margin-right margin-bottom margin-left padding padding-top padding-right padding-bottom padding-left

sort-order: table-layout empty-cells caption-side border-spacing border-collapse list-style list-style-position list-style-type list-style-image

sort-order: content quotes counter-reset counter-increment resize cursor -webkit-user-select -moz-user-select -ms-user-select user-select nav-index nav-up nav-right nav-down nav-left -webkit-transition -moz-transition -ms-transition -o-transition transition -webkit-transition-delay -moz-transition-delay -ms-transition-delay -o-transition-delay transition-delay -webkit-transition-timing-function -moz-transition-timing-function -ms-transition-timing-function -o-transition-timing-function transition-timing-function -webkit-transition-duration -moz-transition-duration -ms-transition-duration -o-transition-duration transition-duration -webkit-transition-property -moz-transition-property -ms-transition-property -o-transition-property transition-property -webkit-transform -moz-transform -ms-transform -o-transform transform -webkit-transform-origin -moz-transform-origin -ms-transform-origin -o-transform-origin transform-origin -webkit-animation -moz-animation -ms-animation -o-animation animation -webkit-animation-name -moz-animation-name -ms-animation-name -o-animation-name animation-name -webkit-animation-duration -moz-animation-duration -ms-animation-duration -o-animation-duration animation-duration -webkit-animation-play-state -moz-animation-play-state -ms-animation-play-state -o-animation-play-state animation-play-state -webkit-animation-timing-function -moz-animation-timing-function -ms-animation-timing-function -o-animation-timing-function animation-timing-function -webkit-animation-delay -moz-animation-delay -ms-animation-delay -o-animation-delay animation-delay -webkit-animation-iteration-count -moz-animation-iteration-count -ms-animation-iteration-count -o-animation-iteration-count animation-iteration-count -webkit-animation-direction -moz-animation-direction -ms-animation-direction -o-animation-direction animation-direction text-align -webkit-text-align-last -moz-text-align-last -ms-text-align-last text-align-last vertical-align white-space text-decoration text-emphasis text-emphasis-color text-emphasis-style text-emphasis-position text-indent -ms-text-justify text-justify text-transform letter-spacing word-spacing -ms-writing-mode text-outline text-transform text-wrap text-overflow -ms-text-overflow text-overflow-ellipsis text-overflow-mode -ms-word-wrap word-wrap word-break -ms-word-break -moz-tab-size -o-tab-size tab-size -webkit-hyphens -moz-hyphens hyphens pointer-events

sort-order: font font-family font-size font-weight font-style font-variant font-size-adjust font-stretch font-effect font-emphasize font-emphasize-position font-emphasize-style font-smooth line-height


code:
/dist
/ts-out
/node_modules
/package-lock.json
/static/bundle.js
*.backup

path: .gitignore


code:
image: node:14

stages:
  - build
  - deploy
variables:
  GIT_SUBMODULE_STRATEGY: recursive
  GIT_DEPTH: 500
pages:
  stage: build
  cache:
    paths:
      - node_modules/
  script:
    - npm install
    - npm run lint
    - npm run deobfuscate-resources
    - npm run build
    - mkdir public
    - mv dist/* public
    - gzip -k -9 $(find public -type f -not -name "*.jpg" -not -name "*.png")
  artifacts:
    paths:
      - public
  only:
    - master

cfworker:
  stage: deploy
  script:
    - npm --prefix ./workers-site install ./workers-site
    - npm install @cloudflare/wrangler
    - sed -i "s/\!AccountID/$CF_AID/g" wrangler.toml
    - sed -i "s/\!ZoneID/$CF_ZID/g" wrangler.toml
    - npx wrangler publish
  only:
    - master


code:
[submodule "chapters/7 - 插图"]
	path = chapters/1.4 - 插图
	url = ../wearable-technology-illustrations.git

path: .gitmodules


cSpell.words: MAKAI Unparsed WTCD scrollable sfnf strlen transitionend undecide


code:
{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "label": "VSCode Problems Provider",
      "type": "npm",
      "script": "vscode-problems",
      "isBackground": true,
      "problemMatcher": [
        "$tsc-watch"
      ],
    }
  ]
}


code:
>《可穿戴科技》是一部重口味色情小说。因其中含有大量露骨的非常规性行为描写，本小说可能不适合所有年龄段，亦不宜在工作期间访问。

# 可穿戴科技 [![pipeline status](https://gitgud.io/RinTepis/wearable-technology/badges/master/pipeline.svg)](https://gitgud.io/RinTepis/wearable-technology/-/commits/master)
《可穿戴科技》是一部关于一名社会恐惧症美少女和某智能贞操带斗智斗勇的色情小说。

## [点此在线阅读 (GitLab Pages)](https://wt.tepis.me/)
- [镜像站 1 | wt.bgme.me（感谢 Shrink 提供）](https://wt.bgme.me)
- [镜像站 2 | rbq.desi（感谢 kookxiang 提供）](https://rbq.desi)
- [镜像站 3 | wt.0w0.bid（感谢立音喵提供）](https://wt.0w0.bid)
- [镜像站 4 | wt.umwings.com（感谢 C86 提供）](https://wt.umwings.com)

### 其他链接：[投稿](https://wt.tepis.me/#META/%E6%92%B0%E7%A8%BF%E9%A1%BB%E7%9F%A5%E5%8F%8A%E7%AE%80%E6%98%93-Markdown-%E6%95%99%E7%A8%8B.html) | [龙套](https://wt.tepis.me/#META/%E4%BA%BA%E5%90%8D%E8%AF%B7%E6%B1%82.html) | [WTCD 语言](https://wt.tepis.me/#META/WTCD/1.-%E6%A6%82%E8%BF%B0.html)
本小说[原先是放在 Google Docs 上](https://docs.google.com/document/d/1Pp5CtO8c77DnWGqbXg-3e7w9Q3t88P35FOl6iIJvMfo/edit?usp=sharing)的，但是由于篇幅变长，Google Docs 越来越卡，因此转移到 GitHub。然后 GitHub 又因为我们违反 ToS，[把我们的仓库封了](https://github.com/SCLeoX/Wearable-Technology)。

更新推送频道：https://t.me/joinchat/AAAAAEpkRVwZ-3s5V3YHjA

讨论组：https://t.me/joinchat/Dt8_WlJnmEwYNbjzlnLyNA

## 鸣谢
特别感谢以下小伙伴提供的建议与帮助，排名不分先后：

- 灵翼
- 城岭 樱
- 立音喵
- lgd_小翅膀
- 青葉
- [C86](https://c86.moe)
- Butby
- [VV](https://www.pixiv.net/users/58170013)
- [acted咕咕喵](https://acted.gitlab.io/h3)
- 路人乙
- 炽羽渡尘01
- 熵
- [Runian Lee](https://t.me/Runian)
- 0 级骨钉
- [零件](https://nekosc.com)
- Skimige
- 神楽坂 萌绫
- [TExL](http://texas.penguin-logistics.cn)
- 神楽坂 紫
- 冰蓮音
- NekoCaffeine
- 某不愿透露姓名的N性？
- kn
- 禾裱禾裱
- 夏克斯
- kookxiang
- Testingdoll01
- RainSlide
- [F74nk](https://t.me/F74nk_K)
- 为霜
- 铱则
- 杨佳文
- 不知名的N姓人士就好
- 王木木
- 琥珀
- [帕蒂卡](https://github.com/Patika-ailemait)
- [幻梦](https://t.me/HuanmengQwQ)
- [重水时雨](https://t.me/boatmasteronD2O)
- 47AD
- [czp](https://www.hiczp.com)
- [pokemonchw](https://github.com/pokemonchw)
- 櫻川 紗良

如果你想加入鸣谢列表里，你可以在讨论组或者在和作者的私聊里提提意见/脑洞啥的。哪怕你说的没有被采纳，我也十分愿意把你的名字加进来（一般情况下，如果我意识到了你在提意见，我就会主动来问你要不要加鸣谢列表。如果我没有意识到，我十分欢迎你主动来跟我说你要加鸣谢列表，热热闹闹的多好 √）。


code:
不可脱下的穿戴物（女/伪娘/男/扶她）
不拘束双手，但是无法自行取下的设备。
例①：不包括手铐，因为手铐拘束了双手。
例②：包括脚镣，因为它如果没有钥匙，有手也打不开。
例③：不包括用绳子捆绑脚腕，因为用手可以解开。
例④：不包括普通口球，因为可以用手取下来。
例⑤：包括上锁的口球，因为没有钥匙，用手也取不下来。

贞操带（女/伪娘/男/扶她）！！！
不可自行取下的代替内裤的装置。
需要由硬性材质制成。因此“上锁的蓝白内裤”不算。
和【贞操笼】的区别在于，贞操带必须环绕腰部。
+需选择【不可脱下的穿戴物】

强制刺激贞操带（女/伪娘/男/扶她）
不但无法取下，而且会造成刺激（电击，快感等）的贞操带。
+需选择【贞操带】

禁欲贞操带（女/伪娘/男/扶她）
以禁欲为目的的贞操带。
+需选择【贞操带】

贞操笼（伪娘/男/扶她）！！！
不可自行取下的将阴茎罩住的装置。
需要由硬性材质制成。因此“上锁的避孕套”不算。
如果环绕腰部了，请选择【贞操带】。
+需选择【不可脱下的穿戴物】

强制刺激贞操笼（伪娘/男/扶她）
不但无法取下，而且会造成刺激（电击，快感，等）的贞操笼。
+需选择【贞操笼】

禁欲贞操笼（伪娘/男/扶她）
以禁欲为目的的贞操带。
+需选择【贞操笼】

贞操胸罩（女/伪娘/男/扶她）
不可自行取下的代替胸罩的装置。
需要由硬性材质制成。因此“上锁的胸罩”不算。
如果暴露面积很大（比如只覆盖了一个乳头），就不要选了。

阴道插入（女/扶她）
将任何物体（包括手指）插入阴道，或者描写有物体在阴道内的状态。

肛门插入（女/伪娘/男/扶她）
将任何物体（包括手指）插入肛门，或者描写有物体在肛门内的状态。

尿道插入（女/伪娘/男/扶她）！
将任何物体（包括手指）插入尿道，或者描写有物体在尿道内的状态。

阴蒂刺激（女/扶她）
以任何方式刺激阴蒂，包含穿刺，震动，电击等。

阴茎刺激（伪娘/男/扶她）
用手或者道具刺激阴茎（或者龟头等）。
例①：不包括插入插入阴道性交。
例②：包括手淫。

榨精（伪娘/男/扶她）！
使用自动化设备或其他手段采集男性的精液。

乳头刺激（女/伪娘/男/扶她）
以任何方式刺激乳头，包含穿刺，震动，电击等。

穿刺（女/伪娘/男/扶她）！
穿刺身体的敏感部位的行为。
比如，除非你的角色光靠摸耳垂能高潮，不然耳环不算。

阴蒂穿刺（女/扶她）！
穿刺阴蒂的行为。
+需选择【阴蒂刺激】及【穿刺】

乳头穿刺（女/伪娘/男/扶她）！
穿刺乳头的行为。
+需选择【乳头刺激】及【穿刺】

榨乳（女/扶她）！
使用自动化设备或其他手段采集女性乳房分泌的乳液。

爱液采集（女/扶她）！
使用自动化设备或其他手段采集女性高潮在阴道分泌的液体。

尿液采集（女/伪娘/男/扶她）
使用自动化设备或其他手段采集尿液。

汗液采集（女/伪娘/男/扶她）
使用自动化设备或其他手段采集汗液。

口水采集（女/伪娘/男/扶她）
使用自动化设备或其他手段采集口水。

按摩棒（女/伪娘/男/扶她）
插入体内可以震动/旋转/等的按摩设备。

跳蛋（女/伪娘/男/扶她）
震动设备。

电击（女/伪娘/男/扶她）！
使用电流产生痛感/快感的行为。
使用电流进行精神控制不算。

窒息（女/伪娘/男/扶她）！
限制呼吸的行为。
=呼吸限制，限制呼吸

流体灌输（女/伪娘/男/扶她）
将流体强制灌入人的体内的行为。
灌输使用的器具必须为非人类的阴茎。
例①：不包括中出，因为精液是使用人类的阴茎灌入的。
例②：包括使用阴茎形状的灌肠器。
例③：包括使用灌肠器将预先存储的精液灌入体内。

灌肠（女/伪娘/男/扶她）！
将流体灌入肠道的行为。
灌输使用的器具必须为非人类的阴茎。
+需选择【流体灌输】

遥控！
使用远程遥控道具。
+需选择对应性别的【遥控他人】
+需选择对应性别的【被遥控】

遥控他人（女/伪娘/男/扶她）
远程遥控他人身上的远程遥控道具。
+需选择【遥控】

被遥控（女/伪娘/男/扶她）
被他人远程遥控身上的远程遥控道具。
+需选择【遥控】

舔舐
使用舌头舔身体/物体的行为。
如果舔的是人，则需要选择对应性别的【舔舐他人】和【被舔舐】。
请注意：如果是人舔非人，或非人舔人，则不需要选择对应的性别标签。
=舔

舔舐他人（女/伪娘/男/扶她）
+需选择【舔舐】

被舔舐（女/伪娘/男/扶她）
+需选择【舔舐】

舔足！
使用舌头舔脚或者腿的行为。
可以隔着丝袜或者其他不是特别厚的袜子。
+需选择【舔舐】
+需选择对应性别的【舔他人足】
+需选择对应性别的【被舔足】
=舔腿，舔脚

舔他人足（女/伪娘/男/扶她）
+需选择【舔足】

被舔足（女/伪娘/男/扶她）
+需选择【舔足】

虐足（女/伪娘/男/扶她）！
使用道具对脚施加痛苦或其他难以忍受的感觉的行为。
包括脚底挠痒。
=虐脚

口交！
使用嘴（包括舌头，牙齿，等）刺激阴蒂/阴茎/阴道/肛门，其他部位不算。
非人形机械使用虚拟舌头等不算口交。
如果有舔的动作，请选择【舔舐】。
+需选择对应性别的【为他人口交】
+需选择对应性别的【被口交】

为他人口交（女/伪娘/男/扶她）
+需选择【口交】

被口交（女/伪娘/男/扶她）
被他人口交。
如果被舔的部位是阴蒂，需选择【阴蒂刺激】。
如果被舔的部位是阴茎，需选择【阴茎刺激】。
如果舌头伸入了阴道，需选择【阴道插入】。
如果舌头伸入了肛门，需选择【肛门插入】。
+需选择【口交】

腹击交！
使用拳头击打他人以造成快感的行为。
请注意，必须目的为造成快感，且实际造成了快感。普通的斗殴不算腹击交。
+需选择对应性别的【腹击交他人】
+需选择对应性别的【被腹击交】

腹击交他人（女/伪娘/男/扶她/机械/触手）
+需选择【腹击交】

被腹击交（女/伪娘/男/扶她）
+需选择【腹击交】

尿液饮用（女/伪娘/男/扶她）！
喝下尿液的行为。
=圣水，喝尿

爱液饮用（女/伪娘/男/扶她）！
喝下爱液的行为。

精液饮用（女/伪娘/男/扶她）！
喝下精液的行为。
精液包括仿制精液和触手分泌物。
=饮精

中出！
将精液射入他人阴道或直肠的行为。
精液包括仿制精液和触手分泌物。
+需选择对应性别的【中出他人】
+需选择对应性别的【被中出】

中出他人（伪娘/男/扶她/触手）
+需选择【中出】

被中出（女/伪娘/男/扶她）
+需选择【中出】

排尿控制（女/伪娘/男/扶她）！
限制排尿的行为。
需要具体描写憋尿。如果只是插入了尿道塞则不算。
=憋尿

放尿（女/伪娘/男/扶她）！
强迫排尿或因无法忍受尿意而排尿。
如果预先接受排尿控制，需选择【排尿控制】
=漏尿

强制高潮（女/伪娘/男/扶她）！！
使用物理或精神手段强制他人高潮的行为。
=强高

高潮边缘控制（女/伪娘/男/扶她）！！
使用物理或精神手段强制他人处在高度兴奋状态，但不让其达到高潮的行为。
=临高

高潮忍耐（女/伪娘/男/扶她）！
因为高潮后会有不好的结果（例如惩罚）而忍耐不达到高潮的行为。
=忍耐高潮

自慰（女/伪娘/男/扶她）！
自己刺激自己获得快感的行为。
=手淫

自虐（女/伪娘/男/扶她）！
自己刺激自己获得痛感/痛苦的行为。
也包括故意通过给自己施加大量快感以至于超过忍受极限而感到痛苦的行为。

露出（女/伪娘/男/扶她）！
在公开场合做潜在色情的事情的行为。
比如在公开场合【自慰】或者在公开场合【放尿】。

战斗（女/伪娘/男/扶她）！
仅包括有色情内容的战斗。
比如戴着跳蛋的狙击手。
=作战

调教！
以洗脑、改变行为、改变性能力为目的地施加刺激。
常见的例子有每天性交使人堕落，或者锻炼他人的高潮忍耐能力。
+需选择对应性别的【调教他人】
+需选择对应性别的【被调教】

调教他人（女/伪娘/男/扶她/机械/触手）
如果有人使用机械来调教他人，请同时选择调教者的性别和机械。
+需选择【调教】

被调教（女/伪娘/男/扶她）
+需选择【调教】

折磨！
以施加痛苦为目的地施加刺激。
+需选择对应性别的【折磨他人】
+需选择对应性别的【被折磨】
=虐待，拷问

折磨他人（女/伪娘/男/扶她/机械/触手）
如果有人使用机械来折磨他人，请同时选择调教者的性别和机械。
+需选择【折磨】

被折磨（女/伪娘/男/扶她）
+需选择【折磨】

鞭打（女/伪娘/男/扶她）！
被鞭打。
=鞭刑，鞭挞，鞭子

监禁（女/伪娘/男/扶她）！
将人长期限制在一定活动区域的行为。
需要有一定色情要素，比如戴着跳蛋。
例①：不包括普通的监狱，因为不色情。
例②：包括让美少女以后扔进监狱里。

深喉！
被异物深深插入喉咙的行为。
+需选择对应性别的【被深喉】
如果深入的是口塞的假阴茎，需选择【深喉口塞】。
如果深入的是阴茎或者触手，需选择【深喉他人】。

被深喉（女/伪娘/男/扶她）
+需选择【深喉】

深喉口塞（女/伪娘/男/扶她）！
佩戴长度很长的，足以深入喉咙的假阴茎口塞。
+需选择【深喉】
+需选择【被深喉】
+需选择【假阴茎口塞】

深喉他人（伪娘/男/扶她/触手）
+需选择【深喉】

逃脱（女/伪娘/男/扶她）！
有一定自由度，但是不完全自由，努力重获自由的行为。
需要有一定色情要素，比如戴着跳蛋。

野外生存（女/伪娘/男/扶她）！
在野外尝试活下去的行为。
需要有一定色情要素，比如戴着跳蛋。

挠痒！
使人发痒的行为。
+需选择对应性别的【挠痒他人】
+需选择对应性别的【被挠痒】
=tk

挠痒他人（女/伪娘/男/扶她/机械/触手）
如果有人使用机械来挠痒他人，请同时选择调教者的性别和机械。
+需选择【挠痒】

被挠痒（女/伪娘/男/扶她）
+需选择【挠痒】

媚药（女/伪娘/男/扶她）
使用使用提升敏感度或是性欲的药物。固体液体气体都行。
=春药

扩张（女/伪娘/男/扶她）！
使阴道，肛门，尿道变粗的行为。

轮奸（女/伪娘/男/扶她）！
被与多人强制发生性行为。
=群奸

打屁股（女/伪娘/男/扶她）！
被使用工具或手拍打屁股。

堕落（女/伪娘/男/扶她）！
从正常到完全沉迷于性快感的过程。
=恶堕

固化（女/伪娘/男/扶她）！
将人拘束在类似水泥或凝胶内的行为。

拘束（女/伪娘/男/扶她）
以任何方式限制他人（或者自己）身体自由的道具或装置。
=bdsm

固定拘束（女/伪娘/男/扶她）！
使用相对牢固的装置将人拘束住的行为。
拘束后身体的活动范围应该会很小。
+需选择【拘束】

机械奸（女/伪娘/男/扶她）！！
使用相对较大型的机械进行拘束并产生快感。
其中拘束必须是机械的一部分。
例①：不包括自己坐在炮机上，因为没有拘束。
例②：不包括用绳子把自己绑住后坐在炮机上，因为绳子不是炮机的一部分。
例③：包括自己将自己固定在自带拘束皮带的炮机上。
+需选择【固定拘束】

伪装拘束（女/伪娘/男/扶她）！！
明明被拘束但是假装没有被拘束的行为。
+需选择【拘束】

捆绑（女/伪娘/男/扶她）！
用绳子拘束。
+需选择【拘束】
=绳艺

吊缚（女/伪娘/男/扶她）
拘束后被吊在空中的行为。
如果用绳子，需要选择【捆绑】。
+需选择【拘束】

手铐（女/伪娘/男/扶她）
将手腕拘束在一起的拘束具。
必须是设计出来就是用来铐住手腕的，这意味着绳子之类的不算。
+需选择【拘束】

单手套（女/伪娘/男/扶她）
将双臂拘束在身后的拘束具。
+需选择【拘束】

拘束枷（女/伪娘/男/扶她）
同时固定颈部和手腕的装置。
比如一字枷，提琴枷，等。
+需选择【拘束】
=枷

拘束手套（女/伪娘/男/扶她）
穿在手上限制手指活动的手套，包括金属球。
+需选择【拘束】

脚镣（女/伪娘/男/扶她）
将脚腕拘束在一起的拘束具。
必须是设计出来就是用来铐住脚腕的，这意味着绳子之类的不算。
+需选择【拘束】

困境拘束（女/伪娘/男/扶她）！！
困境拘束泛指将“被害人”放入两难的境地使其做出选择的行为，因此不一定是【拘束】。
比如用上吊绳圈迫使被害人踮脚。

拘束衣（女/伪娘/男/扶她）！
设计出来专门用来拘束人的衣服。
+需选择【拘束】

项圈（女/伪娘/男/扶她）
固定在脖子上产生羞耻感的道具。
如果功能仅是装饰则不属于拘束。
但是如果限制了脖子活动，则需选择拘束。

电击项圈（女/伪娘/男/扶她）！
可以产生电击的项圈。
+需选择【项圈】，【电击】

感官剥夺（女/伪娘/男/扶她）！
限制听觉或视觉的装置。
比如眼罩或者耳塞。
如果上锁，并且手可自由活动，需选择【不可脱下的穿戴物】。

口枷（女/伪娘/男/扶她）！
限制说话的装置。
如果上锁，并且手可自由活动，需选择【不可脱下的穿戴物】。
=口塞

口球（女/伪娘/男/扶她）！
通过将球固定在牙齿之间，防止嘴巴闭合的口枷。
+需选择【口枷】

马嚼子（女/伪娘/男/扶她）！
通过将长条圆柱横向固定在牙齿之间，防止嘴巴闭合的口枷。
+需选择【口枷】

假阴茎口塞（女/伪娘/男/扶她）！
将假阴茎或其他柱状物纵向固定在嘴中，防止嘴巴闭合的口枷。
如果长度很长，已经到达了喉咙里，需选择【深喉口塞】
+需选择【口枷】

束腰（女/伪娘/男/扶她）！
固定在腰部，限制腰部宽度的装置。
不属于【拘束】。
如果上锁，需选择【不可脱下的穿戴物】。

三角木马（女/伪娘/男/扶她）！
让受刑者用阴部坐在的木马上进行惩罚的刑具。
如果使用了器具将目标固定在木马上，则需选择【拘束】。

触手（女/伪娘/男/扶她）！
如果有拘束剧情，需选择【拘束】。
如果触手刺激了阴蒂，需选择【阴蒂刺激】。
如果触手刺激了阴茎，需选择【阴茎刺激】。
如果触手伸入了阴道，需选择【阴道插入】。
如果触手伸入了肛门，需选择【肛门插入】。

触手服（女/伪娘/男/扶她）！
内部有触手的衣服。
如果限制了自由，比如固定了双手，需选择【拘束】。
如果无法自行脱下，且不起到拘束的目的，需选择【不可脱下的穿戴物】。
+需选择【触手】

拟物化（女/伪娘/男/扶她）！
将人拘束成其他物体的行为。
+需选择【拘束】

放置（女/伪娘/男/扶她）！
被拘束住然后什么也不做的行为。
比如把一个人绑住，塞上跳蛋，然后离开。
如果将目标置于两难境地了，需选择【困境拘束】。
+需选择【拘束】

唯一主人公
全文参与所有色情活动的人全部为同一人。

含有女性
参与某一场色情活动的人中含有一个及以上的女性。

含有伪娘
参与某一场色情活动的人中含有一个及以上的伪娘。
=伪娘，女装

含有男性
参与某一场色情活动的人中含有一个及以上的非伪娘男性。
=男性

含有扶她
参与某一场色情活动的人中含有一个及以上的扶她。
=扶她

百合！
参与某一场色情活动的人为两个及以上的女性。
=女同，女同性恋

强制百合！
使用物理拘束手段迫使两人进行百合。
+需选择【拘束】

耽美！
参与某一场色情活动的人为两个及以上的非伪娘男性。
=男同，男同性恋

伪百合！
参与某一场色情活动的人为一个及以上的女性和一个及以上的伪娘或两个及以上的伪娘。
换言之：①必须总人数两人及以上；②至少有一个伪娘；③不能有非伪娘男性。

同辈亲属！
指参与某一场色情活动的人中含有同辈亲属（兄妹等）。
=兄妹，姐妹，兄弟，姐弟

异辈亲属！
指参与某一场色情活动的人中含有非同辈亲属（母女等）。
=母女，父女

丝袜（女/伪娘/男/扶她）
含有丝袜，且含有一定程度的互动。
如果只是作为外貌描写出现一下则不算。
但是，比如描写了舔舐，或者穿脱的动作，就算。
如果上锁，需要选择【不可脱下的穿戴物】。

高跟鞋（女/伪娘/男/扶她）
含有高跟鞋，且含有一定程度的互动。
如果只是作为外貌描写出现一下则不算。
但是，比如描写了穿在上面难以行走，或者穿脱的动作，就算。
如果上锁，需要选择【不可脱下的穿戴物】。

连体衣（女/伪娘/男/扶她）
任何材质的连体衣。
如果上锁，需要选择【不可脱下的穿戴物】。

乳胶紧身衣（女/伪娘/男/扶她）
+需选择【连体衣】
=乳胶衣

女仆（女/伪娘/男/扶她）！
只要穿了女仆装就是女仆。
如果上锁，需要选择【不可脱下的穿戴物】。

古代
文章中含有在古代环境发生的色情剧情。
古代即基本没有自动化设备的时代。如果有，也是简单的（水车等）。

近代
文章中含有在近代环境发生的色情剧情。
近代即不使用数字电路的时代，比如蒸汽朋克。

现代
文章中含有在现代环境发生的色情剧情。

未来
文章中含有在未来环境发生的色情剧情。

校园！
文章中含有发生在校园中的色情剧情。

魔法少女！
含有魔法☆少女。

淫纹！
含有淫❤纹。

桌游！
不一定要在桌子上玩。以游戏为性质的色情行为。

性转（女/伪娘/男/扶她）！
请选择在性转发生前的标签变种。（如果男变女，请选择性转（男））
生理性别发生改变。
使用完全沉浸式的虚拟现实设备变成其他性别也算。
发生改变后，其他标签按照改变后的性别进行。
需选择对应性别的【性转至】

性转至（女/男/扶她）
当发生性转后，变成的性别。
需选择对应性别的【性转】


琳 缇佩斯

description: 《可穿戴科技》主线作者；表面上是全职魔法☆少女，私底下偶尔写写代码。

城岭 樱

description: 城岭神社的守社巫女，也是神社的所有者，M 体质。

0 级骨钉

description: 非常非常非常非常喜欢百合但只会写短篇的小钉。

没有茄子

description: 享受焦虑，摄取痛苦，沉迷于前功尽弃，期待着社会性死亡。_(:з」∠)_

无公害小蘑菇

description: 如果君落羽出什么事了那一定是我妹的锅。

何雁青

description: 在写了在写了...

芙萝尔

description: 对爱情的渴望，对知识的追求，对人类苦难不可遏制的同情，这三种纯洁但无比强烈的感情支配着我的一生。这三种感情就像飓风一样，在深深的苦海上，肆意地把我吹来吹去，吹到濒临绝望的边缘。

NanayaSakuya

description: 比起美少女，更喜欢漂亮衣服；比起编故事，更喜欢听故事。