diff --git a/1.5/Assemblies/RJW_Menstruation.dll b/1.5/Assemblies/RJW_Menstruation.dll new file mode 100644 index 0000000..26ec0a6 Binary files /dev/null and b/1.5/Assemblies/RJW_Menstruation.dll differ diff --git a/1.5/Assemblies/RJW_Menstruation.dll.config b/1.5/Assemblies/RJW_Menstruation.dll.config new file mode 100644 index 0000000..4bfa005 --- /dev/null +++ b/1.5/Assemblies/RJW_Menstruation.dll.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/1.5/Defs/Drugs/Pills_Menstruation.xml b/1.5/Defs/Drugs/Pills_Menstruation.xml new file mode 100644 index 0000000..9f65c17 --- /dev/null +++ b/1.5/Defs/Drugs/Pills_Menstruation.xml @@ -0,0 +1,188 @@ + + + + + OvaryRegenerationPill + + Recovers the ovaries' health, restoring some quantity of eggs. Less effective on ovaries with few eggs remaining. Cannot recover menopause. + + Things/Item/ORPill + Graphic_StackCount + + false + + 2400 + 160 + 0.05 + + Industrial + + Medical + +
  • + 0.3 +
  • +
    +
    + + DrugProduction + +
  • DrugLab
  • +
    +
    + + 10 + 4 + 8 + + +
  • + 0 + 1000 + + 0.08 + 0.14 + +
  • +
    +
    + + + SuperovulationInducingAgent + + Induce superovulation, causing the next ovulation to produce 1-4 extra eggs. May hasten the onset of menopause. + + Things/Item/SIA + Graphic_StackCount + + false + + 2400 + 140 + 0.05 + + Industrial + + Medical + +
  • +
  • +
    +
    + + DrugProduction + +
  • DrugLab
  • +
    +
    + + 12 + 6 + + +
  • + 0 + 1000 + + 0.08 + 0.14 + +
  • +
    +
    + + + PainReliever + + Relieves menstrual pain for 24 hours. Also effective on other sources of pain. + + Things/Item/PainReliever + Graphic_StackCount + + false + + 1000 + 12 + 0.01 + + Industrial + + Medical + +
  • + Hediff_PainReliever + 1.0 +
  • +
    +
    + + DrugProduction + +
  • DrugLab
  • +
    +
    + + 1 + + +
  • + 0 + 1000 + + 0.08 + 0.14 + +
  • +
    +
    + + + Cyclosporine + + An immunosuppressant. Can cure antisperm antibody, but reduces the body's ability to fight off infection and disease for 24 hours. + + Things/Item/Cyclosporine + Graphic_StackCount + + false + + 1000 + 12 + 0.01 + + Industrial + + Medical + +
  • + Hediff_Cyclosporine + 1.0 +
  • +
  • + Hediff_ASA + -0.20 +
  • +
    +
    + + DrugProduction + +
  • DrugLab
  • +
    +
    + + 1 + + +
  • + 0 + 1000 + + 0.08 + 0.14 + +
  • +
    +
    + +
    \ No newline at end of file diff --git a/1.5/Defs/GeneDefs/GeneDefs_Menstruation.xml b/1.5/Defs/GeneDefs/GeneDefs_Menstruation.xml new file mode 100644 index 0000000..0b788e7 --- /dev/null +++ b/1.5/Defs/GeneDefs/GeneDefs_Menstruation.xml @@ -0,0 +1,150 @@ + + + + + Menstruation + + 402 + + + + Menstruation + UI/Genes/Placeholder + +
  • Menstruation_EggLifetime
  • +
    +
    + + + Menstruation_ShortEggLifetime + + Unfertilized eggs with this gene last three-quarters as long. + UI/Genes/ShortEggLifetime + 1 + 10 + +
  • + 0.75 +
  • +
    +
    + + + Menstruation_DoubleEggLifetime + + Unfertilized eggs with this gene last twice as long. + UI/Genes/DoubleEggLifetime + -1 + 12 + +
  • + 2.0 +
  • +
    +
    + + + Menstruation_QuadEggLifetime + + Eggs with this gene last four times as long. + UI/Genes/QuadEggLifetime + -2 + 1 + 16 + +
  • + 4.0 +
  • +
    +
    + + + Menstruation + UI/Genes/Placeholder + +
  • Menstruation_Estrus
  • +
    +
    + + + Menstruation_NeverEstrus + + Carriers of this gene will never go into estrus. + UI/Genes/NeverEstrus + 1 + 20 + +
  • + true +
  • +
    +
    + + + Menstruation_FullEstrus + + Carriers of this gene will enter full estrus every menstrual cycle, regardless of vagina type. + UI/Genes/FullEstrus + -1 + 1 + 25 + +
  • + true +
  • +
    +
    + + + Menstruation + UI/Genes/Placeholder + +
  • Menstruation_Ovulation
  • +
    +
    + + + Menstruation_DoubleOvulation + + Carriers of this gene will ovulate twice as many eggs. + UI/Genes/DoubleOvulation + -1 + 30 + +
  • + 2 +
  • +
    +
    + + + Menstruation_QuadOvulation + + Carriers of this gene will ovulate four times as many eggs. + UI/Genes/QuadOvulation + -1 + 35 + +
  • + 4 +
  • +
    +
    + + + Menstruation_NoBleeding + + Menstruation + Carriers of this gene will not bleed at the end of their cycle. + UI/Genes/NoBleeding + -1 + 40 + +
  • + true +
  • +
    +
    + + +
    \ No newline at end of file diff --git a/1.5/Defs/HediffDef/Hediffs_Cum.xml b/1.5/Defs/HediffDef/Hediffs_Cum.xml new file mode 100644 index 0000000..8ad5b54 --- /dev/null +++ b/1.5/Defs/HediffDef/Hediffs_Cum.xml @@ -0,0 +1,111 @@ + + + + HediffWithComps + Hediff_ASA + + antisperm antibody + Antisperm antibody. Increases death rate of sperm. + {0} has an antisperm antibody + (0.8,0.1,0.1) + false + false + false + true + 1 + 0.1 + + true + + +
  • + false +
  • +
  • + 0.40 + true +
  • +
    + + +
    + + + HediffWithComps + Hediff_ForceFertile + + fertile + fertile + {0} is fertile + (0.3,0.3,0.8) + false + false + false + true + 3 + 0.1 + + true + + +
  • + false + +
  • + RJW_Fertility + 0.05 +
  • + + +
  • + 0.20 + false + +
  • + RJW_Fertility + 0.25 +
  • + + +
  • + 0.40 + true + +
  • + RJW_Fertility + 0.50 +
  • + + +
  • + 0.60 + true + +
  • + RJW_Fertility + 0.75 +
  • + + +
  • + 0.80 + true + +
  • + RJW_Fertility + 1.00 +
  • + + +
    + +
  • + -1.0 + true +
  • +
    +
    + + + +
    \ No newline at end of file diff --git a/1.5/Defs/HediffDef/Hediffs_Menstruation.xml b/1.5/Defs/HediffDef/Hediffs_Menstruation.xml new file mode 100644 index 0000000..7fe11f7 --- /dev/null +++ b/1.5/Defs/HediffDef/Hediffs_Menstruation.xml @@ -0,0 +1,217 @@ + + + + HediffWithComps + Hediff_MenstrualCramp + + in period + Bleeding from the vagina at the end of the menstrual cycle. Often painful. + (0.70,0.00,0.00) + true + false + false + false + 1 + 0.1 + + true + + +
  • + + + 0.50 + 0.95 + + 0.005 +
  • +
  • + 0.2 + + + 0.40 + 0.95 + + 0.01 +
  • +
  • + 0.4 + + + 0.20 + 0.95 + + 0.10 +
  • +
  • + 0.6 + + + 0.0 + 0.95 + + 0.20 +
  • +
    + +
  • + -0.1 +
  • +
    +
    + + + RJW_Menstruation.Hediff_Estrus + Hediff_Estrus + + estrus + A condition caused by a womb entering the most fertile phase of its menstrual cycle. Sexual arousal and desire increase dramatically as the body yearns to become pregnant. Increased chance of vaginal sex occurring and potentially lower standards in mate selection. + (1.00,0.60,0.75) + false + false + false + false + 10000 + 1.0 + + true + + +
  • + + 5.0 + 1.5 + +
  • +
    + +
  • + 0.25 + 6 +
  • +
    +
    + + + RJW_Menstruation.Hediff_Estrus + Hediff_Estrus_Concealed + + estrus + A condition caused by a womb its most fertile phase of the menstrual cycle. Sexual arousal and desire increase slightly. Slightly increased chance of vaginal sex. + (1.00,0.60,0.75) + false + false + false + false + 10000 + 1.0 + + true + + +
  • + false + + 1.10 + 1.05 + +
  • +
    +
    + + + HediffWithComps + Hediff_AffectedByPheromones + + A condition caused by being around someone in estrus. Sex drive and satisfaction is increased by the scent of heat. + (1.00,0.60,0.75) + false + false + false + false + 1.0 + + true + + +
  • + + + 1.1 + +
  • +
  • + 0.4 + + + 1.4 + 1.1 + +
  • +
  • + 0.8 + + + 2.0 + 1.2 + +
  • +
    + +
  • + -1.0 +
  • +
    +
    + + + + HediffWithComps + Hediff_PainReliever + + A mild reprieve from menstrual (and other) sources of pain. + (0.75,0.75,1.0) + false + false + false + false + 5 + 1.0 + +
  • + -0.1 +
  • +
    + +
  • + -1.0 +
  • +
    +
    + + + HediffWithComps + Hediff_Cyclosporine + + Under the effect of an immunosuppressant, hampering the body's ability to fight off infection and disease. + (0.75,0.75,1.0) + false + false + false + false + 10 + 1.0 + +
  • + + -0.25 + +
  • +
    + +
  • + -1.0 +
  • +
    +
    +
    \ No newline at end of file diff --git a/1.5/Defs/JobDefs/Jobs_CleanSelf.xml b/1.5/Defs/JobDefs/Jobs_CleanSelf.xml new file mode 100644 index 0000000..fbfaad1 --- /dev/null +++ b/1.5/Defs/JobDefs/Jobs_CleanSelf.xml @@ -0,0 +1,10 @@ + + + + + VaginaWashing + RJW_Menstruation.JobDriver_VaginaWashing + washing vagina + true + + \ No newline at end of file diff --git a/1.5/Defs/JobDefs/Jobs_MilkSelf.xml b/1.5/Defs/JobDefs/Jobs_MilkSelf.xml new file mode 100644 index 0000000..79df022 --- /dev/null +++ b/1.5/Defs/JobDefs/Jobs_MilkSelf.xml @@ -0,0 +1,9 @@ + + + + LactateSelf + RJW_Menstruation.JobDriver_MilkSelf + lactating self + true + + diff --git a/1.5/Defs/KeyBindings/KeyBindings_Menstruation.xml b/1.5/Defs/KeyBindings/KeyBindings_Menstruation.xml new file mode 100644 index 0000000..6044f12 --- /dev/null +++ b/1.5/Defs/KeyBindings/KeyBindings_Menstruation.xml @@ -0,0 +1,9 @@ + + + + + OpenStatusWindow + + Q + + diff --git a/1.5/Defs/Recipe_Surgery/Recipes_Surgery_Breast.xml b/1.5/Defs/Recipe_Surgery/Recipes_Surgery_Breast.xml new file mode 100644 index 0000000..e19496d --- /dev/null +++ b/1.5/Defs/Recipe_Surgery/Recipes_Surgery_Breast.xml @@ -0,0 +1,80 @@ + + + + Surgery + Recipe_Surgery + MedicalOperationSpeed + Medicine + 0.2 + 400 + false + +
  • Human
  • +
    + 100 + +
  • + + +
  • Medicine
  • + + + 1 + +
    + + +
  • Medicine
  • +
    +
    +
    + + + Surgery_ExpandAreola + + Expand the areolae. + RJW_Menstruation.Recipe_ExpandAreola + expanding areolae + + + + Surgery_ContractAreola + + Contract the areolae. + RJW_Menstruation.Recipe_ContractAreola + contracting areolae + + + + Surgery_ExpandNipple + + Expand the nipples. + RJW_Menstruation.Recipe_ExpandNipple + expanding nipples + + + + Surgery_ContractNipple + + Contract the nipples. + RJW_Menstruation.Recipe_ContractNipple + contracting nipples + + + + Surgery_DarkenNipple + + Darken the nipples. + RJW_Menstruation.Recipe_DarkenNipple + darkening nipples + + + + Surgery_LightenNipple + + Lighten the nipples. + RJW_Menstruation.Recipe_LightenNipple + lightening nipples + + +
    diff --git a/1.5/Defs/RecordDefs/Records_Womb.xml b/1.5/Defs/RecordDefs/Records_Womb.xml new file mode 100644 index 0000000..6228687 --- /dev/null +++ b/1.5/Defs/RecordDefs/Records_Womb.xml @@ -0,0 +1,19 @@ + + + + + AmountofCreampied + + The milliliters of cum that's been ejaculated into my womb. + Float + + + + AmountofFertilizedEggs + + The number of my eggs that sperm has fertilized. + Int + + + + diff --git a/1.5/Defs/Stats/Stats_Absorber.xml b/1.5/Defs/Stats/Stats_Absorber.xml new file mode 100644 index 0000000..b45fda3 --- /dev/null +++ b/1.5/Defs/Stats/Stats_Absorber.xml @@ -0,0 +1,27 @@ + + + + + MaxAbsorbable + + Maximum amount of fluid that this item can absorb. + Apparel + 0 + FloatOne + {0} ml + false + 60 + +
  • + 0.5 + 0.8 + 1 + 1.2 + 1.4 + 2.0 + 5.0 +
  • +
    +
    + +
    diff --git a/1.5/Defs/TaleDefs/Tales_Cum.xml b/1.5/Defs/TaleDefs/Tales_Cum.xml new file mode 100644 index 0000000..105f2b2 --- /dev/null +++ b/1.5/Defs/TaleDefs/Tales_Cum.xml @@ -0,0 +1,32 @@ + + + + CameInside + + Tale_DoublePawn + Volatile + FUCKER + FUCKED + 1.5 + + +
  • tale_noun->[FUCKER_nameDef] coming inside of [FUCKED_nameDef]
  • +
  • image->[FUCKER_nameFull]'s penis deep inside of [FUCKED_nameFull]'s vagina [circumstance_group]
  • +
  • image->[FUCKER_nameFull]'s penis vanishing into [FUCKED_nameFull]'s vagina [circumstance_group]
  • +
  • image->[FUCKED_nameFull]'s vagina being filled by [FUCKER_nameFull]'s penis [circumstance_group]
  • +
  • image->[FUCKED_nameFull]'s vagina gripping [FUCKER_nameFull]'s penis tight [cirsumstance_group]
  • +
  • circumstance_phrase->while [FUCKER_nameDef] grits [FUCKER_possessive] teeth
  • +
  • circumstance_phrase->while [FUCKER_nameDef] wears a triumphant smirk
  • +
  • circumstance_phrase->as [FUCKED_nameDef] shudders in ecstasy
  • +
  • circumstance_phrase->as [FUCKER_nameDef] shoots [FUCKER_possessive] load into [FUCKED_nameDef]
  • +
  • circumstance_phrase->while [FUCKED_nameDef] looks into [FUCKER_nameDef]'s eyes with a smile
  • +
  • desc_sentence->[FUCKER_nameDef]'s cum oozes out of [FUCKED_nameDef]'s vagina and drips onto the floor.
  • +
  • desc_sentence->[FUCKER_nameDef]'s sperm races into [FUCKED_nameDef]'s womb and enters [FUCKED_possessive] egg.
  • +
  • desc_sentence->[FUCKER_nameDef]'s cum shoots into [FUCKED_nameDef]'s womb.
  • +
  • desc_sentence->[FUCKED_nameDef]'s womb is filled with cum.
  • +
  • desc_sentence->Sweat runs down [FUCKER_nameDef]'s face.
  • +
  • desc_sentence->[FUCKED_nameDef] is panting heavily.
  • +
    +
    +
    +
    \ No newline at end of file diff --git a/1.5/Defs/ThingDefs/ApparelLayerDefs_Absorber.xml b/1.5/Defs/ThingDefs/ApparelLayerDefs_Absorber.xml new file mode 100644 index 0000000..85fec8c --- /dev/null +++ b/1.5/Defs/ThingDefs/ApparelLayerDefs_Absorber.xml @@ -0,0 +1,8 @@ + + + + Absorber + + 500 + + diff --git a/1.5/Defs/ThingDefs/Apparel_Absorbers.xml b/1.5/Defs/ThingDefs/Apparel_Absorbers.xml new file mode 100644 index 0000000..87fa765 --- /dev/null +++ b/1.5/Defs/ThingDefs/Apparel_Absorbers.xml @@ -0,0 +1,278 @@ + + + + + Absorber_Tampon + + A tampon for absorbing fluids from a vagina. May cause an infection if worn for too long. + RJW_Menstruation.Absorber_Tampon + + Things/Item/Tampon + Graphic_Single + + Never + false + Sellable + + 20 + 0.01 + 1000 + 1.0 + 2 + 10 + + 5 + +
  • Fabric
  • +
    + + UnfinishedApparel + ComplexClothing + GeneralLaborSpeed + Crafting + Tailor + Recipe_Tailor + +
  • ElectricTailoringBench
  • +
  • HandTailoringBench
  • +
    + true + + 4 + +
    + +
  • ApparelUtility
  • +
    + + true + false + false + 0 + Female + +
  • GenitalsBPG
  • +
    + +
  • Absorber
  • +
    + +
  • Absorber
  • +
    + +
  • Worker
  • +
  • Soldier
  • +
  • Nudist
  • +
  • Slave
  • +
    +
    + +
  • + 0.2 + false + true + 10 + Absorber_Tampon_Dirty +
  • +
    +
    + + + Absorber_Tampon_Dirty + + A wet used tampon. May cause infection if left in. + RJW_Menstruation.Absorber_Tampon + + Things/Item/Tampon + Graphic_Single + + Never + false + None + + 20 + 0.05 + 0 + 1000 + 0.2 + 2 + 10 + -5 + + +
  • Fabric
  • +
    + +
  • ApparelUtility
  • +
    + + true + false + false + 0 + Female + +
  • GenitalsBPG
  • +
    + +
  • Absorber
  • +
    + +
  • Absorber
  • +
    +
    + +
  • + 0.2 + false + true + 8 + Absorber_Tampon_Dirty +
  • +
    +
    + + + + Absorber_Pad + + A pad for absorbing fluids from a vagina. + RJW_Menstruation.Absorber + + Things/Item/Pad + Graphic_Single + + Never + false + Sellable + + 40 + 0.02 + 1000 + 1.0 + 4 + 25 + 0.02 + 0.02 + 0.05 + 0.01 + 0.04 + 0.05 + 1 + -1 + + 10 + +
  • Fabric
  • +
    + + UnfinishedApparel + GeneralLaborSpeed + Crafting + Tailor + Recipe_Tailor + +
  • ElectricTailoringBench
  • +
  • HandTailoringBench
  • +
    + true + + 4 + +
    + +
  • ApparelUtility
  • +
    + + true + true + false + 0 + Female + +
  • GenitalsBPG
  • +
    + +
  • Absorber
  • +
    + +
  • Absorber
  • +
    + +
  • Worker
  • +
  • Soldier
  • +
  • Slave
  • +
    +
    + +
  • + 0.04 + true + false + Absorber_Pad_Dirty +
  • +
    +
    + + + Absorber_Pad_Dirty + + A wet used pad. + RJW_Menstruation.Absorber + + Things/Item/Pad + Graphic_Single + + Never + false + None + + 40 + 0.10 + 0 + 1000 + 0.2 + 4 + 25 + -5 + 0.02 + 0.02 + 0.05 + 0.01 + 0.04 + 0.1 + -4 + 2 + + +
  • Fabric
  • +
    + +
  • ApparelUtility
  • +
    + + true + true + false + 0 + Female + +
  • GenitalsBPG
  • +
    + +
  • Absorber
  • +
    + +
  • Absorber
  • +
    +
    + +
  • + 0.04 + true + false + Absorber_Pad_Dirty +
  • +
    +
    +
    diff --git a/1.5/Defs/ThingDefs/Filth_Mixture.xml b/1.5/Defs/ThingDefs/Filth_Mixture.xml new file mode 100644 index 0000000..fda4e41 --- /dev/null +++ b/1.5/Defs/ThingDefs/Filth_Mixture.xml @@ -0,0 +1,25 @@ + + + + + FilthMixture + + RJW_Menstruation.Filth_Colored + + -30 + -10 + + + Graphic_Random + Things/Filth/PoolSoft + (255, 255, 255, 180) + + + true + 40 + true + + + + + \ No newline at end of file diff --git a/1.5/Defs/ThoughtDefs/Thoughts_sex.xml b/1.5/Defs/ThoughtDefs/Thoughts_sex.xml new file mode 100644 index 0000000..0b0bf12 --- /dev/null +++ b/1.5/Defs/ThoughtDefs/Thoughts_sex.xml @@ -0,0 +1,367 @@ + + + + + LeakingFluids + Thought_Memory + 0.05 + 1 + 0.4 + +
  • + + Can't I get something to absorb this? + -2 +
  • +
    +
    + + + HaterCameInsideM + Thought_MemorySocial + 1.0 + 5 + 0.4 + +
  • + + I came inside of my rival! + 5 + 1 +
  • +
    + +
  • CameInsideMIdeo
  • +
  • CameInsideM
  • +
    +
    + + + CameInsideM + Thought_MemorySocial + 1.0 + 5 + 0.4 + +
  • + + That felt so good. + 2 + 1 +
  • +
    +
    + + + CameInsideFFetish + Thought_MemorySocial + 3.0 + 5 + 0.1 + 1 + +
  • + + I hope I get pregnant. + 10 + 5 +
  • +
    + +
  • CameInsideFIdeo
  • +
    +
    + + + HaterCameInsideF + Thought_MemorySocial + 7.0 + 5 + 0.1 + 1 + +
  • + + I don't want to be pregnant with his baby! + -5 + -10 +
  • +
    + +
  • HaterCameInsideFEstrus
  • +
  • CameInsideF
  • +
  • HaterCameInsideFSafe
  • +
  • CameInsideFLowFert
  • +
  • CameInsideFFetishSafe
  • +
  • HaterCameInsideFIdeo
  • +
  • CameInsideFFetish
  • +
  • CameInsideFIdeo
  • +
    +
    + + + HaterCameInsideFEstrus + Thought_MemorySocial + 7.0 + 5 + 0.1 + 1 + +
  • + + What was I thinking, letting him do that? + -3 + -5 +
  • +
    + +
  • CameInsideF
  • +
  • HaterCameInsideFSafe
  • +
  • CameInsideFLowFert
  • +
  • CameInsideFFetishSafe
  • +
  • HaterCameInsideFIdeo
  • +
  • CameInsideFFetish
  • +
  • CameInsideFIdeo
  • +
    +
    + + + CameInsideFLowFert + Thought_MemorySocial + 3.0 + 5 + 0.1 + 1 + +
  • + + I'm worried I might get pregnant. The chance is low, but... + -1 +
  • +
    + +
  • CameInsideFFetishSafe
  • +
  • HaterCameInsideFIdeo
  • +
  • CameInsideFFetish
  • +
  • CameInsideFIdeo
  • +
    +
    + + + CameInsideF + Thought_MemorySocial + 7.0 + 5 + 0.1 + 1 + +
  • + + I'm worried I might get pregnant. + -3 + -2 +
  • +
    + +
  • HaterCameInsideFSafe
  • +
  • CameInsideFLowFert
  • +
  • CameInsideFFetishSafe
  • +
  • HaterCameInsideFIdeo
  • +
  • CameInsideFFetish
  • +
  • CameInsideFIdeo
  • +
    +
    + + + CameInsideFFetishSafe + Thought_MemorySocial + 3.0 + 5 + 0.1 + 1 + +
  • + + I don't think I'll get pregnant, but it's fun to fantasize. + 3 + 1 +
  • +
    + +
  • HaterCameInsideFIdeo
  • +
  • CameInsideFFetish
  • +
  • CameInsideFIdeo
  • +
    +
    + + + HaterCameInsideFSafe + Thought_MemorySocial + 3.0 + 5 + 0.1 + 1 + +
  • + + I probably won't get pregnant, but I still don't like it. + -2 + -5 +
  • +
    + +
  • CameInsideFLowFert
  • +
  • CameInsideFFetishSafe
  • +
  • HaterCameInsideFIdeo
  • +
  • CameInsideFFetish
  • +
  • CameInsideFIdeo
  • +
    +
    + + + UnwantedPregnancy + Thought_Memory + 14.0 + 5 + 0.1 + +
  • + + How will I take care of a baby? What am I going to do? + -10 +
  • +
    +
    + + + UnwantedPregnancyMild + Thought_Memory + 14.0 + 5 + 0.1 + +
  • + + I'm having a baby. I hope I can manage. + -3 +
  • +
    +
    + + + TookContraceptivePill + Thought_Memory + 7.0 + 5 + 0.1 + +
  • + + Everything will be okay now. + 1 +
  • +
    +
    + + + HateTookContraceptivePill + Thought_Memory + 7.0 + 5 + 0.1 + +
  • + + I want to get pregnant. + -3 +
  • +
    +
    + + + EggRestorationReceived + Thought_Memory + 4 + 1 + +
  • + + I can breed for a little longer now. + 2 +
  • +
    +
    + + + CameInsideMIdeo + Thought_MemorySocial + 1.0 + 5 + 0.4 + +
  • + + It is my duty to make her pregnant. + 3 + 2 +
  • +
    + +
  • CameInsideM
  • +
    +
    + + + CameInsideFIdeo + Thought_MemorySocial + 3.0 + 5 + 0.1 + 1 + +
  • + + I hope this makes me pregnant like should be. + 15 + 10 +
  • +
    +
    + + + HaterCameInsideFIdeo + Thought_MemorySocial + 3.0 + 5 + 0.1 + 1 + +
  • + + I know I should become pregnant, but does it have to be his? + 5 + 2 +
  • +
    + +
  • CameInsideFFetish
  • +
  • CameInsideFIdeo
  • +
    +
    + + + HateTookContraceptivePillIdeo + Thought_Memory + 7.0 + 5 + 0.1 + +
  • + + My beliefs demand I become pregnant. + -5 +
  • +
    +
    + +
    diff --git a/1.5/Languages/ChineseSimplified/DefInjected/ApparelLayerDef/RJWMenstruation.xml b/1.5/Languages/ChineseSimplified/DefInjected/ApparelLayerDef/RJWMenstruation.xml new file mode 100644 index 0000000..bd0c960 --- /dev/null +++ b/1.5/Languages/ChineseSimplified/DefInjected/ApparelLayerDef/RJWMenstruation.xml @@ -0,0 +1,4 @@ + + + 生殖器 + \ No newline at end of file diff --git a/1.5/Languages/ChineseSimplified/DefInjected/HediffDef/RJWMenstruation.xml b/1.5/Languages/ChineseSimplified/DefInjected/HediffDef/RJWMenstruation.xml new file mode 100644 index 0000000..c1baebe --- /dev/null +++ b/1.5/Languages/ChineseSimplified/DefInjected/HediffDef/RJWMenstruation.xml @@ -0,0 +1,14 @@ + + + + 中枢性疼痛 + 经期中 + 不快 + 恼人 + 疼痛 + 痛苦 + + + + + \ No newline at end of file diff --git a/1.5/Languages/ChineseSimplified/DefInjected/JobDef/RJWMenstruation.xml b/1.5/Languages/ChineseSimplified/DefInjected/JobDef/RJWMenstruation.xml new file mode 100644 index 0000000..6d73d1d --- /dev/null +++ b/1.5/Languages/ChineseSimplified/DefInjected/JobDef/RJWMenstruation.xml @@ -0,0 +1,7 @@ + + + 清洗阴道 + + + + \ No newline at end of file diff --git a/1.5/Languages/ChineseSimplified/DefInjected/StatDef/RJWMenstruation.xml b/1.5/Languages/ChineseSimplified/DefInjected/StatDef/RJWMenstruation.xml new file mode 100644 index 0000000..6c2c93a --- /dev/null +++ b/1.5/Languages/ChineseSimplified/DefInjected/StatDef/RJWMenstruation.xml @@ -0,0 +1,7 @@ + + + 可吸收量 + 最大可吸收的液体量 + + + \ No newline at end of file diff --git a/1.5/Languages/ChineseSimplified/DefInjected/ThingDef/RJWMenstruation.xml b/1.5/Languages/ChineseSimplified/DefInjected/ThingDef/RJWMenstruation.xml new file mode 100644 index 0000000..75ebeeb --- /dev/null +++ b/1.5/Languages/ChineseSimplified/DefInjected/ThingDef/RJWMenstruation.xml @@ -0,0 +1,31 @@ + + + + +卫生棉条 + +从阴道吸收液体的卫生棉条 + +湿的卫生棉条 + +使用过的湿卫生棉条 + +卫生棉 + +从阴道吸收液体的卫生棉 + +湿的卫生棉 + +使用过的湿卫生棉 + +卵巢再生药物 + +使卵巢再生以增加可排卵的卵子 卵子消耗量越大,效果越差 不能缓解更年期症状 + +排卵药 + +诱导排卵的药物 可导致更年期提前 + +混合物 + + \ No newline at end of file diff --git a/1.5/Languages/ChineseSimplified/DefInjected/ThoughtDef/RJWMenstruation.xml b/1.5/Languages/ChineseSimplified/DefInjected/ThoughtDef/RJWMenstruation.xml new file mode 100644 index 0000000..48c020b --- /dev/null +++ b/1.5/Languages/ChineseSimplified/DefInjected/ThoughtDef/RJWMenstruation.xml @@ -0,0 +1,23 @@ + + + 裤湿啦 + 真让人困恼... + 被{0}中出了 + 我担心我可能会怀孕... + 被{0}中出了 + 虽然几率很低,但我还是担心怀孕... + 被{0}中出了 + 我想我怀孕了 + 被{0}中出了 + 我爱做爱 + 中出了{0} + 超爽的 + 被{0}中出了 + 那龟孙子上了我,我不想怀上他的孩子... + 被{0}中出了 + 那龟孙子上了我.... + 中出了{0} + 我上了一个婊子 + 不想要的怀孕 + 我该怎麽办?... + \ No newline at end of file diff --git a/1.5/Languages/ChineseSimplified/Keyed/RJW_Menstruation.xml b/1.5/Languages/ChineseSimplified/Keyed/RJW_Menstruation.xml new file mode 100644 index 0000000..d10b3fe --- /dev/null +++ b/1.5/Languages/ChineseSimplified/Keyed/RJW_Menstruation.xml @@ -0,0 +1,110 @@ + + + RJW Menstruation Cycle + + 月经血 + + 卵泡期 + 排卵 + 黄体期 + 月经来潮 + 怀孕 + 产后恢复 + + 更年期 + 非发情期 + 状态 + 挤自己奶 + 状态 + 胎儿 + 父亲 + 阴道精液列表 + 已受精 + 受精中 + 排卵 + + + + 激活子宫图标 + 激活子宫图标框 + 激活动物经期 + 仿真动物的经期. 此选项将在保存读取后生效 不推荐开启此选项 + 植入机会 + 设置受精卵的植入机会 + 受精的机会 + 设置每小时受精的机会 + 每小时阴道中的精液量衰减率 + 阴道中的精液量将以这个比率减少 + 每小时生育率衰减率 + 精液列表的生育率将以这个比率减少 + 循环加速 + 加快月经周期 + 调试 + 显示调试信息 + 子宫状态 + 在状态窗口中绘制子宫图标 + 阴道状态 + 在状态窗口中绘制阴道和肛门图标 + 胎儿信息级别 + 显示有关胎儿的所有信息 + 显示妊娠后胎儿的所有信息 + 不显示有关胎儿的信息,但显示怀孕後胎儿的图象 + 不显示胎儿图象和信息 + 激活更年期 + 激活更年期效果,使小人随着时间的推移而变得不育 如果您较长寿的外星人种族有碰到任何问题,请关闭此选项. 此选项将在保存读取后生效 + 多重怀孕 + 使用多重怀孕代替RJW的默认怀孕 + 激活异卵双胞胎 + 激活复数个卵子可以个别受精 + 激活双胞胎 + 允许单个卵子生成多个后代 + 双胞胎出现率 + 设置双胞胎的出现率 + 最大双胞胎数量 + 设置最大双胞胎数量 + 启用卵子图标 + 启用覆盖在子宫图标上的卵子图标 + 经血数量 + 预计经血总量 + 设置经血量 根据阴道不同出血量有变化 通常人类女性的经血量为20-80ml左右每月 + 殖民者 + 囚犯 + 盟友派系 + 中立者 + 敌对派系 + 目标小人 + 按钮和图标会出现在这些人物上 + 使用杂交扩展 + 覆盖RJW and RaceSupport的杂交定义 主杂交决定了谁的定义用在前面,不建议改变此项 + 主杂交扩展 + 母方 + 父方 + 怀孕后乳头动态变化 + 设定每次怀孕,乳头/乳晕变得更深色/宽大的程度。 + 怀孕后乳头固定变化 + 设定每次怀孕,乳头/乳晕永久性变得更深色/宽大的程度。 + 最大变化 + 乳头/乳晕不会变得比这个值更深色/宽大。 + 乳头变化速度 + 设定乳头/乳晕的变化速度。 1 = 立刻变化 + 自定义杂交 + 打开自定义杂交编辑器 该项会覆盖XML文件定义的杂交。 + 允许缩放图标 + 如有需要,允许图标缩小。 + 卵子生命周期倍增 + 倍增卵子生命周期。 在已受精阶段结束后,卵子将无视该选项死去。 + 启用产后阴道变化 + 启用产后永久阴道扩张。 如果你在用另一mod处理该项,关闭该选项。 + 变形力度 + 设置变形力度。 + 预计精子生命周期 + 预计卵子生命周期 + 1小时内受精几率: {0}% 受精卵着床几率。 白色覆盖层表示子宫内精子受精的几率。 + + 清洗阴道 + + 自定义杂交编辑器 + {0}的杂交种 + 当{0}与{1}交配,将有{3}几率生出{2}。 如果两个种族都有对方的杂交定义,将会使用父方的定义。 + + diff --git a/1.5/Languages/ChineseTraditional/DefInjected/ApparelLayerDef/RJWMenstruation.xml b/1.5/Languages/ChineseTraditional/DefInjected/ApparelLayerDef/RJWMenstruation.xml new file mode 100644 index 0000000..a90d863 --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/ApparelLayerDef/RJWMenstruation.xml @@ -0,0 +1,4 @@ + + + 生殖器 + \ No newline at end of file diff --git a/1.5/Languages/ChineseTraditional/DefInjected/Drugs/Pills_Menstruation.xml b/1.5/Languages/ChineseTraditional/DefInjected/Drugs/Pills_Menstruation.xml new file mode 100644 index 0000000..437c98e --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/Drugs/Pills_Menstruation.xml @@ -0,0 +1,11 @@ + + + 止痛藥 + 在接下來的24小時內舒緩痛經。 + +亦作用於其他類型的疼痛。 + 環孢素 + 一種免疫抑製劑。 + +用以清除體內的精子抗體,但會在24小時期間降低身體的免疫力。 + diff --git a/1.5/Languages/ChineseTraditional/DefInjected/GeneDefs/GeneDefs_Menstruation.xml b/1.5/Languages/ChineseTraditional/DefInjected/GeneDefs/GeneDefs_Menstruation.xml new file mode 100644 index 0000000..377a6b5 --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/GeneDefs/GeneDefs_Menstruation.xml @@ -0,0 +1,20 @@ + + + 月經週期 + 較短卵細胞壽命 + 未受精卵細胞存活時長僅有原先的3/4 + 雙倍卵細胞壽命 + 未受精卵細胞可存活至原先的2倍之久 + 四倍卵細胞壽命 + 未受精卵細胞可存活至原先的4倍之久 + 永不發情 + 基因攜帶者永遠不會進入發情期。 + 始終發情 + 基因攜帶者的每一個月經週期均具備發情期,無論陰道類型為何。 + 雙倍排卵 + 基因攜帶者的子宮可以在每個排卵週期產生雙倍的卵子。 + 四倍排卵 + 基因攜帶者的子宮可以在每個排卵週期產生四倍的卵子。 + 無經血 + 基因攜帶者的子宮內膜不會脫落出血。 + diff --git a/1.5/Languages/ChineseTraditional/DefInjected/HediffDef/Hediffs_Cum.xml b/1.5/Languages/ChineseTraditional/DefInjected/HediffDef/Hediffs_Cum.xml new file mode 100644 index 0000000..8402405 --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/HediffDef/Hediffs_Cum.xml @@ -0,0 +1,12 @@ + + + 精子抗體 + 精子抗體 + 精子抗體。 +增加精子的失活率。 + {0}體內存有精子抗體。 + 多產 + 多產 + 多產。 + {0}有著多產的身體。 + diff --git a/1.5/Languages/ChineseTraditional/DefInjected/HediffDef/Hediffs_Menstruation.xml b/1.5/Languages/ChineseTraditional/DefInjected/HediffDef/Hediffs_Menstruation.xml new file mode 100644 index 0000000..fef8db8 --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/HediffDef/Hediffs_Menstruation.xml @@ -0,0 +1,22 @@ + + + 月經來潮 + 發情期 + 發情期 + 由於子宮進入月經週期中最多產的階段,身體受激素影響而變得渴望懷孕。性慾急遽膨脹。 +增加發生陰道性交的頻率,並且對性伴侶的選擇標準降低。 + 發情期(隱性) + 發情期 + 由於子宮進入月經週期中最多產的階段,身體受激素影響而變得渴望懷孕。輕微增加性慾。 +輕微增加發生陰道性交的頻率。 + 止痛藥 + 緩解源自於痛經及此類神經痛的苦楚。 + 環孢素 + 由於免疫抑製劑的作用,身體抵抗感染和疾病的能力受扼制。 + + 受費洛蒙影響 + 受附近某人處於發情期之故,此人的性需求及娛樂需求正急遽上升。 + + + + diff --git a/1.5/Languages/ChineseTraditional/DefInjected/HediffDef/RJWMenstruation.xml b/1.5/Languages/ChineseTraditional/DefInjected/HediffDef/RJWMenstruation.xml new file mode 100644 index 0000000..3cce982 --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/HediffDef/RJWMenstruation.xml @@ -0,0 +1,14 @@ + + + + 中樞性疼痛 + 經期中 + 不快 + 惱人 + 疼痛 + 痛苦 + + + + + \ No newline at end of file diff --git a/1.5/Languages/ChineseTraditional/DefInjected/JobDef/RJWMenstruation.xml b/1.5/Languages/ChineseTraditional/DefInjected/JobDef/RJWMenstruation.xml new file mode 100644 index 0000000..fc04f3d --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/JobDef/RJWMenstruation.xml @@ -0,0 +1,7 @@ + + + 清洗陰道 + + + + \ No newline at end of file diff --git a/1.5/Languages/ChineseTraditional/DefInjected/JobDefs/Jobs_MilkSelf.xml b/1.5/Languages/ChineseTraditional/DefInjected/JobDefs/Jobs_MilkSelf.xml new file mode 100644 index 0000000..7d17897 --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/JobDefs/Jobs_MilkSelf.xml @@ -0,0 +1,4 @@ + + + 自行擠奶 + diff --git a/1.5/Languages/ChineseTraditional/DefInjected/KeyBindings/KeyBindings_Menstruation.xml b/1.5/Languages/ChineseTraditional/DefInjected/KeyBindings/KeyBindings_Menstruation.xml new file mode 100644 index 0000000..5b95326 --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/KeyBindings/KeyBindings_Menstruation.xml @@ -0,0 +1,4 @@ + + + 月經週期: 開啟狀態視窗 + diff --git a/1.5/Languages/ChineseTraditional/DefInjected/RecipeDef/Recipes_Surgery_Breast.xml b/1.5/Languages/ChineseTraditional/DefInjected/RecipeDef/Recipes_Surgery_Breast.xml new file mode 100644 index 0000000..7477d9d --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/RecipeDef/Recipes_Surgery_Breast.xml @@ -0,0 +1,21 @@ + + + 增大乳暈 + 增大乳暈。 + 正通過手術增大乳暈 + 縮小乳暈 + 縮小乳暈。 + 正通過手術縮小乳暈 + 增大乳頭 + 增大乳頭。 + 正通過手術增大乳頭。 + 縮小乳頭 + 縮小乳頭。 + 正通過手術縮小乳頭 + 染黑乳頭 + 染黑乳頭。 + 正通過手術染黑乳頭 + 白化乳頭 + 使乳頭顏色變粉。 + 正通過手術粉化乳頭 + diff --git a/1.5/Languages/ChineseTraditional/DefInjected/RecordDefs/Records_Womb.xml b/1.5/Languages/ChineseTraditional/DefInjected/RecordDefs/Records_Womb.xml new file mode 100644 index 0000000..3393215 --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/RecordDefs/Records_Womb.xml @@ -0,0 +1,7 @@ + + + 體內射精 + 我子宮中的精液,以毫升計。 + 受精卵 + 我體內同精子結合的卵子數。 + diff --git a/1.5/Languages/ChineseTraditional/DefInjected/StatDef/RJWMenstruation.xml b/1.5/Languages/ChineseTraditional/DefInjected/StatDef/RJWMenstruation.xml new file mode 100644 index 0000000..d485637 --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/StatDef/RJWMenstruation.xml @@ -0,0 +1,7 @@ + + + 可吸收量 + 最大可吸收的液體量 + + + \ No newline at end of file diff --git a/1.5/Languages/ChineseTraditional/DefInjected/Stats/Stats_Absorber.xml b/1.5/Languages/ChineseTraditional/DefInjected/Stats/Stats_Absorber.xml new file mode 100644 index 0000000..801727f --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/Stats/Stats_Absorber.xml @@ -0,0 +1,4 @@ + + + {0}毫升 + diff --git a/1.5/Languages/ChineseTraditional/DefInjected/TaleDefs/Tales_Cum.xml b/1.5/Languages/ChineseTraditional/DefInjected/TaleDefs/Tales_Cum.xml new file mode 100644 index 0000000..da44ed4 --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/TaleDefs/Tales_Cum.xml @@ -0,0 +1,20 @@ + + + 體內射精 + tale_noun->[FUCKER_nameDef]在[FUCKED_nameDef]體內射了精。 + image->[FUCKER_nameFull]的陰莖深深刺入了[FUCKED_nameFull]的陰道[circumstance_group] + image->[FUCKER_nameFull]的陰莖消失在了[FUCKED_nameFull]的黑洞中[circumstance_group] + image->[FUCKED_nameFull]的陰道被[FUCKER_nameFull]的陰莖灌得滿滿的[circumstance_group] + image->[FUCKED_nameFull]的陰道緊緊吸住了[FUCKER_nameFull]的陰莖[circumstance_group] + circumstance_phrase->,於是[FUCKER_nameDef]不得不咬緊牙關 + circumstance_phrase->,但[FUCKER_nameDef]卻滿臉傻笑 + circumstance_phrase->,整得[FUCKED_nameDef]在狂喜中不停顫抖 + circumstance_phrase->,而後[FUCKER_nameDef]將[FUCKER_possessive]濃稠精液射入[FUCKED_nameDef]的體內 + circumstance_phrase->。接著,[FUCKED_nameDef]深情地看著[FUCKER_nameDef]的眼眸。 + desc_sentence->[FUCKER_nameDef]的精液緩緩流出[FUCKED_nameDef]的陰道,順著大腿滴到了地上。 + desc_sentence->[FUCKER_nameDef]的精液衝進了[FUCKED_nameDef]的子宮,同[FUCKED_possessive]的卵子結合了。 + desc_sentence->[FUCKER_nameDef]的精液射入了[FUCKED_nameDef]的子宮。 + desc_sentence->[FUCKED_nameDef]的子宮被精液灌得滿滿的。 + desc_sentence->汗水從[FUCKER_nameDef]的臉上滴落。 + desc_sentence->[FUCKED_nameDef]氣喘吁吁。 + diff --git a/1.5/Languages/ChineseTraditional/DefInjected/ThingDef/RJWMenstruation.xml b/1.5/Languages/ChineseTraditional/DefInjected/ThingDef/RJWMenstruation.xml new file mode 100644 index 0000000..9404fb7 --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/ThingDef/RJWMenstruation.xml @@ -0,0 +1,31 @@ + + + + +衛生棉條 + +從陰道吸收液體的衛生棉條 + +濕的衛生棉條 + +使用過的濕衛生棉條 + +衛生棉 + +從陰道吸收液體的衛生棉 + +濕的衛生棉 + +使用過的濕衛生棉 + +卵巢再生藥物 + +使卵巢再生以增加可排卵的卵子 卵子消耗量越大,效果越差 不能緩解更年期症狀 + +排卵藥 + +誘導排卵的藥物 可導致更年期提前 + +混合物 + + \ No newline at end of file diff --git a/1.5/Languages/ChineseTraditional/DefInjected/ThoughtDef/RJWMenstruation.xml b/1.5/Languages/ChineseTraditional/DefInjected/ThoughtDef/RJWMenstruation.xml new file mode 100644 index 0000000..e793dd3 --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/ThoughtDef/RJWMenstruation.xml @@ -0,0 +1,23 @@ + + + 褲濕啦 + 能不能有什麼東西來吸體液啊? + 被{0}中出了 + 我擔心我可能會懷孕... + 被{0}中出了 + 雖然機率很低,但我還是擔心懷孕... + 被{0}中出了 + 好期待懷孕啊! + 被{0}中出了 + 雖說不太可能懷孕,但是這個幻想真的好有趣! + 中出了{0} + 超爽的 + 被{0}中出了 + 我不想要他的孩子! + 被{0}中出了 + 雖說不太可能懷上,但是這真的很噁! + 中出了{0} + 我上了那個婊子...哈! + 不想要的懷孕 + 我該怎麼照顧寶寶?怎麼辦怎麼辦怎麼辦... + \ No newline at end of file diff --git a/1.5/Languages/ChineseTraditional/DefInjected/ThoughtDefs/Thoughts_sex.xml b/1.5/Languages/ChineseTraditional/DefInjected/ThoughtDefs/Thoughts_sex.xml new file mode 100644 index 0000000..86e27de --- /dev/null +++ b/1.5/Languages/ChineseTraditional/DefInjected/ThoughtDefs/Thoughts_sex.xml @@ -0,0 +1,23 @@ + + + {0}內射了 + 我著了什麼魔,竟然讓他做出了這種事! + 不情願的妊娠 + 有個寶寶在我肚子裡。但願我能搞定這事。 + 吃了避孕藥 + 總算把這事了結了。 + 吃了避孕藥 + 我想要小孩! + + 卵母細胞再生術 + 我可以繼續繁衍一小段時間了! + + 內射了{0} + 讓她懷孕正是我的職責所在。 + {0}內射了我 + 我希望這次能懷上,讓我盡到責任。 + {0}內射了我 + 我知道我有生育的義務,但是難道非他不可嗎? + 服用避孕藥 + 我的信仰要求我能夠懷孕。 + diff --git a/1.5/Languages/ChineseTraditional/Keyed/RJW_Menstruation.xml b/1.5/Languages/ChineseTraditional/Keyed/RJW_Menstruation.xml new file mode 100644 index 0000000..d190877 --- /dev/null +++ b/1.5/Languages/ChineseTraditional/Keyed/RJW_Menstruation.xml @@ -0,0 +1,171 @@ + + + RJW-月經週期 + 經血 + + 卵泡期 + 排卵 + 黃體期 + 月經來潮 + 妊娠 + 從生產中恢復 + + 更年期 + 狀態 + 胎兒 + 父親 + 陰道精液列表 + 已受精 + 受精中 + 排卵 + + + 啟用子宮圖標 + 啟用子宮圖標框 + 啟用動物經期 + 模擬動物的經期. +此選項將在保存讀取後生效 +不推薦開啟此選項 + 著床機會 + 設置受精卵的著床機會 + 受精的機會 + 設置每小時受精的機會 + 每小時陰道中的精液量衰減率 + 陰道中的精液量將以這個比率減少 + 每小時精子活力衰減率 + 列表中精液的活力將按此比率減少。該值間接影響生育率。 + 月經加速 + 加快月經週期 + 除錯 + 顯示除錯資訊 +啟用時會令「胎兒信息級別」選項調至「全部細節」。 + 子宮狀態 + 在狀態窗口中繪製子宮圖標 + 陰道狀態 + 在狀態窗口中繪製陰道和肛門圖標 + 胎兒信息級別 + 顯示有關胎兒的所有信息 + 顯示妊娠後胎兒的所有信息 + 不顯示有關胎兒的信息,但顯示懷孕後胎兒的圖像 + 不顯示胎兒圖像和信息 + 啟用更年期 + 啟用更年期效果,使小人隨著時間的推移而變得不育 +如果您較長壽的外星人種族有碰到任何問題,請關閉此選項. +此選項將在保存讀取後生效 + 啟用多胎妊娠 + 使用多胎妊娠代替RJW的默認懷孕 + 啟用異卵雙胞胎 + 啟用複數個卵子分別受精 + 啟用同卵雙胞胎 + 允許單個卵子產生多個後代 + 雙胞胎出現率 + 設置雙胞胎的出現率 + 最大雙胞胎數量 + 設置最大雙胞胎數量 + 清洗陰道 + + 絕經 + 乏情期 + 卵巢正準備釋放卵子。排卵將在此階段結束時發生。 + 卵巢正準備釋放卵子。如果精液進入子宮,就會發生排卵。 + 卵巢正在將卵子釋放至子宮中。 + 子宮已準備好接受受精卵。如果在該階段結束之前有受精卵著床,將進入懷孕階段。 + 子宮內膜正在脫落,並將所有未能著床的受精卵排出。 + 寶寶正在子宮中茁壯成長。假以時日,這個世界將會迎來一個新居民。 + 子宮正從最近的妊娠中恢復。 + 子宮處於不孕的狀態。 + 隨著卵巢枯竭,月經週期變得不規則。 + 卵巢枯竭,身體已經無法再產生卵子。 + 處於繁殖季節之外。月經週期會在時機到來時恢復。 + 狀態 + 自行擠奶 + 將精液擠入桶中 + 將精液留在子宮中 + 不明 + 啟用子宮圖標 + 啟用健康面板中的按鈕 + 啟用卵細胞覆蓋層 + 在子宮圖示上顯示卵細胞狀態 + 出血量 + 預估總出血量 + 預估的出血量。 +正常人類女性在月經週期內大約會流失20~80毫升的血。 + 殖民者 + 囚犯 + 同盟派系 + 中立 + 敵對派系 + 本模組作用於: + 這些小人的「RJW月經週期」工具欄對玩家可見。 + 使用進階雜交定義 + 覆寫RJW和RaceSupport插件的雜交定義。Overrides RJW and RaceSupport's hybrid definition. +主導混合擴展決定了首先使用誰的定義。不建議更改此設置。Dominant hybrid extension determines whose definition used first. Not recommended to change this. + 主導混合擴展Dominant hybrid extension + 母本 + 父本 + 胸部在孕期增大 + 調整小人的乳房在懷孕期間的增長幅度。有些小人可能會比其他人長得更大。 + 乳頭在孕期間改變 + 變更乳頭在孕期間的改變幅度。 + 永久改變乳頭 + 乳頭在孕期間的改變會在孕期結束後保留多少? + 客製化雜交細節 + 開啟雜交編輯器 +該選項會覆寫XML文件中的雜交定義。 + 允許圖標縮小 + 允許圖標在特殊場合縮小。 + 卵細胞生命期乘數 + 以倍數延長卵細胞的生命期 +無論此數值為何,所有未著床的卵子都會在黃體期結束時死亡。 + 啟用產後陰道擴張 + 令陰道在產後永久擴張。 +若存在其他模組擁有類似功能,請關閉此功能。 + 擴張力度 + 調節擴張力度。 + 啟用「擠出精液」按鈕 + 令「發情期」機制覆寫RJW的濫交選項 + 啟用時,處於顯式發情期的小人將會使用以下選項來選定床伴。RJW的原始設定會被忽略。 +所有數值與RJW的對應選項相同。 + 發情期床伴:最低fuckability + 發情期床伴:最低吸引度 + 發情期床伴:最低態度值 + 預估精子壽命 + 預估卵子壽命 + 受精卵著床機率。 +本小時內受精機率:{0}% + 回歸預設值 + 擠出精液 + 客製化雜交編輯器 + {0}之雜交 + 當{0}與{1}產生後代,有{3}的概率生出{2}。 +若兩個種族相互間皆存在雜交定義,則以父本的定義為準。 + + 使用RJW的簡單懷孕系統 + 使用本模組的多重懷孕 + 使用「生機」(Biotech)追加的懷孕機制 + 於「徵召」狀態下仍顯示子宮狀態 + 角色處於被徵召狀態時,子宮圖標不予隱藏。 + 沒有卵細胞 + 必須擁有子宮 + {PAWN_labelShort}完成了{PAWN_possessive}卵母細胞再生術(cycle) + + 排卵機率:{0} + 排卵期內每個卵子的獨立排卵機率。 + (測試中!) 允許在「生機」(Biotech)追加的懷孕機制中出現多胞胎。 + 啟用這個選項將允許同卵或異卵雙胞胎出現在「生機」(Biotech)追加的懷孕機制中。 +一併將啟用雜交系統;然而兩個類人(humanlikes)生物絕不可能生出動物。 + + 玩家小人刷新間隔 + 殖民者、囚犯和奴隸的子宮狀態應該每隔多久刷新一次? +較小的刷新間隔可以更精確地模擬真實子宮;較大的刷新間隔可以提升遊戲流暢度 + 非玩家小人刷新間隔 + 非玩家勢力控制下的小人的子宮應該每隔多久刷新一次? +較小的刷新間隔可以更精確地模擬真實子宮;較大的刷新間隔可以提升遊戲流暢度 + 動物子宮刷新間隔 + 動物們的子宮應該多久刷新一次? +較小的刷新間隔可以更精確地模擬真實子宮;較大的刷新間隔可以提升遊戲流暢度 + 啟用費洛蒙機制 + 擁有發情期的類人生物在發情期將刺激附近的雄性類人生物,使其性慾大增。 + 動物費洛蒙效果 + 選定擁有發情期的動物在發情期內對類人生物的影響。 + diff --git a/1.5/Languages/English/Keyed/RJW_Menstruation.xml b/1.5/Languages/English/Keyed/RJW_Menstruation.xml new file mode 100644 index 0000000..7aa650e --- /dev/null +++ b/1.5/Languages/English/Keyed/RJW_Menstruation.xml @@ -0,0 +1,152 @@ + + + RJW Menstruation Cycle + + menstrual blood + Empty + Follicular + Ovulation + Luteal + In period + Pregnant + Recovering from birth + None + Climacteric + Menopause + Anestrus + The ovaries are preparing to release an egg. Ovulation will occur at the end of this phase. + The ovaries are preparing to release an egg. Ovulation will occur if semen enters the womb. + The ovaries are releasing an egg into the womb. + The womb is prepared to recieve a fertilized egg. Pregnancy will result if one implants before the end of the stage. + The womb is shedding its lining, along with any eggs that failed to implant. + A baby is growing inside the womb. With time and care, it will become a new resident of this world. + The womb is recovering from its recent pregnancy. + The womb is not fertile and cannot become pregnant. + The ovaries have neared exhaustion and the menstrual cycle has become irregular. + The ovaries have been exhausted and the womb can no longer produce eggs. + The womb is out of breeding season. The cycle will resume once conditions are met. + Status + Lactate self + State + Fetus + Father + Cum list + Fertilized + Fertilizing + Ovulated + + + Unknown + Absorbed + + + Enable womb icon + Enable button in health tab + Enable animal cycle + Simulate animal cycles. Not recommended. + Implantation chance + Base implantation chance of fertilized egg This value affects the chance of impregnation. + Fertilization chance + The fertilization chance per ml of sperm per hour This value affects the chance of impregnation. + Cum decay ratio per hour + The amount of cum in the womb will drop by this amount every hour This value affects the chance of impregnation. + Cum fertility decay ratio per hour + Cum will lose fertility by this amount every hour This value affects fertilization chance indirectly. + Cycle acceleration + Accelerate menstruation cycle This can cause early menopause and infertility. Setting this lower than x12 is recommended. Rimworld's timescale: x6(default) + Colonist update interval + How often the womb of each of your colonists, prisoners, and slaves update. Lowering this will improve accuracy, increasing this can improve performance. + Non-colonist update interval + How often the womb of humans you don't control update. Lowering this will improve accuracy, increasing this can improve performance. + Animal update interval + How often the womb of animals update. Lowering this will improve accuracy, increasing this can improve performance. + Debug + Show debug information. + Womb status + Draw womb icon in status window. + Vagina and breast status + Draw vagina, anus and breast icons in the status window. + Fetus information level + Show all information about a fetus. + Show all information about a fetus after discovered pregnancy. + Show only image of a fetus after discovered pregnancy. + Do not show any information about a fetus. + Enable menopause + Enable menopause effect that makes pawn infertile when they run out of eggs. If you have problems with long lived races, turn off this option. + Enable pheromones + Allow humanlikes in visible estrus to increase the sex drive of nearby humanlike males. + Animal pheromone effect + Set the effect that animals in visible estrus have on humanlikes. + Use multiple pregnancy + Use multiple pregnancy instead RJW's default pregnancy Disable this option if you are in trouble with impregnation RJW pregnancy should be turned on. + Enable hetero ovular twins + Allow pregnancy from multiple eggs at the same time. + Enable enzygotic twins + Enable a single egg to result in multiple identical offspring. + Enzygotic twins chance + The chance of identical twins. + Max enzygotic twins + The maximum number of identical siblings. + Enable egg overlay + Enable egg overlay on womb icon. + Bleeding amount + Estimated total bleeding amount + The approximate bleeding amount. The normal bleeding amount of a human is about 20~80ml per cycle. + Colonist + Prisoner + Allied Faction + Neutral + Hostile Faction + Target pawns: + The gizmo and button will appear for these pawns + Use hybrid extension + Overrides RJW and RaceSupport's hybrid definition. Dominant hybrid extension determines whose definition used first. Not recommended to change this. + Dominant hybrid extension + Mother + Father + Breast growth during pregnancy + Change how much a pregnant pawn's breasts will grow when pregnant. Some pawns will grow more than others. + Nipple change during pregnancy + Change how much a pregnant pawn's nipples will change during pregnancy. + Permanent nipple change after pregnancy + Adjusts approximately how much of a pregnant pawn's nipples will remain changed after the pregnancy ends. + Customize Hybrids + Open custom hybrid editor. This will overrides hybrid definitions of XML files. + Allow shrink icon + Let icon become smaller if needed. + Egg lifespan multiplier + Multiply egg's lifespan. All non-implanted eggs will die at end of luteal stage regardless of this setting. + Enable vagina morph after birth + Enable permanent vagina stretch after birth. If you are using another mod handling this, turn off this option. + Morph power + Set morph power. + Estrus overrides RJW hookup settings + If enabled, a pawn in visible estrus will use these settings for potential impregnation hookups instead of the RJW settings. All settings default to their RJW counterparts. + Hookup minimum fuckability in estrus + Hookup minimum attractability in estrus + Hookup minimum opinion in estrus + Estimated sperm lifespan + Estimated egg lifespan + Ovulation {0} + Chance of each egg being released during ovulation. + Implantation chance of fertilized eggs. Chance of fertilization this hour: {0}% + Use basic RJW pregnancy + Use menstruation multiple pregnancy + Use Biotech pregnancy + (EXPERIMENTAL) Enable multiple babies/twins in a single Biotech pregnancy. + Enabling this option will allow identical and hetero ovular twins with Biotech. Also allows the hybrid system, but two humanlikes cannot produce an animal. + Show womb status when drafted + Draw womb icon for drafted pawns + Reset to default + + Vaginal washing + + Custom Hybrid Editor + Hybrids of {0} + When {0} breed with {1}, {2} will be born at {3} chance. If both races have hybrid definitions for each other, the father's definition will be used. + + No eggs + Must have a womb + {PAWN_labelShort} has completed {PAWN_possessive} egg restoration cycle. + + \ No newline at end of file diff --git a/1.5/Languages/Japanese/DefInjected/ApparelLayerDef/RJWMenstruation.xml b/1.5/Languages/Japanese/DefInjected/ApparelLayerDef/RJWMenstruation.xml new file mode 100644 index 0000000..cf5232e --- /dev/null +++ b/1.5/Languages/Japanese/DefInjected/ApparelLayerDef/RJWMenstruation.xml @@ -0,0 +1,4 @@ + + + 性器 + \ No newline at end of file diff --git a/1.5/Languages/Japanese/DefInjected/Drugs/Pills_Menstruation.xml b/1.5/Languages/Japanese/DefInjected/Drugs/Pills_Menstruation.xml new file mode 100644 index 0000000..a801670 --- /dev/null +++ b/1.5/Languages/Japanese/DefInjected/Drugs/Pills_Menstruation.xml @@ -0,0 +1,7 @@ + + + 鎮痛剤 + 生理痛を24時間和らげます。 その他の痛みにも効果あり。 + シクロスポリン + 免疫抑制剤。 抗精子抗体を直すことができるが、24時間の間、体の免疫力は低下する。 + diff --git a/1.5/Languages/Japanese/DefInjected/HediffDef/RJWMenstruation.xml b/1.5/Languages/Japanese/DefInjected/HediffDef/RJWMenstruation.xml new file mode 100644 index 0000000..e066065 --- /dev/null +++ b/1.5/Languages/Japanese/DefInjected/HediffDef/RJWMenstruation.xml @@ -0,0 +1,14 @@ + + + + 生理中 + 月経周期の終わりに膣からの出血。よく痛い。 + 不快 + 痒い + 痛い + 苦痛 + + + + + \ No newline at end of file diff --git a/1.5/Languages/Japanese/DefInjected/JobDef/RJWMenstruation.xml b/1.5/Languages/Japanese/DefInjected/JobDef/RJWMenstruation.xml new file mode 100644 index 0000000..abd8a16 --- /dev/null +++ b/1.5/Languages/Japanese/DefInjected/JobDef/RJWMenstruation.xml @@ -0,0 +1,7 @@ + + + 膣を洗っている + + + + \ No newline at end of file diff --git a/1.5/Languages/Japanese/DefInjected/StatDef/RJWMenstruation.xml b/1.5/Languages/Japanese/DefInjected/StatDef/RJWMenstruation.xml new file mode 100644 index 0000000..c5ce3d0 --- /dev/null +++ b/1.5/Languages/Japanese/DefInjected/StatDef/RJWMenstruation.xml @@ -0,0 +1,7 @@ + + + 吸収量 + 吸収可能な液体の最大量。 + + + \ No newline at end of file diff --git a/1.5/Languages/Japanese/DefInjected/ThingDef/RJWMenstruation.xml b/1.5/Languages/Japanese/DefInjected/ThingDef/RJWMenstruation.xml new file mode 100644 index 0000000..76f4ba9 --- /dev/null +++ b/1.5/Languages/Japanese/DefInjected/ThingDef/RJWMenstruation.xml @@ -0,0 +1,31 @@ + + + + +タンポン + +膣内の体液を吸収するタンポン。長時間に着けて感染症を引き起こすことがある。 + +汚れたタンポン + +濡れた使用済みタンポン。そのままにしておくと感染症を引き起こす可能性がある。 + +生理用品 + +膣からの体液を吸収するためのナプキン。 + +汚れた生理用品 + +濡れた使用済みナプキン + +卵巣再生薬 + +卵巣を回復させ、卵子の数をある程度を回復させる。 卵子がほとんど残っていない卵巣にはあまり効果がない。 更年期の回復はできない。 + +排卵剤 + +過排卵を誘発し、次の排卵で卵子を1~4個余分に産生させる。 更年期を早める可能性がある。 + +混じった物 + + \ No newline at end of file diff --git a/1.5/Languages/Japanese/DefInjected/ThoughtDefs/RJWMenstruation.xml b/1.5/Languages/Japanese/DefInjected/ThoughtDefs/RJWMenstruation.xml new file mode 100644 index 0000000..7092dde --- /dev/null +++ b/1.5/Languages/Japanese/DefInjected/ThoughtDefs/RJWMenstruation.xml @@ -0,0 +1,33 @@ + + + ぽたぽた + これを吸収するものはないのかな? + {0}に中出した + ライバルに中出した + {0}に中出した + 気持ちよかった。 + {0}に中出した + 妊娠するといいな。 + {0}に中出された + あいつの子を妊娠したくない! + {0}に中出された + そんなことをさせるなんて、私は何を考えていたんだろう? + {0}に中出された + 可能性は低いけど、妊娠できるかどうか心配で... + {0}に中出された + 妊娠しないか心配なんだ。 + {0}に中出された + 妊娠するとは思わないけど、妄想するのは楽しい。 + {0}に中出された + 妊娠することはないだろうけど、やっぱり嫌だ。 + 望まない妊娠 + 赤ん坊の世話なんてできるか?どうすればいい? + 望まない妊娠 + 赤ちゃんが生まれる。なんとかなるといいな。 + 避妊ピルを飲んだ + もう大丈夫です。 + 避妊ピルを飲んだ + 妊娠したい。 + 卵巣復活を得た + もう少しの間、繁殖ことができる。 + diff --git a/1.5/Languages/Japanese/Keyed/RJW_Menstruation.xml b/1.5/Languages/Japanese/Keyed/RJW_Menstruation.xml new file mode 100644 index 0000000..538bdc3 --- /dev/null +++ b/1.5/Languages/Japanese/Keyed/RJW_Menstruation.xml @@ -0,0 +1,152 @@ + + + RJW Menstruation Cycle + + 経血 + 空っぽ + 卵胞期 + 排卵期 + 黄体期 + 月経期 + 妊娠 + 出産後 + 無し + クリマクテリック + 更年期 + 無発情期 + 卵巣は卵子を放出するの準備をしています。この時期の終わりに排卵が起こります。 + 卵巣は卵子を放出するの準備をしています。精液が子宮に入ると排卵が起こります。 + 卵巣が卵子を子宮に放出しています。 + 子宮は受精卵を受け入れる準備ができている。この時期が終る前に受精卵が着床すれば妊娠となります。 + 子宮内膜は剥がれ落ち、着床できなかった受精卵を排出します。 + 子宮に赤ちゃんがいます。時間とケアによって、この世界の新しい住人となる。 + 子宮は最近の妊娠から回復しています。 + 子宮は繁殖能力がなく、妊娠することはできない。 + 卵巣が枯渇すると、月経周期が不規則になる。 + 。卵巣が枯渇し、子宮が卵子を産み出せなくなる。 + 繁殖期を過ぎた。時期が来れば発情周期は再開する。 + ステータス + 自分を搾乳する + ステータス + 胎児 + 父親 + 精液リスト + 受精卵 + 受精中 + 排卵済み + + + 精液をバケッツに集める + 子宮に精液をためる + 不明 + + + + Enable womb icon + Enable button in health tab + Enable animal cycle + Simulate animal cycles. Not recommended. + Implantation chance + Base implantation chance of fertilized egg This value affects the chance of impregnation. + Fertilization chance + The fertilization chance per ml of sperm per hour This value affects the chance of impregnation. + Cum decay ratio per hour + The amount of cum in the womb will drop by this amount every hour This value affects the chance of impregnation. + Cum fertility decay ratio per hour + Cum will lose fertility by this amount every hour This value affects fertilization chance indirectly. + Cycle acceleration + Accelerate menstruation cycle This can cause early menopause and infertility. Setting this lower than x12 is recommended. Rimworld's timescale: x6(default) + Colonist update interval + How often the womb of each of your colonists, prisoners, and slaves update. Lowering this will improve accuracy, increasing this can improve performance. + Non-colonist update interval + How often the womb of humans you don't control update. Lowering this will improve accuracy, increasing this can improve performance. + Animal update interval + How often the womb of animals update. Lowering this will improve accuracy, increasing this can improve performance. + Debug + Show debug information. + Womb status + Draw womb icon in status window. + Vagina and breast status + Draw vagina, anus and breast icons in the status window. + Fetus information level + Show all information about a fetus. + Show all information about a fetus after discovered pregnancy. + Show only image of a fetus after discovered pregnancy. + Do not show any information about a fetus. + Enable menopause + Enable menopause effect that makes pawn infertile when they run out of eggs If you have problems with long lived races, turn off this option. + Use multiple pregnancy + Use multiple pregnancy instead RJW's default pregnancy Disable this option if you are in trouble with impregnation RJW pregnancy should be turned on. + Enable hetero ovular twins + Allow pregnancy from multiple eggs at the same time. + Enable enzygotic twins + Enable a single egg to result in multiple identical offspring. + Enzygotic twins chance + The chance of identical twins. + Max enzygotic twins + The maximum number of identical siblings. + Enable egg overlay + Enable egg overlay on womb icon. + Bleeding amount + Estimated total bleeding amount + The approximate bleeding amount. The normal bleeding amount of a human is about 20~80ml per cycle. + Colonist + Prisoner + Allied Faction + Neutral + Hostile Faction + Target pawns: + The gizmo and button will appear for these pawns + Use hybrid extension + Overrides RJW and RaceSupport's hybrid definition. Dominant hybrid extension determines whose definition used first. Not recommended to change this. + Dominant hybrid extension + + + Breast growth during pregnancy + Change how much a pregnant pawn's breasts will grow when pregnant. Some pawns will grow more than others. + Nipple change during pregnancy + Change how much a pregnant pawn's nipples will change during pregnancy. + Permanent nipple change after pregnancy + Adjusts approximately how much of a pregnant pawn's nipples will remain changed after the pregnancy ends. + Customize Hybrids + Open custom hybrid editor. This will overrides hybrid definitions of XML files. + Allow shrink icon + Let icon become smaller if needed. + Egg lifespan multiplier + Multiply egg's lifespan. All non-implanted eggs will die at end of luteal stage regardless of this setting. + Enable vagina morph after birth + Enable permanent vagina stretch after birth. If you are using another mod handling this, turn off this option. + Morph power + Set morph power. + Enable gather cum gizmo + Estrus overrides RJW hookup settings + If enabled, a pawn in visible estrus will use these settings for potential impregnation hookups instead of the RJW settings. All settings default to their RJW counterparts. + Hookup minimum fuckability in estrus + Hookup minimum attractability in estrus + Hookup minimum opinion in estrus + Estimated sperm lifespan + Estimated egg lifespan + 排卵 {0} + 排卵時に各卵が放出される確率。 + 受精卵の着床確率。 この時間に受精する確率{0}% + Use basic RJW pregnancy + Use menstruation multiple pregnancy + Use Biotech pregnancy + (EXPERIMENTAL) Enable multiple babies/twins in a single Biotech pregnancy. + Enabling this option will allow identical and hetero ovular twins with Biotech. Also allows the hybrid system, but two humanlikes cannot produce an animal. + Show womb status when drafted + Draw womb icon for drafted pawns + Reset to default + + 精液を収集 + 膣を洗う + + Custom Hybrid Editor + Hybrids of {0} + When {0} breed with {1}, {2} will be born at {3} chance. If both races have hybrid definitions for each other, the father's definition will be used. + + 卵子がない + 子宮が必要 + {PAWN_labelShort} has completed {PAWN_possessive} egg restoration cycle. + + \ No newline at end of file diff --git a/1.5/Languages/Korean/DefInjected/ApparelLayerDef/RJWMenstruation.xml b/1.5/Languages/Korean/DefInjected/ApparelLayerDef/RJWMenstruation.xml new file mode 100644 index 0000000..9c687e3 --- /dev/null +++ b/1.5/Languages/Korean/DefInjected/ApparelLayerDef/RJWMenstruation.xml @@ -0,0 +1,4 @@ + + + 성기 + \ No newline at end of file diff --git a/1.5/Languages/Korean/DefInjected/HediffDef/RJWMenstruation.xml b/1.5/Languages/Korean/DefInjected/HediffDef/RJWMenstruation.xml new file mode 100644 index 0000000..0b9539a --- /dev/null +++ b/1.5/Languages/Korean/DefInjected/HediffDef/RJWMenstruation.xml @@ -0,0 +1,18 @@ + + + 생리통 + 생리중입니다. + 불편함 + 짜증남 + 아픔 + 고통스러움 + 발정기 + 발정기입니다. + 발정기(숨김) + 발정기입니다. + 진통제 + 약간의 고통을 줄여줍니다. + + + + \ No newline at end of file diff --git a/1.5/Languages/Korean/DefInjected/JobDef/RJWMenstruation.xml b/1.5/Languages/Korean/DefInjected/JobDef/RJWMenstruation.xml new file mode 100644 index 0000000..67ae283 --- /dev/null +++ b/1.5/Languages/Korean/DefInjected/JobDef/RJWMenstruation.xml @@ -0,0 +1,7 @@ + + + 질세척 하는중 + + + + \ No newline at end of file diff --git a/1.5/Languages/Korean/DefInjected/RecipeDef/BreastSurgeries.xml b/1.5/Languages/Korean/DefInjected/RecipeDef/BreastSurgeries.xml new file mode 100644 index 0000000..8c501f4 --- /dev/null +++ b/1.5/Languages/Korean/DefInjected/RecipeDef/BreastSurgeries.xml @@ -0,0 +1,15 @@ + + + 유륜확대 수술 + 유륜을 크게만듭니다. + 유륜확대 수술중 + 유륜축소 수술 + 유륜을 작게만듭니다. + 유륜축소 수술중 + 유두확대 수술 + 유두를 크게만듭니다. + 유두확대 수술중 + 유두축소 수술 + 유두를 작게만듭니다. + 유두축소 수술중 + \ No newline at end of file diff --git a/1.5/Languages/Korean/DefInjected/RecordDef/RJWMenstruation.xml b/1.5/Languages/Korean/DefInjected/RecordDef/RJWMenstruation.xml new file mode 100644 index 0000000..b807e13 --- /dev/null +++ b/1.5/Languages/Korean/DefInjected/RecordDef/RJWMenstruation.xml @@ -0,0 +1,5 @@ + + + 질내사정 + 질내사정당한 정액 양 + \ No newline at end of file diff --git a/1.5/Languages/Korean/DefInjected/StatDef/RJWMenstruation.xml b/1.5/Languages/Korean/DefInjected/StatDef/RJWMenstruation.xml new file mode 100644 index 0000000..f92112e --- /dev/null +++ b/1.5/Languages/Korean/DefInjected/StatDef/RJWMenstruation.xml @@ -0,0 +1,7 @@ + + + 흡수량 + 액체를 흡수할수 있는 정도입니다. + + + \ No newline at end of file diff --git a/1.5/Languages/Korean/DefInjected/ThingDef/RJWMenstruation.xml b/1.5/Languages/Korean/DefInjected/ThingDef/RJWMenstruation.xml new file mode 100644 index 0000000..c48a975 --- /dev/null +++ b/1.5/Languages/Korean/DefInjected/ThingDef/RJWMenstruation.xml @@ -0,0 +1,20 @@ + + + 탐폰 + 보지에서 나오는 액체를 흡수하는 탐폰입니다. 오래 착용하고 있을 경우 감염이 발생할수도 있습니다. + 더러운 탐폰 + 사용된 축축한 탐폰입니다. + 생리대 + 보지에서 나오는 액체를 흡수하는 생리대입니다. 흡수량 이상의 액체가 나올경우 샐수있습니다. + 젖은 생리대 + 사용된 축축한 생리대입니다. + 난소 재생약 + 난소를 재생시켜 배출할수있는 난자의 양을 증가시킵니다. 난자 소모량이 클수록 효과가 줄어듭니다. 폐경을 회복시키지 않습니다. + 과배란 유도제 + 과배란을 유도하는 약물입니다. 조기폐경을 초래할수도 있습니다. + 진통제 + 하루동안 약간의 통증을 줄여줍니다. + 혼합물 + + + \ No newline at end of file diff --git a/1.5/Languages/Korean/DefInjected/ThoughtDef/RJWMenstruation.xml b/1.5/Languages/Korean/DefInjected/ThoughtDef/RJWMenstruation.xml new file mode 100644 index 0000000..9509437 --- /dev/null +++ b/1.5/Languages/Korean/DefInjected/ThoughtDef/RJWMenstruation.xml @@ -0,0 +1,29 @@ + + + 가랑이가 축축함 + 찝찝해... + {0}에게 질내사정당함 + 임신할까봐 걱정돼... + {0}에게 질내사정당함 + 확률은 낮겠지만 임신할까봐 걱정돼... + {0}에게 질내사정당함 + 임신할것 같아 + {0}에게 질내사정당함 + 좋았어... + {0}에게 질내사정함 + 질싸를하니 기분이 좋네 + {0}에게 질내사정당함 + 그새끼의 자식을 임신하고 싶지 않아... + {0}에게 질내사정당함 + 안전일이였지만 기분나빠 + {0}에게 질내사정함 + 그년한테 질싸를했어 + 원치않은 임신 + 어떻게 해야하지?... 그년한테 질싸를했어 + 원치않은 임신 + 어떻게 해야하지?... + 피임약 복용 + 괜찮을거야 + 피임약 복용 + 임신하고싶어 + \ No newline at end of file diff --git a/1.5/Languages/Korean/Keyed/RJW_Menstruation.xml b/1.5/Languages/Korean/Keyed/RJW_Menstruation.xml new file mode 100644 index 0000000..829fcf5 --- /dev/null +++ b/1.5/Languages/Korean/Keyed/RJW_Menstruation.xml @@ -0,0 +1,110 @@ + + + RJW Menstruation Cycle + + 생리혈 + 없음 + 난포기 + 배란 + 황체기 + 생리중 + 임신 + 회복기 + 없음 + 갱년기 + 휴지기 + 상태창 + 모유 짜기 + 상태 + 태아 + + 정액목록 + 수정됨 + 수정중 + 배란 + + + + 자궁아이콘 활성화 + 건강탭에 버튼 추가 + 동물주기 활성화 + 동물의 월경주기를 시뮬레이션합니다. 변경한후에 세이브로드가 필요합니다. not recommended + 착상확률 + 수정란의 착상확률을 설정합니다. + 수정확률 + 1시간마다 정자가 난자를 수정시킬확률을 설정합니다. + 시간당 정액배출비율 + 이 비율만큼 매 시간마다 정액이 배출됩니다. + 시간당 정자 사망비율 + 이 비율만큼 매 시간마다 정자가 사망해 정액이 생식능력을 잃습니다. 정자 예상수명: 정액이 대부분의 생식능력을 잃는 시간입니다. + 주기 가속 + 월경주기를 더 빠르게합니다. 이 설정은 조기폐경과 난임을 유발할수도 있습니다. 12배속 이하로 설정하는것을 권장합니다. 림월드의 시간배율: x6(default) + Debug + 디버그정보를 보여줍니다. + 자궁 그림 + 상태창에 자궁그림을 표시합니다. + 가슴, 보지 그림 + 상태창에 가슴, 보지와 항문그림을 표시합니다. + 태아 정보 + 태아에 대한 모든 정보를 표시합니다. + 임신을 발견한 이후에 태아에 대한 모든 정보를 표시합니다. + 태아에 대한 정보를 표시하지 않지만, 임신한 이후 태아이미지를 표시합니다. + 태아에 대한 어떠한 정보도 표시하지 않습니다. + 폐경기 활성화 + 시간이 지남에따라 불임상태로 만드는 폐경기를 활성화합니다. 수명이 긴 종족을 사용할때 문제가 있으면 이 옵션을 끄세요. 변경한후에 세이브로드가 필요합니다. + 다중임신 + RJW의 기본임신 대신 다중임신을 사용합니다. 임신에 문제가 있다면 이 기능을 끄는것으로 해결될수도 있습니다. RJW 임신이 활성화 되어야 합니다. + 이란성 쌍둥이 활성화 + 다수의 난자가 임신으로 이어지게 합니다. + 일란성 쌍둥이 활성화 + 하나의 난자가 다수의 태아로 나뉘게 합니다. + 일란성 쌍둥이 확률 + 일란성 쌍둥이가 발생할 확률을 설정합니다. + 최대 일란성 쌍둥이 수 + 일란성 쌍둥이의 수를 제한합니다. + 난자 오버레이 + 자궁그림 위에 난자그림를 표시합니다. + 생리양 + 예상되는 총 생리양 + 생리혈의 양을 설정합니다. 실제 생리양은 보지에따라 다를수 있습니다. 일반적인 인간 여성의 생리량은 약 20~80ml입니다. + 정착민 + 죄수 + 동맹관계 + 중립 + 적대관계 + 표시 대상 + 아이콘과 버튼을 표시할 대상입니다. + 잡종 정의 대체 + RJW와 RaceSupport의 잡종정의를 대체합니다. 우선순위는 누구의 잡종 정의를 우선으로 사용할지 정합니다. 변경하지 않는것을 추천합니다. + 우선순위 + + + 임신후 유두 변화량 + 임신후에 유두가 얼마나 어두워지고 커지는지 설정합니다. + 유두 영구변화량 + 매번 임신할때마다 유두가 얼마나 영구적으로 어두워지고 커지는지 설정합니다. + 최대 변화량 + 유두는 이 값 이상으로 변하지 않습니다. + 유두 변화 속도 + 유두가 얼마나 빨리 변하는지 설정합니다. + 잡종 정의 변경하기 + 사용자 지정 잡종 편집기를 엽니다. 이 설정은 XML파일의 잡종 정의를 대체합니다. + 아이콘 축소 허용 + 아이콘 축소를 허용합니다. + 난자 수명 배수 + 난자 수명을 늘립니다. 이 설정에 관계없이 황체기가 끝나면 난자는 죽습니다. + 출산 이후 보지 변화 활성화 + 출산 이후 보지가 영구적으로 늘어나게 합니다. 만약 이 설정을 다루고있는 다른 모드가 있다면, 이 설정을 끄세요. + 변화 강도 + 변화 강도를 설정합니다. + 정자 예상수명 + 난자 예상수명 + 한시간 안에 수정될 확률: {0}% 수정란이 임신으로 진행될 확률입니다. 흰색 오버레이는 정자가 난자를 수정시킬 확률을 표시하는 것입니다. + + 질세척 + + 사용자 지정 잡종 편집기 + {0}의 잡종설정 + {0}이(가) {1}와(과) 교미했을 때, {2}이(가) {3}의 확률로 태어납니다. 만약 두 종족이 서로에 대한 잡종 정의가 있을경우 아버지 쪽의 정의가 우선적으로 사용됩니다. + + \ No newline at end of file diff --git a/1.5/Languages/Spanish/Keyed/RJW_Menstruation.xml b/1.5/Languages/Spanish/Keyed/RJW_Menstruation.xml new file mode 100644 index 0000000..e428b7d --- /dev/null +++ b/1.5/Languages/Spanish/Keyed/RJW_Menstruation.xml @@ -0,0 +1,84 @@ + + + RJW Ciclo menstrual + + sangre menstrual + Vacía + Folicular + Ovulación + Luteal + En periodo + Embarazada + Recuperándose del nacimiento + Ninguna + Climaterio + Anestro + Estado + Estado + Fetos + Padre + Semen lista + Fecundada + Fertil + Ovulación + + + + habilitar icono de útero + habilitar el botón en la pestaña de salud + habilitar ciclo animal + simular el ciclo del animal. esta opción se aplicará después del cargado no recomendado + posibilidad de implantación + establecer la posibilidad de implantación del óvulo fertilizado este valor determina la posibilidad de finalización de la impregnación + oportunidad de fertilización + establecer la posibilidad de fertilización de 1 ml de esperma cada hora este valor determina la posibilidad inicial de impregnación + Relación de descomposición semen por hora + el semen disminuirá en esta proporción este valor afecta indirectamente al cambio de fertilidad + índice de descomposición de la fertilidad acumulada por hora + el semen perderá la fertilidad en esta proporción este valor afecta indirectamente a la probabilidad de fertilidad + acelerar el ciclo X + acelerar el ciclo de la menstruación + Depurar + mostrar información de depuración. + estado del útero + dibujar icono de útero en la ventana de estado + estado de la vagina + dibujar el icono de vagina y ano en la ventana de estado + Nivel de información del feto + Mostrar toda la información sobre el feto + Mostrar toda la información sobre el feto después de un embarazo notado + No muestre información sobre el feto, pero muestre la imagen del feto después de un embarazo notado + No mostrar la imagen ni la información del feto. + permitir la menopausia + Permitir el efecto de la menopausia que hace que el peón sea infértil con el paso del tiempo. Si tiene problemas con las carreras de larga duración, desactive esta opción. esta opción se aplicará después de guardar cargado + usar embarazo múltiple + use embarazo múltiple en lugar del embarazo predeterminado de RJW deshabilite esta opción si tiene problemas con la impregnación + permitir gemelos hetero ovulares + permitir que varios óvulos puedan quedar embarazadas + permitir gemelos enzimáticos + permitir que un solo huevo dé como resultado múltiples crías + posibilidad de gemelos enzimáticos + Establecer la posibilidad de gemel@s + gemelos enzimáticos max + Establecer el número máximo de gemelos + habilitar la superposición de huevos + habilitar la superposición de huevos en el icono del útero + cantidad de sangrado + cantidad total estimada de sangrado + establecer la cantidad de sangrado la cantidad de sangrado real puede ser diferente dependiendo de la vagina la cantidad de sangrado genérico de una mujer humana es de aproximadamente 20 ~ 80 ml por mes + Colonos + Prisionero + todas las Facciones + Neutral + Facción enemiga + objetivo de colonos + el artilugio y el botón aparecerán para estos peones + usar extensión híbrida + anula la definición híbrida de RJW y RaceSupport La extensión híbrida dominante determina qué definición se usa primero. No se recomienda cambiar esto + Extensión híbrida dominante + Madre + Padre + + Lavado Vaginal + + \ No newline at end of file diff --git a/1.5/Patches/Biosculpter_Patch.xml b/1.5/Patches/Biosculpter_Patch.xml new file mode 100644 index 0000000..558f4b7 --- /dev/null +++ b/1.5/Patches/Biosculpter_Patch.xml @@ -0,0 +1,24 @@ + + + + +
  • Ideology
  • +
    + + /Defs/ThingDef[defName="BiosculpterPod"]/comps + +
  • + eggRestoration + + Restore one year worth of eggs in each womb. + UI/Icon/EggRegeneration + 4 + + + (0.867, 0.373, 0.396) + 1.0 +
  • +
    +
    +
    +
    \ No newline at end of file diff --git a/1.5/Patches/CycleDisabledGenes.xml b/1.5/Patches/CycleDisabledGenes.xml new file mode 100644 index 0000000..01f8827 --- /dev/null +++ b/1.5/Patches/CycleDisabledGenes.xml @@ -0,0 +1,73 @@ + + + + + +
  • Alpha Genes
  • +
    + + /Defs/GeneDef[defName="AG_EggLaying"] + +
  • + true +
  • +
    +
    +
    + + + +
  • Vanilla Races Expanded - Saurid
  • +
    + + /Defs/GeneDef[defName="VRESaurids_Oviparous"] + +
  • + true +
  • +
    +
    +
    + + + +
  • Vanilla Races Expanded - Phytokin
  • +
    + + /Defs/GeneDef[defName="VRE_SaplingBirth"] + +
  • + true +
  • +
    +
    +
    + + + +
  • Erin's Corvyia
  • +
    + + /Defs/GeneDef[defName="ERN_EggLayer"] + +
  • + true +
  • +
    +
    +
    + + + +
  • Outland - Genetics
  • +
    + + /Defs/GeneDef[defName="Outland_EggLayer"] + +
  • + true +
  • +
    +
    +
    +
    \ No newline at end of file diff --git a/1.5/Patches/Drugs.xml b/1.5/Patches/Drugs.xml new file mode 100644 index 0000000..6f53daf --- /dev/null +++ b/1.5/Patches/Drugs.xml @@ -0,0 +1,17 @@ + + + + + /Defs/ThingDef[defName="RJW_FertPill"]/ingestible/outcomeDoers + +
  • + + + + + /Defs/ThingDef[defName="RJW_Contraceptive"]/ingestible/outcomeDoers + +
  • + + + \ No newline at end of file diff --git a/1.5/Patches/Hediffs_PrivateParts.xml b/1.5/Patches/Hediffs_PrivateParts.xml new file mode 100644 index 0000000..58bd529 --- /dev/null +++ b/1.5/Patches/Hediffs_PrivateParts.xml @@ -0,0 +1,148 @@ + + + + + + + + + + + + /Defs/rjw.HediffDef_PartBase[defName="Vagina"] + + +
  • + 10 + 1.0 + 1.0 + 14 + 14 + 6 + 30 + 1 + Womb/Womb + Genitals/Vagina + true +
  • + +
    +
    + + + + /Defs/rjw.HediffDef_PartBase[defName="GenericVagina"] + + +
  • + 10 + 1.0 + 1.0 + 14 + 14 + 0 + 30 + 3 + Womb/Womb + Genitals/Vagina +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="HydraulicVagina"] + + +
  • + 10 + Womb/Womb + Genitals/BionicVagina + true + 0 +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="BionicVagina"] + + +
  • + 10 + Womb/Womb + Genitals/BionicVagina + true + 0 +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="ArchotechVagina"] + + +
  • + 10 + 2.0 + 2.0 + 14 + 14 + 0 + 0 + 3 + Womb/Womb + Genitals/Vagina + true + 4 +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="Anus"] + + +
  • + Genitals/Anal +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="HydraulicAnus"] + + +
  • + Genitals/BionicAnal +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="BionicAnus"] + + +
  • + Genitals/BionicAnal +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="ArchotechAnus"] + + +
  • + Genitals/Anal +
  • +
    +
    +
    +
    \ No newline at end of file diff --git a/1.5/Patches/Hediffs_PrivateParts_Animal.xml b/1.5/Patches/Hediffs_PrivateParts_Animal.xml new file mode 100644 index 0000000..63b12b5 --- /dev/null +++ b/1.5/Patches/Hediffs_PrivateParts_Animal.xml @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + /Defs/rjw.HediffDef_PartBase[defName="DogVagina"] + + +
  • + 8 + 1.0 + 1.0 + 14 + 36 + 8 + 15 + 4 + Womb/Womb + Genitals/Vagina + 9 + 180~360 +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="CatVagina"] + + +
  • + 6 + 1.0 + 2.0 + 9 + 10 + 0 + 15 + 1 + Womb/Womb + Genitals/Vagina + FirstHalf + 9 +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="HorseVagina"] + + +
  • + 25 + 1.0 + 1.0 + 7 + 14 + 0 + 30 + 1 + Womb/Womb + Genitals/Vagina + FirstHalf + 5 +
  • +
    +
    +
    + + + + /Defs/rjw.HediffDef_PartBase[defName="DragonVagina"] + + +
  • + 50 + 0.5 + 0.2 + 270 + 30 + 0 + 300 + 30 + Womb/Womb + Genitals/Vagina + 0 +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="NarrowVagina"] + + +
  • + 10 + 1.0 + 1.0 + 5 + 16 + 0 + 15 + 2 + Womb/Womb + Genitals/Vagina + 1 +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="RodentVagina"] + + +
  • + 5 + 1.0 + 2.0 + 6 + 9 + 0 + 3 + 1 + Womb/Womb + Genitals/Vagina + 6 +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="SlimeVagina"] + + +
  • + 5 + 2.0 + 2.0 + 12 + 9 + 0 + 3 + 1 + Womb/Womb + Genitals/Vagina + 6 +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="DemonVagina"] + + +
  • + 10 + 2.0 + 2.0 + 14 + 14 + 0 + 3 + 1 + Womb/Womb + Genitals/Vagina + 6 +
  • +
    +
    +
    + + +
    \ No newline at end of file diff --git a/1.5/Patches/Hediffs_PrivateParts_Breasts.xml b/1.5/Patches/Hediffs_PrivateParts_Breasts.xml new file mode 100644 index 0000000..b3ef231 --- /dev/null +++ b/1.5/Patches/Hediffs_PrivateParts_Breasts.xml @@ -0,0 +1,76 @@ + + + + + + /Defs/rjw.HediffDef_PartBase[defName="Breasts"] + + +
  • + Breasts/Breast + (55,20,0) +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="HydraulicBreasts"] + + +
  • + Breasts_Artificial/Breast + (255,255,255) +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="BionicBreasts"] + + +
  • + Breasts_Artificial/Breast + (255,255,255) +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="ArchotechBreasts"] + + +
  • + Breasts/Breast + (255,255,255) +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="SlimeBreasts"] + + +
  • + Breasts/Breast + (55,20,0) +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="UdderBreasts"] + + +
  • + Breasts_Udder/Breast + (55,20,0) +
  • +
    +
    +
    +
    \ No newline at end of file diff --git a/1.5/Patches/Item_Resource_Stuffs.xml b/1.5/Patches/Item_Resource_Stuffs.xml new file mode 100644 index 0000000..2bdc062 --- /dev/null +++ b/1.5/Patches/Item_Resource_Stuffs.xml @@ -0,0 +1,38 @@ + + + + + /Defs/ThingDef[defName="Cloth"]/stuffProps/statFactors + + 1.0 + + + + + /Defs/ThingDef[defName="Synthread"]/stuffProps/statFactors + + 2.0 + + + + + /Defs/ThingDef[defName="DevilstrandCloth"]/stuffProps/statFactors + + 0.5 + + + + + /Defs/ThingDef[defName="Hyperweave"]/stuffProps/statFactors + + 0.25 + + + + + /Defs/ThingDef[@Name="WoolBase"]/stuffProps/statFactors + + 1.5 + + + \ No newline at end of file diff --git a/1.5/Patches/PawnModExtensions.xml b/1.5/Patches/PawnModExtensions.xml new file mode 100644 index 0000000..4daadde --- /dev/null +++ b/1.5/Patches/PawnModExtensions.xml @@ -0,0 +1,55 @@ + + + + + + + + /Defs/ThingDef[defName="Human"] + +
  • + Fetus/Fetus_Default + (255,255,255,255) + 0.2 + +
  • + 0.005 + Hediff_ASA + 0.01 +
  • + + + + +
    +
    +
    \ No newline at end of file diff --git a/1.5/Patches/PawnModExtensions_Animals.xml b/1.5/Patches/PawnModExtensions_Animals.xml new file mode 100644 index 0000000..19172ac --- /dev/null +++ b/1.5/Patches/PawnModExtensions_Animals.xml @@ -0,0 +1,859 @@ + + + + + + + /Defs/ThingDef[@Name="BigBirdThingBase"] + +
  • + Fetus/Birds/Fetus_Bird + (255,255,255,255) + 0.2 + + +
  • +
    +
    + + + /Defs/ThingDef[defName="Chicken"] + +
  • + Fetus/Birds/Fetus_Bird + (255,255,255,255) + 0.2 + + +
  • +
    +
    + + + /Defs/ThingDef[defName="Duck"] + +
  • + Fetus/Birds/Fetus_Bird + (255,255,255,255) + 0.2 + + +
  • +
    +
    + + + /Defs/ThingDef[defName="Goose"] + +
  • + Fetus/Birds/Fetus_Bird + (255,255,255,255) + 0.2 + + +
  • +
    +
    + + + /Defs/ThingDef[defName="Husky"] + +
  • + Fetus/Canines/Fetus_Canine + (255,255,255,255) + 0.05 + + +
  • +
    +
    + + + /Defs/ThingDef[defName="LabradorRetriever"] + +
  • + Fetus/Canines/Fetus_Canine + (255,255,255,255) + 0.05 + + +
  • +
    +
    + + + /Defs/ThingDef[defName="YorkshireTerrier"] + +
  • + Fetus/Canines/Fetus_Canine + (255,255,255,255) + 0.05 + + +
  • +
    +
    + + + + /Defs/ThingDef[defName="Warg"] + +
  • + Fetus/Canines/Fetus_Canine + (255,255,255,255) + 0.05 + + +
  • +
    +
    + + + /Defs/ThingDef[@Name="ThingBaseWolf"] + +
  • + Fetus/Canines/Fetus_Canine + (255,255,255,255) + 0.05 + + +
  • +
    +
    + + + /Defs/ThingDef[@Name="ThingBaseFox"] + +
  • + Fetus/Canines/Fetus_CanineV + (255,255,255,255) + 0.05 + + +
  • +
    +
    + + + /Defs/ThingDef[defName="Pig"] + +
  • + Fetus/Pigs/Fetus_Pig + (255,255,255,255) + 0.8 + + +
  • +
    +
    + + + /Defs/ThingDef[defName="WildBoar"] + +
  • + Fetus/Pigs/Fetus_Pig + (255,255,255,255) + 0.8 + + +
  • +
    +
    + + + /Defs/ThingDef[@Name="BaseInsect"] + +
  • + Fetus/Insects/Fetus_Insect + (153,212,89,255) + 0.5 + + +
  • +
    +
    + + + Defs/ThingDef[defName="Turkey"] + +
  • + Fetus/Birds/Fetus_Bird + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Sheep"] + +
  • + Fetus/Bovines/Fetus_Bovine + (255,255,255,255) + 0.3 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Goat"] + +
  • + Fetus/Bovines/Fetus_Bovine + (255,255,255,255) + 0.3 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Ibex"] + +
  • + Fetus/Cervines/Fetus_Cervine + (255,255,255,255) + 0.3 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Deer"] + +
  • + Fetus/Cervines/Fetus_Cervine + (255,255,255,255) + 0.3 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Gazelle"] + +
  • + Fetus/Cervines/Fetus_Cervine + (255,255,255,255) + 0.3 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Alpaca"] + +
  • + Fetus/Bovines/Fetus_Bovine + (255,255,255,255) + 0.3 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Yak"] + +
  • + Fetus/Bovines/Fetus_Bovine + (255,255,255,255) + 0.3 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Elk"] + +
  • + Fetus/Cervines/Fetus_Cervine + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Caribou"] + +
  • + Fetus/Cervines/Fetus_Cervine + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Horse"] + +
  • + Fetus/Bovines/Fetus_Bovine + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Donkey"] + +
  • + Fetus/Bovines/Fetus_Bovine + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Cow"] + +
  • + Fetus/Bovines/Fetus_Bovine + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Boomalope"] + +
  • + Fetus/Boomies/Fetus_Boomalope + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Muffalo"] + +
  • + Fetus/Muffalos/Fetus_Muffalo + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Bison"] + +
  • + Fetus/Bovines/Fetus_Bovine + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Dromedary"] + +
  • + Fetus/Bovines/Fetus_Bovine + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Elephant"] + +
  • + Fetus/Elephants/Fetus_Elephant + (255,255,255,255) + 0.5 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Rhinoceros"] + +
  • + Fetus/Rhinoceroses/Fetus_Rhinoceros + (255,255,255,255) + 0.5 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Cat"] + +
  • + Fetus/Felines/Fetus_Feline_D + (255,255,255,255) + 0.1 + + + + +
  • +
    +
    + + + Defs/ThingDef[@Name="BigCatThingBase"] + +
  • + Fetus/Felines/Fetus_Feline_W + (255,255,255,255) + 0.2 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Cougar"] + +
  • + Fetus/Felines/Fetus_Feline_W + (255,255,255,255) + 0.2 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Panther"] + +
  • + Fetus/Felines/Fetus_Feline_D + (255,255,255,255) + 0.2 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Iguana"] + +
  • + Fetus/Reptiles/Fetus_Reptile + (255,255,255,255) + 0.5 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Tortoise"] + +
  • + Fetus/Reptiles/Fetus_Reptile + (255,255,255,255) + 0.5 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Cobra"] + +
  • + Fetus/Snakes/Fetus_Snake + (255,255,255,255) + 0.5 + + + + +
  • +
    +
    + + + Defs/ThingDef[@Name="BaseHare"] + +
  • + Fetus/Lagomorphs/Fetus_Lagomorph + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Rat"] + +
  • + Fetus/Rodents/Fetus_Rodent + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Boomrat"] + +
  • + Fetus/Boomies/Fetus_Boomrat + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="GuineaPig"] + +
  • + Fetus/Rodents/Fetus_Rodent + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Chinchilla"] + +
  • + Fetus/Rodents/Fetus_Rodent + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Snowhare"] + +
  • + Fetus/Lagomorphs/Fetus_Lagomorph + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Capybara"] + +
  • + Fetus/Rodents/Fetus_Rodent + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Raccoon"] + +
  • + Fetus/Rodents/Fetus_Rodent + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Alphabeaver"] + +
  • + Fetus/Rodents/Fetus_Rodent + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Squirrel"] + +
  • + Fetus/Rodents/Fetus_Rodent + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Monkey"] + +
  • + Fetus/Primate/Fetus_Primate + (255,255,255,255) + 0.2 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Megasloth"] + +
  • + Fetus/Megasloths/Fetus_Megasloth + (255,255,255,255) + 0.9 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Thrumbo"] + +
  • + Fetus/Thrumbos/Fetus_Thrumbo + (255,255,255,255) + 0.7 + + + + +
  • +
    +
    + + + Defs/ThingDef[@Name="BaseMechanoid"] + +
  • + Fetus/Mechanoids/Fetus_Mechanoid + (255,255,255,255) + 0.9 + + + + +
  • +
    +
    + + + Defs/ThingDef[@Name="BaseMechanoidWalker"] + +
  • + Fetus/Mechanoids/Fetus_Mechanoid + (255,255,255,255) + 0.9 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Cassowary"] + +
  • + Fetus/Birds/Fetus_Bird + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + Defs/ThingDef[defName="Emu"] + +
  • + Fetus/Birds/Fetus_Bird + (255,255,255,255) + 0.4 + + + + +
  • +
    +
    + + + /Defs/ThingDef[@Name="BaseBear"] + +
  • + Fetus/Ursids/Fetus_Ursid + (255,255,255,255) + 0.05 + + + + +
  • +
    +
    + +
    \ No newline at end of file diff --git a/1.5/Patches/Pregenerated_Babies.xml b/1.5/Patches/Pregenerated_Babies.xml new file mode 100644 index 0000000..07d05b3 --- /dev/null +++ b/1.5/Patches/Pregenerated_Babies.xml @@ -0,0 +1,16 @@ + + + + +
  • Biotech
  • +
    + + /Defs/HediffDef[defName="PregnantHuman" or defName="PregnancyLabor" or defName="PregnancyLaborPushing"]/comps + +
  • + RJW_Menstruation.HediffComp_PregeneratedBabies +
  • +
    +
    +
    +
    \ No newline at end of file diff --git a/1.5/Patches/RJW_StatDefs.xml b/1.5/Patches/RJW_StatDefs.xml new file mode 100644 index 0000000..f83365a --- /dev/null +++ b/1.5/Patches/RJW_StatDefs.xml @@ -0,0 +1,19 @@ + + + + + /Defs/StatDef[defName="SexFrequency"]/parts + +
  • +
  • + + + + + /Defs/StatDef[defName="SexSatisfaction"]/parts + +
  • +
  • + + + \ No newline at end of file diff --git a/1.5/RJW Menstruation Race Support/About/About.xml b/1.5/RJW Menstruation Race Support/About/About.xml new file mode 100644 index 0000000..b3aa6ce --- /dev/null +++ b/1.5/RJW Menstruation Race Support/About/About.xml @@ -0,0 +1,26 @@ + + + RJW Menstruation Cycle Race Support + a + +
  • 1.2
  • + + +
  • + rjw.menstruation + RJW Menstruation + https://github.com/moreoreganostodump/RJW_Menstruation +
  • +
  • + Abraxas.RJW.RaceSupport + RJW - RaceSupport + https://gitgud.io/Abraxas/rjw-race-support +
  • +
    + +
  • Abraxas.RJW.RaceSupport
  • +
  • rjw.menstruation
  • +
    + rjw.menstruation.racesupport + good good + \ No newline at end of file diff --git a/1.5/RJW Menstruation Race Support/About/Manifest.xml b/1.5/RJW Menstruation Race Support/About/Manifest.xml new file mode 100644 index 0000000..1904137 --- /dev/null +++ b/1.5/RJW Menstruation Race Support/About/Manifest.xml @@ -0,0 +1,12 @@ + + + RJW Menstruation Race Support + 8.9.0 + + + + + + + + \ No newline at end of file diff --git a/1.5/RJW Menstruation Race Support/Patches/Hediffs_PrivateParts_Animal_RaceSupport.xml b/1.5/RJW Menstruation Race Support/Patches/Hediffs_PrivateParts_Animal_RaceSupport.xml new file mode 100644 index 0000000..e63d625 --- /dev/null +++ b/1.5/RJW Menstruation Race Support/Patches/Hediffs_PrivateParts_Animal_RaceSupport.xml @@ -0,0 +1,217 @@ + + + + + + + + + + + + + + + + /Defs/rjw.HediffDef_PartBase[defName="BovineVagina"] + + +
  • + 10 + 1.0 + 1.0 + 4 + 17 + 0 + 90 + 2 + Womb/Womb + Genitals/Vagina +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="CactoidVagina"] + + +
  • + 8 + 1.0 + 1.0 + 8 + 12 + 0 + 0 + 2 + Womb/Womb + Genitals/Vagina + Summer +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="ElephantVagina"] + + +
  • + 18 + 1.0 + 1.0 + 35 + 63 + 0 + 30 + 3 + Womb/Womb + Genitals/Vagina +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="HyenaVagina"] + + +
  • + 18 + 1.0 + 1.0 + 7 + 7 + 0 + 30 + 1 + Womb/Womb + Genitals/Vagina + true +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="MammalVagina"] + + +
  • + 10 + 1.0 + 1.0 + 14 + 14 + 0 + 30 + 3 + Womb/Womb + Genitals/Vagina +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="MarineVagina"] + + +
  • + 10 + 1.0 + 1.0 + 10 + 20 + 0 + 30 + 2 + Womb/Womb + Genitals/Vagina +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="PigVagina"] + + +
  • + 18 + 1.0 + 1.0 + 6 + 14 + 0 + 24 + 2 + Womb/Womb + Genitals/Vagina +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="PistilVagina"] + + +
  • + 8 + 1.0 + 1.0 + 6 + 12 + 0 + 30 + 2 + Womb/Womb + Genitals/Vagina + Fall +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="GhostVagina"] + + +
  • + 2 + 0.1 + 0.1 + 14 + 14 + 0 + 0 + 1 + Womb/Womb + Genitals/Vagina + true +
  • +
    +
    +
    +
    \ No newline at end of file diff --git a/1.5/RJW Menstruation Race Support/Patches/Hediffs_PrivateParts_Breasts_RaceSupport.xml b/1.5/RJW Menstruation Race Support/Patches/Hediffs_PrivateParts_Breasts_RaceSupport.xml new file mode 100644 index 0000000..b5f0a5e --- /dev/null +++ b/1.5/RJW Menstruation Race Support/Patches/Hediffs_PrivateParts_Breasts_RaceSupport.xml @@ -0,0 +1,107 @@ + + + + + + + /Defs/rjw.HediffDef_PartBase[defName="MammalBreasts"] + + +
  • + Breasts/Breast + (55,20,0) +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="CatBreasts"] + + +
  • + Breasts/Breast + (55,20,0) +
  • +
    +
    +
    + + /Defs/rjw.HediffDef_PartBase[defName="GhostBreasts"] + + +
  • + Breasts/Breast + (55,20,0) +
  • +
    +
    +
    + + /Defs/rjw.HediffDef_PartBase[defName="CactoidBreasts"] + + +
  • + Breasts/Breast + (55,20,0) +
  • +
    +
    +
    + + /Defs/rjw.HediffDef_PartBase[defName="GhoulBreasts"] + + +
  • + Breasts/Breast + (55,20,0) +
  • +
    +
    +
    + + /Defs/rjw.HediffDef_PartBase[defName="NecroBreasts"] + + +
  • + Breasts/Breast + (55,20,0) +
  • +
    +
    +
    + + /Defs/rjw.HediffDef_PartBase[defName="OrcBreasts"] + + +
  • + Breasts/Breast + (55,20,0) +
  • +
    +
    +
    + + /Defs/rjw.HediffDef_PartBase[defName="ScaleBreasts"] + + +
  • + Breasts/Breast + (55,20,0) +
  • +
    +
    +
    + + /Defs/rjw.HediffDef_PartBase[defName="TreeBreasts"] + + +
  • + Breasts/Breast + (55,20,0) +
  • +
    +
    +
    + +
    \ No newline at end of file diff --git a/1.5/RJW Menstruation Race Support/Patches/Hediffs_PrivateParts_Humanlike_RaceSupport.xml b/1.5/RJW Menstruation Race Support/Patches/Hediffs_PrivateParts_Humanlike_RaceSupport.xml new file mode 100644 index 0000000..8f83940 --- /dev/null +++ b/1.5/RJW Menstruation Race Support/Patches/Hediffs_PrivateParts_Humanlike_RaceSupport.xml @@ -0,0 +1,150 @@ + + + + + + + + + + + + /Defs/rjw.HediffDef_PartBase[defName="ElfVagina"] + + +
  • + 10 + 1.0 + 1.0 + 1800 + 1800 + 6 + 30 + 1 + Womb/Womb + Genitals/Vagina + true +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="ElfAnus"] + + +
  • + Genitals/Anal +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="OrcVagina"] + + +
  • + 10 + 1.0 + 1.0 + 7 + 10 + 0 + 10 + 1 + Womb/Womb + Genitals/Vagina + true +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="OrcAnus"] + + +
  • + Genitals/Anal +
  • +
    +
    +
    + + + + + /Defs/rjw.HediffDef_PartBase[defName="GhoulVagina"] + + +
  • + 10 + 0.2 + 0.2 + 14 + 14 + 0 + 10 + 1 + Womb/Womb + Genitals/Vagina + true +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="GhoulAnus"] + + +
  • + Genitals/Anal +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="NecroVagina"] + + +
  • + 10 + 0.1 + 0.1 + 14 + 14 + 0 + 0 + 1 + Womb/Womb + Genitals/Vagina + true +
  • +
    +
    +
    + + + /Defs/rjw.HediffDef_PartBase[defName="TreeVagina"] + + +
  • + 15 + 1.0 + 1.0 + 10 + 12 + 0 + 30 + 2 + Womb/Womb + Genitals/Vagina + Fall +
  • +
    +
    +
    +
    \ No newline at end of file diff --git a/1.5/Textures/Breasts/Breast_Breast00.png b/1.5/Textures/Breasts/Breast_Breast00.png new file mode 100644 index 0000000..ee9235e Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast00.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast00_Areola00.png b/1.5/Textures/Breasts/Breast_Breast00_Areola00.png new file mode 100644 index 0000000..886d752 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast00_Areola00.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast00_Areola01.png b/1.5/Textures/Breasts/Breast_Breast00_Areola01.png new file mode 100644 index 0000000..128b260 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast00_Areola01.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast00_Areola02.png b/1.5/Textures/Breasts/Breast_Breast00_Areola02.png new file mode 100644 index 0000000..925b105 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast00_Areola02.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast00_Areola03.png b/1.5/Textures/Breasts/Breast_Breast00_Areola03.png new file mode 100644 index 0000000..c4030d9 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast00_Areola03.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast00_Areola04.png b/1.5/Textures/Breasts/Breast_Breast00_Areola04.png new file mode 100644 index 0000000..c4030d9 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast00_Areola04.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast00_Nipple00.png b/1.5/Textures/Breasts/Breast_Breast00_Nipple00.png new file mode 100644 index 0000000..180bfab Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast00_Nipple00.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast00_Nipple01.png b/1.5/Textures/Breasts/Breast_Breast00_Nipple01.png new file mode 100644 index 0000000..d52d303 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast00_Nipple01.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast00_Nipple02.png b/1.5/Textures/Breasts/Breast_Breast00_Nipple02.png new file mode 100644 index 0000000..a317c52 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast00_Nipple02.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast00_Nipple03.png b/1.5/Textures/Breasts/Breast_Breast00_Nipple03.png new file mode 100644 index 0000000..dbbfb78 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast00_Nipple03.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast01.png b/1.5/Textures/Breasts/Breast_Breast01.png new file mode 100644 index 0000000..2e4f27f Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast01.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast01_Areola00.png b/1.5/Textures/Breasts/Breast_Breast01_Areola00.png new file mode 100644 index 0000000..e9e4958 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast01_Areola00.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast01_Areola01.png b/1.5/Textures/Breasts/Breast_Breast01_Areola01.png new file mode 100644 index 0000000..a42aff7 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast01_Areola01.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast01_Areola02.png b/1.5/Textures/Breasts/Breast_Breast01_Areola02.png new file mode 100644 index 0000000..e5b9cf0 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast01_Areola02.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast01_Areola03.png b/1.5/Textures/Breasts/Breast_Breast01_Areola03.png new file mode 100644 index 0000000..d40a30c Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast01_Areola03.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast01_Areola04.png b/1.5/Textures/Breasts/Breast_Breast01_Areola04.png new file mode 100644 index 0000000..d40a30c Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast01_Areola04.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast01_Nipple00.png b/1.5/Textures/Breasts/Breast_Breast01_Nipple00.png new file mode 100644 index 0000000..c970cd6 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast01_Nipple00.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast01_Nipple01.png b/1.5/Textures/Breasts/Breast_Breast01_Nipple01.png new file mode 100644 index 0000000..0b2fc35 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast01_Nipple01.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast01_Nipple02.png b/1.5/Textures/Breasts/Breast_Breast01_Nipple02.png new file mode 100644 index 0000000..a8966bf Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast01_Nipple02.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast01_Nipple03.png b/1.5/Textures/Breasts/Breast_Breast01_Nipple03.png new file mode 100644 index 0000000..ce7523d Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast01_Nipple03.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast02.png b/1.5/Textures/Breasts/Breast_Breast02.png new file mode 100644 index 0000000..26883a9 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast02.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast02_Areola00.png b/1.5/Textures/Breasts/Breast_Breast02_Areola00.png new file mode 100644 index 0000000..93e1843 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast02_Areola00.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast02_Areola01.png b/1.5/Textures/Breasts/Breast_Breast02_Areola01.png new file mode 100644 index 0000000..0c17fad Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast02_Areola01.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast02_Areola02.png b/1.5/Textures/Breasts/Breast_Breast02_Areola02.png new file mode 100644 index 0000000..3a154ef Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast02_Areola02.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast02_Areola03.png b/1.5/Textures/Breasts/Breast_Breast02_Areola03.png new file mode 100644 index 0000000..7c70961 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast02_Areola03.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast02_Areola04.png b/1.5/Textures/Breasts/Breast_Breast02_Areola04.png new file mode 100644 index 0000000..7c70961 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast02_Areola04.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast02_Nipple00.png b/1.5/Textures/Breasts/Breast_Breast02_Nipple00.png new file mode 100644 index 0000000..4798891 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast02_Nipple00.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast02_Nipple01.png b/1.5/Textures/Breasts/Breast_Breast02_Nipple01.png new file mode 100644 index 0000000..d865a8b Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast02_Nipple01.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast02_Nipple02.png b/1.5/Textures/Breasts/Breast_Breast02_Nipple02.png new file mode 100644 index 0000000..4e96c84 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast02_Nipple02.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast02_Nipple03.png b/1.5/Textures/Breasts/Breast_Breast02_Nipple03.png new file mode 100644 index 0000000..591e6ea Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast02_Nipple03.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast03.png b/1.5/Textures/Breasts/Breast_Breast03.png new file mode 100644 index 0000000..141ee81 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast03.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast03_Areola00.png b/1.5/Textures/Breasts/Breast_Breast03_Areola00.png new file mode 100644 index 0000000..884558e Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast03_Areola00.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast03_Areola01.png b/1.5/Textures/Breasts/Breast_Breast03_Areola01.png new file mode 100644 index 0000000..376d40e Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast03_Areola01.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast03_Areola02.png b/1.5/Textures/Breasts/Breast_Breast03_Areola02.png new file mode 100644 index 0000000..833219a Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast03_Areola02.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast03_Areola03.png b/1.5/Textures/Breasts/Breast_Breast03_Areola03.png new file mode 100644 index 0000000..d272a38 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast03_Areola03.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast03_Areola04.png b/1.5/Textures/Breasts/Breast_Breast03_Areola04.png new file mode 100644 index 0000000..ef80b45 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast03_Areola04.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast03_Nipple00.png b/1.5/Textures/Breasts/Breast_Breast03_Nipple00.png new file mode 100644 index 0000000..77b2a31 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast03_Nipple00.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast03_Nipple01.png b/1.5/Textures/Breasts/Breast_Breast03_Nipple01.png new file mode 100644 index 0000000..1f6a50c Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast03_Nipple01.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast03_Nipple02.png b/1.5/Textures/Breasts/Breast_Breast03_Nipple02.png new file mode 100644 index 0000000..91b5ff9 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast03_Nipple02.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast03_Nipple03.png b/1.5/Textures/Breasts/Breast_Breast03_Nipple03.png new file mode 100644 index 0000000..0663d61 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast03_Nipple03.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast04.png b/1.5/Textures/Breasts/Breast_Breast04.png new file mode 100644 index 0000000..49e3fdd Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast04.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast04_Areola00.png b/1.5/Textures/Breasts/Breast_Breast04_Areola00.png new file mode 100644 index 0000000..f829fe3 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast04_Areola00.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast04_Areola01.png b/1.5/Textures/Breasts/Breast_Breast04_Areola01.png new file mode 100644 index 0000000..41015e1 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast04_Areola01.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast04_Areola02.png b/1.5/Textures/Breasts/Breast_Breast04_Areola02.png new file mode 100644 index 0000000..43807cd Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast04_Areola02.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast04_Areola03.png b/1.5/Textures/Breasts/Breast_Breast04_Areola03.png new file mode 100644 index 0000000..fececfc Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast04_Areola03.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast04_Areola04.png b/1.5/Textures/Breasts/Breast_Breast04_Areola04.png new file mode 100644 index 0000000..aee0036 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast04_Areola04.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast04_Nipple00.png b/1.5/Textures/Breasts/Breast_Breast04_Nipple00.png new file mode 100644 index 0000000..64dd9ab Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast04_Nipple00.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast04_Nipple01.png b/1.5/Textures/Breasts/Breast_Breast04_Nipple01.png new file mode 100644 index 0000000..767399f Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast04_Nipple01.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast04_Nipple02.png b/1.5/Textures/Breasts/Breast_Breast04_Nipple02.png new file mode 100644 index 0000000..ea44548 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast04_Nipple02.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast04_Nipple03.png b/1.5/Textures/Breasts/Breast_Breast04_Nipple03.png new file mode 100644 index 0000000..2638747 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast04_Nipple03.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast05.png b/1.5/Textures/Breasts/Breast_Breast05.png new file mode 100644 index 0000000..21c932f Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast05.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast05_Areola00.png b/1.5/Textures/Breasts/Breast_Breast05_Areola00.png new file mode 100644 index 0000000..4ed1442 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast05_Areola00.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast05_Areola01.png b/1.5/Textures/Breasts/Breast_Breast05_Areola01.png new file mode 100644 index 0000000..888f2f0 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast05_Areola01.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast05_Areola02.png b/1.5/Textures/Breasts/Breast_Breast05_Areola02.png new file mode 100644 index 0000000..ca0182d Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast05_Areola02.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast05_Areola03.png b/1.5/Textures/Breasts/Breast_Breast05_Areola03.png new file mode 100644 index 0000000..aa7384d Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast05_Areola03.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast05_Areola04.png b/1.5/Textures/Breasts/Breast_Breast05_Areola04.png new file mode 100644 index 0000000..052d759 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast05_Areola04.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast05_Nipple00.png b/1.5/Textures/Breasts/Breast_Breast05_Nipple00.png new file mode 100644 index 0000000..62ff534 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast05_Nipple00.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast05_Nipple01.png b/1.5/Textures/Breasts/Breast_Breast05_Nipple01.png new file mode 100644 index 0000000..359195a Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast05_Nipple01.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast05_Nipple02.png b/1.5/Textures/Breasts/Breast_Breast05_Nipple02.png new file mode 100644 index 0000000..620b81f Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast05_Nipple02.png differ diff --git a/1.5/Textures/Breasts/Breast_Breast05_Nipple03.png b/1.5/Textures/Breasts/Breast_Breast05_Nipple03.png new file mode 100644 index 0000000..9720601 Binary files /dev/null and b/1.5/Textures/Breasts/Breast_Breast05_Nipple03.png differ diff --git a/1.5/Textures/Breasts/average_nip_2.png b/1.5/Textures/Breasts/average_nip_2.png new file mode 100644 index 0000000..5ae33c6 Binary files /dev/null and b/1.5/Textures/Breasts/average_nip_2.png differ diff --git a/1.5/Textures/Breasts/average_nip_preg.png b/1.5/Textures/Breasts/average_nip_preg.png new file mode 100644 index 0000000..ad126e1 Binary files /dev/null and b/1.5/Textures/Breasts/average_nip_preg.png differ diff --git a/1.5/Textures/Breasts/enormous_nip_gray.png b/1.5/Textures/Breasts/enormous_nip_gray.png new file mode 100644 index 0000000..74ea39f Binary files /dev/null and b/1.5/Textures/Breasts/enormous_nip_gray.png differ diff --git a/1.5/Textures/Breasts/enormous_nip_pink.png b/1.5/Textures/Breasts/enormous_nip_pink.png new file mode 100644 index 0000000..eab90a6 Binary files /dev/null and b/1.5/Textures/Breasts/enormous_nip_pink.png differ diff --git a/1.5/Textures/Breasts/enormous_nip_preg.png b/1.5/Textures/Breasts/enormous_nip_preg.png new file mode 100644 index 0000000..ba664fc Binary files /dev/null and b/1.5/Textures/Breasts/enormous_nip_preg.png differ diff --git a/1.5/Textures/Breasts/enoromous_nip.png b/1.5/Textures/Breasts/enoromous_nip.png new file mode 100644 index 0000000..e199f9a Binary files /dev/null and b/1.5/Textures/Breasts/enoromous_nip.png differ diff --git a/1.5/Textures/Breasts/huge_nip_preg.png b/1.5/Textures/Breasts/huge_nip_preg.png new file mode 100644 index 0000000..c4091f3 Binary files /dev/null and b/1.5/Textures/Breasts/huge_nip_preg.png differ diff --git a/1.5/Textures/Breasts/large_nip_2.png b/1.5/Textures/Breasts/large_nip_2.png new file mode 100644 index 0000000..3a06e22 Binary files /dev/null and b/1.5/Textures/Breasts/large_nip_2.png differ diff --git a/1.5/Textures/Breasts/large_nip_preg.png b/1.5/Textures/Breasts/large_nip_preg.png new file mode 100644 index 0000000..78d7200 Binary files /dev/null and b/1.5/Textures/Breasts/large_nip_preg.png differ diff --git a/1.5/Textures/Breasts/small_nip_2.png b/1.5/Textures/Breasts/small_nip_2.png new file mode 100644 index 0000000..8729d10 Binary files /dev/null and b/1.5/Textures/Breasts/small_nip_2.png differ diff --git a/1.5/Textures/Breasts/small_nip_preg.png b/1.5/Textures/Breasts/small_nip_preg.png new file mode 100644 index 0000000..0f3d5e3 Binary files /dev/null and b/1.5/Textures/Breasts/small_nip_preg.png differ diff --git a/1.5/Textures/Breasts/tiny_nip.png b/1.5/Textures/Breasts/tiny_nip.png new file mode 100644 index 0000000..bd9d889 Binary files /dev/null and b/1.5/Textures/Breasts/tiny_nip.png differ diff --git a/1.5/Textures/Breasts/tiny_nip_2.png b/1.5/Textures/Breasts/tiny_nip_2.png new file mode 100644 index 0000000..8c43665 Binary files /dev/null and b/1.5/Textures/Breasts/tiny_nip_2.png differ diff --git a/1.5/Textures/Breasts/tiny_nip_preg.png b/1.5/Textures/Breasts/tiny_nip_preg.png new file mode 100644 index 0000000..c5a31be Binary files /dev/null and b/1.5/Textures/Breasts/tiny_nip_preg.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast00.png b/1.5/Textures/Breasts_Artificial/Breast_Breast00.png new file mode 100644 index 0000000..ee9235e Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast00.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola00.png b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola00.png new file mode 100644 index 0000000..acb5453 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola00.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola01.png b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola01.png new file mode 100644 index 0000000..1ae974f Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola01.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola02.png b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola02.png new file mode 100644 index 0000000..35baf43 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola02.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola03.png b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola03.png new file mode 100644 index 0000000..870ba5b Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola03.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola04.png b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola04.png new file mode 100644 index 0000000..870ba5b Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Areola04.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast00_Nipple00.png b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Nipple00.png new file mode 100644 index 0000000..0eeaef9 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Nipple00.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast00_Nipple01.png b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Nipple01.png new file mode 100644 index 0000000..edf140f Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Nipple01.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast00_Nipple02.png b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Nipple02.png new file mode 100644 index 0000000..c686b77 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Nipple02.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast00_Nipple03.png b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Nipple03.png new file mode 100644 index 0000000..c362ffb Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast00_Nipple03.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast01.png b/1.5/Textures/Breasts_Artificial/Breast_Breast01.png new file mode 100644 index 0000000..2e4f27f Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast01.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola00.png b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola00.png new file mode 100644 index 0000000..a41b708 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola00.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola01.png b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola01.png new file mode 100644 index 0000000..7241cde Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola01.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola02.png b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola02.png new file mode 100644 index 0000000..3a8b32c Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola02.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola03.png b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola03.png new file mode 100644 index 0000000..51d837d Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola03.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola04.png b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola04.png new file mode 100644 index 0000000..51d837d Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Areola04.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast01_Nipple00.png b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Nipple00.png new file mode 100644 index 0000000..925fa07 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Nipple00.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast01_Nipple01.png b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Nipple01.png new file mode 100644 index 0000000..5c16fdc Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Nipple01.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast01_Nipple02.png b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Nipple02.png new file mode 100644 index 0000000..32f1b03 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Nipple02.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast01_Nipple03.png b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Nipple03.png new file mode 100644 index 0000000..2c6b39b Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast01_Nipple03.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast02.png b/1.5/Textures/Breasts_Artificial/Breast_Breast02.png new file mode 100644 index 0000000..26883a9 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast02.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola00.png b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola00.png new file mode 100644 index 0000000..77ee749 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola00.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola01.png b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola01.png new file mode 100644 index 0000000..cb4f23e Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola01.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola02.png b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola02.png new file mode 100644 index 0000000..269a022 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola02.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola03.png b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola03.png new file mode 100644 index 0000000..fee88bb Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola03.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola04.png b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola04.png new file mode 100644 index 0000000..fee88bb Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Areola04.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast02_Nipple00.png b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Nipple00.png new file mode 100644 index 0000000..dda7f7f Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Nipple00.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast02_Nipple01.png b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Nipple01.png new file mode 100644 index 0000000..356da01 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Nipple01.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast02_Nipple02.png b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Nipple02.png new file mode 100644 index 0000000..e996dc2 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Nipple02.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast02_Nipple03.png b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Nipple03.png new file mode 100644 index 0000000..84ec360 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast02_Nipple03.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast03.png b/1.5/Textures/Breasts_Artificial/Breast_Breast03.png new file mode 100644 index 0000000..141ee81 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast03.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola00.png b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola00.png new file mode 100644 index 0000000..56ae6af Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola00.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola01.png b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola01.png new file mode 100644 index 0000000..4af61d3 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola01.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola02.png b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola02.png new file mode 100644 index 0000000..53c3fa8 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola02.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola03.png b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola03.png new file mode 100644 index 0000000..a949a84 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola03.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola04.png b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola04.png new file mode 100644 index 0000000..0b04d4e Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Areola04.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast03_Nipple00.png b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Nipple00.png new file mode 100644 index 0000000..fad8835 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Nipple00.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast03_Nipple01.png b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Nipple01.png new file mode 100644 index 0000000..c96fd06 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Nipple01.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast03_Nipple02.png b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Nipple02.png new file mode 100644 index 0000000..0382854 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Nipple02.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast03_Nipple03.png b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Nipple03.png new file mode 100644 index 0000000..864a699 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast03_Nipple03.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast04.png b/1.5/Textures/Breasts_Artificial/Breast_Breast04.png new file mode 100644 index 0000000..49e3fdd Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast04.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola00.png b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola00.png new file mode 100644 index 0000000..d0b67f7 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola00.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola01.png b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola01.png new file mode 100644 index 0000000..e1c73f9 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola01.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola02.png b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola02.png new file mode 100644 index 0000000..f768581 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola02.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola03.png b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola03.png new file mode 100644 index 0000000..23fac43 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola03.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola04.png b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola04.png new file mode 100644 index 0000000..53d5b32 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Areola04.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast04_Nipple00.png b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Nipple00.png new file mode 100644 index 0000000..1f24792 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Nipple00.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast04_Nipple01.png b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Nipple01.png new file mode 100644 index 0000000..a2d84df Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Nipple01.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast04_Nipple02.png b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Nipple02.png new file mode 100644 index 0000000..a85b31d Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Nipple02.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast04_Nipple03.png b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Nipple03.png new file mode 100644 index 0000000..1bc64ef Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast04_Nipple03.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast05.png b/1.5/Textures/Breasts_Artificial/Breast_Breast05.png new file mode 100644 index 0000000..21c932f Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast05.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola00.png b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola00.png new file mode 100644 index 0000000..5c5d7cd Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola00.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola01.png b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola01.png new file mode 100644 index 0000000..5d2a33f Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola01.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola02.png b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola02.png new file mode 100644 index 0000000..aaef70d Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola02.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola03.png b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola03.png new file mode 100644 index 0000000..c323c27 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola03.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola04.png b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola04.png new file mode 100644 index 0000000..fc51719 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Areola04.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast05_Nipple00.png b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Nipple00.png new file mode 100644 index 0000000..1980de9 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Nipple00.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast05_Nipple01.png b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Nipple01.png new file mode 100644 index 0000000..605ff53 Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Nipple01.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast05_Nipple02.png b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Nipple02.png new file mode 100644 index 0000000..5a55d4b Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Nipple02.png differ diff --git a/1.5/Textures/Breasts_Artificial/Breast_Breast05_Nipple03.png b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Nipple03.png new file mode 100644 index 0000000..e763dfa Binary files /dev/null and b/1.5/Textures/Breasts_Artificial/Breast_Breast05_Nipple03.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast00.png b/1.5/Textures/Breasts_Udder/Breast_Breast00.png new file mode 100644 index 0000000..ee9235e Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast00.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola00.png b/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola00.png new file mode 100644 index 0000000..210f4a8 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola00.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola01.png b/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola01.png new file mode 100644 index 0000000..096a002 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola01.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola02.png b/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola02.png new file mode 100644 index 0000000..bfe8297 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola02.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola03.png b/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola03.png new file mode 100644 index 0000000..1634915 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola03.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola04.png b/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola04.png new file mode 100644 index 0000000..1634915 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast00_Areola04.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast00_Nipple00.png b/1.5/Textures/Breasts_Udder/Breast_Breast00_Nipple00.png new file mode 100644 index 0000000..3ab60e2 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast00_Nipple00.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast00_Nipple01.png b/1.5/Textures/Breasts_Udder/Breast_Breast00_Nipple01.png new file mode 100644 index 0000000..40df850 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast00_Nipple01.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast00_Nipple02.png b/1.5/Textures/Breasts_Udder/Breast_Breast00_Nipple02.png new file mode 100644 index 0000000..0f0b928 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast00_Nipple02.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast00_Nipple03.png b/1.5/Textures/Breasts_Udder/Breast_Breast00_Nipple03.png new file mode 100644 index 0000000..7c72603 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast00_Nipple03.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast01.png b/1.5/Textures/Breasts_Udder/Breast_Breast01.png new file mode 100644 index 0000000..2e4f27f Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast01.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola00.png b/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola00.png new file mode 100644 index 0000000..e72a4a3 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola00.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola01.png b/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola01.png new file mode 100644 index 0000000..7055e66 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola01.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola02.png b/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola02.png new file mode 100644 index 0000000..6504f43 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola02.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola03.png b/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola03.png new file mode 100644 index 0000000..5ebbca8 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola03.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola04.png b/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola04.png new file mode 100644 index 0000000..5ebbca8 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast01_Areola04.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast01_Nipple00.png b/1.5/Textures/Breasts_Udder/Breast_Breast01_Nipple00.png new file mode 100644 index 0000000..5586e76 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast01_Nipple00.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast01_Nipple01.png b/1.5/Textures/Breasts_Udder/Breast_Breast01_Nipple01.png new file mode 100644 index 0000000..e5680b6 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast01_Nipple01.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast01_Nipple02.png b/1.5/Textures/Breasts_Udder/Breast_Breast01_Nipple02.png new file mode 100644 index 0000000..d721b2a Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast01_Nipple02.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast01_Nipple03.png b/1.5/Textures/Breasts_Udder/Breast_Breast01_Nipple03.png new file mode 100644 index 0000000..0103315 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast01_Nipple03.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast02.png b/1.5/Textures/Breasts_Udder/Breast_Breast02.png new file mode 100644 index 0000000..25fd7ab Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast02.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola00.png b/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola00.png new file mode 100644 index 0000000..8747424 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola00.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola01.png b/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola01.png new file mode 100644 index 0000000..7f8345e Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola01.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola02.png b/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola02.png new file mode 100644 index 0000000..c6d56b8 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola02.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola03.png b/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola03.png new file mode 100644 index 0000000..59b8885 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola03.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola04.png b/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola04.png new file mode 100644 index 0000000..59b8885 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast02_Areola04.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast02_Nipple00.png b/1.5/Textures/Breasts_Udder/Breast_Breast02_Nipple00.png new file mode 100644 index 0000000..a066c73 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast02_Nipple00.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast02_Nipple01.png b/1.5/Textures/Breasts_Udder/Breast_Breast02_Nipple01.png new file mode 100644 index 0000000..8ca0f9f Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast02_Nipple01.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast02_Nipple02.png b/1.5/Textures/Breasts_Udder/Breast_Breast02_Nipple02.png new file mode 100644 index 0000000..57e3437 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast02_Nipple02.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast02_Nipple03.png b/1.5/Textures/Breasts_Udder/Breast_Breast02_Nipple03.png new file mode 100644 index 0000000..116d12c Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast02_Nipple03.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast03.png b/1.5/Textures/Breasts_Udder/Breast_Breast03.png new file mode 100644 index 0000000..28a8181 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast03.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola00.png b/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola00.png new file mode 100644 index 0000000..6f8b10a Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola00.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola01.png b/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola01.png new file mode 100644 index 0000000..0fcd4ca Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola01.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola02.png b/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola02.png new file mode 100644 index 0000000..1e0800e Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola02.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola03.png b/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola03.png new file mode 100644 index 0000000..6881a20 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola03.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola04.png b/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola04.png new file mode 100644 index 0000000..353e0c2 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast03_Areola04.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast03_Nipple00.png b/1.5/Textures/Breasts_Udder/Breast_Breast03_Nipple00.png new file mode 100644 index 0000000..909c923 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast03_Nipple00.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast03_Nipple01.png b/1.5/Textures/Breasts_Udder/Breast_Breast03_Nipple01.png new file mode 100644 index 0000000..93b21a4 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast03_Nipple01.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast03_Nipple02.png b/1.5/Textures/Breasts_Udder/Breast_Breast03_Nipple02.png new file mode 100644 index 0000000..cd83448 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast03_Nipple02.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast03_Nipple03.png b/1.5/Textures/Breasts_Udder/Breast_Breast03_Nipple03.png new file mode 100644 index 0000000..0cc58e6 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast03_Nipple03.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast04.png b/1.5/Textures/Breasts_Udder/Breast_Breast04.png new file mode 100644 index 0000000..1d14007 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast04.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola00.png b/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola00.png new file mode 100644 index 0000000..19e1413 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola00.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola01.png b/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola01.png new file mode 100644 index 0000000..ad00df1 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola01.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola02.png b/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola02.png new file mode 100644 index 0000000..b6d43e2 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola02.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola03.png b/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola03.png new file mode 100644 index 0000000..d92dae1 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola03.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola04.png b/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola04.png new file mode 100644 index 0000000..31a9a80 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast04_Areola04.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast04_Nipple00.png b/1.5/Textures/Breasts_Udder/Breast_Breast04_Nipple00.png new file mode 100644 index 0000000..b5cf61f Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast04_Nipple00.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast04_Nipple01.png b/1.5/Textures/Breasts_Udder/Breast_Breast04_Nipple01.png new file mode 100644 index 0000000..ad7c1b4 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast04_Nipple01.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast04_Nipple02.png b/1.5/Textures/Breasts_Udder/Breast_Breast04_Nipple02.png new file mode 100644 index 0000000..52973d1 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast04_Nipple02.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast04_Nipple03.png b/1.5/Textures/Breasts_Udder/Breast_Breast04_Nipple03.png new file mode 100644 index 0000000..3c85301 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast04_Nipple03.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast05.png b/1.5/Textures/Breasts_Udder/Breast_Breast05.png new file mode 100644 index 0000000..250ee5d Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast05.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola00.png b/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola00.png new file mode 100644 index 0000000..d89d1a2 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola00.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola01.png b/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola01.png new file mode 100644 index 0000000..fdc27b3 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola01.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola02.png b/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola02.png new file mode 100644 index 0000000..3244b0f Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola02.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola03.png b/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola03.png new file mode 100644 index 0000000..fd55a82 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola03.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola04.png b/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola04.png new file mode 100644 index 0000000..70c6aca Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast05_Areola04.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast05_Nipple00.png b/1.5/Textures/Breasts_Udder/Breast_Breast05_Nipple00.png new file mode 100644 index 0000000..1ade575 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast05_Nipple00.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast05_Nipple01.png b/1.5/Textures/Breasts_Udder/Breast_Breast05_Nipple01.png new file mode 100644 index 0000000..a0a3b3f Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast05_Nipple01.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast05_Nipple02.png b/1.5/Textures/Breasts_Udder/Breast_Breast05_Nipple02.png new file mode 100644 index 0000000..9760461 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast05_Nipple02.png differ diff --git a/1.5/Textures/Breasts_Udder/Breast_Breast05_Nipple03.png b/1.5/Textures/Breasts_Udder/Breast_Breast05_Nipple03.png new file mode 100644 index 0000000..15ac682 Binary files /dev/null and b/1.5/Textures/Breasts_Udder/Breast_Breast05_Nipple03.png differ diff --git a/1.5/Textures/Eggs/Egg.png b/1.5/Textures/Eggs/Egg.png new file mode 100644 index 0000000..8bb2ad4 Binary files /dev/null and b/1.5/Textures/Eggs/Egg.png differ diff --git a/1.5/Textures/Eggs/Egg_Fertilized00.png b/1.5/Textures/Eggs/Egg_Fertilized00.png new file mode 100644 index 0000000..49592c7 Binary files /dev/null and b/1.5/Textures/Eggs/Egg_Fertilized00.png differ diff --git a/1.5/Textures/Eggs/Egg_Fertilized01.png b/1.5/Textures/Eggs/Egg_Fertilized01.png new file mode 100644 index 0000000..5e7481a Binary files /dev/null and b/1.5/Textures/Eggs/Egg_Fertilized01.png differ diff --git a/1.5/Textures/Eggs/Egg_Fertilized02.png b/1.5/Textures/Eggs/Egg_Fertilized02.png new file mode 100644 index 0000000..c0d7d24 Binary files /dev/null and b/1.5/Textures/Eggs/Egg_Fertilized02.png differ diff --git a/1.5/Textures/Eggs/Egg_Fertilizing00.png b/1.5/Textures/Eggs/Egg_Fertilizing00.png new file mode 100644 index 0000000..121180e Binary files /dev/null and b/1.5/Textures/Eggs/Egg_Fertilizing00.png differ diff --git a/1.5/Textures/Eggs/Egg_Fertilizing01.png b/1.5/Textures/Eggs/Egg_Fertilizing01.png new file mode 100644 index 0000000..1f94f86 Binary files /dev/null and b/1.5/Textures/Eggs/Egg_Fertilizing01.png differ diff --git a/1.5/Textures/Eggs/Egg_Fertilizing02.png b/1.5/Textures/Eggs/Egg_Fertilizing02.png new file mode 100644 index 0000000..bdea1d1 Binary files /dev/null and b/1.5/Textures/Eggs/Egg_Fertilizing02.png differ diff --git a/1.5/Textures/Eggs/Egg_Implanted00.png b/1.5/Textures/Eggs/Egg_Implanted00.png new file mode 100644 index 0000000..21f74b2 Binary files /dev/null and b/1.5/Textures/Eggs/Egg_Implanted00.png differ diff --git a/1.5/Textures/Eggs/Eggs.zip b/1.5/Textures/Eggs/Eggs.zip new file mode 100644 index 0000000..7d60763 Binary files /dev/null and b/1.5/Textures/Eggs/Eggs.zip differ diff --git a/1.5/Textures/Fetus/Birds/Fetus_Bird00.png b/1.5/Textures/Fetus/Birds/Fetus_Bird00.png new file mode 100644 index 0000000..91c2a8f Binary files /dev/null and b/1.5/Textures/Fetus/Birds/Fetus_Bird00.png differ diff --git a/1.5/Textures/Fetus/Birds/Fetus_Bird01.png b/1.5/Textures/Fetus/Birds/Fetus_Bird01.png new file mode 100644 index 0000000..a6a391c Binary files /dev/null and b/1.5/Textures/Fetus/Birds/Fetus_Bird01.png differ diff --git a/1.5/Textures/Fetus/Birds/Fetus_Bird02.png b/1.5/Textures/Fetus/Birds/Fetus_Bird02.png new file mode 100644 index 0000000..140fe14 Binary files /dev/null and b/1.5/Textures/Fetus/Birds/Fetus_Bird02.png differ diff --git a/1.5/Textures/Fetus/Birds/Fetus_Bird03.png b/1.5/Textures/Fetus/Birds/Fetus_Bird03.png new file mode 100644 index 0000000..07b5afb Binary files /dev/null and b/1.5/Textures/Fetus/Birds/Fetus_Bird03.png differ diff --git a/1.5/Textures/Fetus/Birds/Fetus_Bird04.png b/1.5/Textures/Fetus/Birds/Fetus_Bird04.png new file mode 100644 index 0000000..f884958 Binary files /dev/null and b/1.5/Textures/Fetus/Birds/Fetus_Bird04.png differ diff --git a/1.5/Textures/Fetus/Birds/Fetus_Bird05.png b/1.5/Textures/Fetus/Birds/Fetus_Bird05.png new file mode 100644 index 0000000..c11fff4 Binary files /dev/null and b/1.5/Textures/Fetus/Birds/Fetus_Bird05.png differ diff --git a/1.5/Textures/Fetus/Boars/Fetus_Boar00.png b/1.5/Textures/Fetus/Boars/Fetus_Boar00.png new file mode 100644 index 0000000..762788e Binary files /dev/null and b/1.5/Textures/Fetus/Boars/Fetus_Boar00.png differ diff --git a/1.5/Textures/Fetus/Boars/Fetus_Boar01.png b/1.5/Textures/Fetus/Boars/Fetus_Boar01.png new file mode 100644 index 0000000..bc6164f Binary files /dev/null and b/1.5/Textures/Fetus/Boars/Fetus_Boar01.png differ diff --git a/1.5/Textures/Fetus/Boars/Fetus_Boar02.png b/1.5/Textures/Fetus/Boars/Fetus_Boar02.png new file mode 100644 index 0000000..b423c71 Binary files /dev/null and b/1.5/Textures/Fetus/Boars/Fetus_Boar02.png differ diff --git a/1.5/Textures/Fetus/Boars/Fetus_Boar03.png b/1.5/Textures/Fetus/Boars/Fetus_Boar03.png new file mode 100644 index 0000000..b594dd0 Binary files /dev/null and b/1.5/Textures/Fetus/Boars/Fetus_Boar03.png differ diff --git a/1.5/Textures/Fetus/Boars/Fetus_Boar04.png b/1.5/Textures/Fetus/Boars/Fetus_Boar04.png new file mode 100644 index 0000000..b576ca8 Binary files /dev/null and b/1.5/Textures/Fetus/Boars/Fetus_Boar04.png differ diff --git a/1.5/Textures/Fetus/Boars/Fetus_Boar05.png b/1.5/Textures/Fetus/Boars/Fetus_Boar05.png new file mode 100644 index 0000000..7859a53 Binary files /dev/null and b/1.5/Textures/Fetus/Boars/Fetus_Boar05.png differ diff --git a/1.5/Textures/Fetus/Boomies/Fetus_Boomalope00.png b/1.5/Textures/Fetus/Boomies/Fetus_Boomalope00.png new file mode 100644 index 0000000..f6db1ee Binary files /dev/null and b/1.5/Textures/Fetus/Boomies/Fetus_Boomalope00.png differ diff --git a/1.5/Textures/Fetus/Boomies/Fetus_Boomalope01.png b/1.5/Textures/Fetus/Boomies/Fetus_Boomalope01.png new file mode 100644 index 0000000..6f52148 Binary files /dev/null and b/1.5/Textures/Fetus/Boomies/Fetus_Boomalope01.png differ diff --git a/1.5/Textures/Fetus/Boomies/Fetus_Boomalope02.png b/1.5/Textures/Fetus/Boomies/Fetus_Boomalope02.png new file mode 100644 index 0000000..8ce8b84 Binary files /dev/null and b/1.5/Textures/Fetus/Boomies/Fetus_Boomalope02.png differ diff --git a/1.5/Textures/Fetus/Boomies/Fetus_Boomalope03.png b/1.5/Textures/Fetus/Boomies/Fetus_Boomalope03.png new file mode 100644 index 0000000..928d5e3 Binary files /dev/null and b/1.5/Textures/Fetus/Boomies/Fetus_Boomalope03.png differ diff --git a/1.5/Textures/Fetus/Boomies/Fetus_Boomalope04.png b/1.5/Textures/Fetus/Boomies/Fetus_Boomalope04.png new file mode 100644 index 0000000..55444f8 Binary files /dev/null and b/1.5/Textures/Fetus/Boomies/Fetus_Boomalope04.png differ diff --git a/1.5/Textures/Fetus/Boomies/Fetus_Boomalope05.png b/1.5/Textures/Fetus/Boomies/Fetus_Boomalope05.png new file mode 100644 index 0000000..767be38 Binary files /dev/null and b/1.5/Textures/Fetus/Boomies/Fetus_Boomalope05.png differ diff --git a/1.5/Textures/Fetus/Boomies/Fetus_Boomrat00.png b/1.5/Textures/Fetus/Boomies/Fetus_Boomrat00.png new file mode 100644 index 0000000..468fd46 Binary files /dev/null and b/1.5/Textures/Fetus/Boomies/Fetus_Boomrat00.png differ diff --git a/1.5/Textures/Fetus/Boomies/Fetus_Boomrat01.png b/1.5/Textures/Fetus/Boomies/Fetus_Boomrat01.png new file mode 100644 index 0000000..1279edc Binary files /dev/null and b/1.5/Textures/Fetus/Boomies/Fetus_Boomrat01.png differ diff --git a/1.5/Textures/Fetus/Boomies/Fetus_Boomrat02.png b/1.5/Textures/Fetus/Boomies/Fetus_Boomrat02.png new file mode 100644 index 0000000..a32f0c2 Binary files /dev/null and b/1.5/Textures/Fetus/Boomies/Fetus_Boomrat02.png differ diff --git a/1.5/Textures/Fetus/Boomies/Fetus_Boomrat03.png b/1.5/Textures/Fetus/Boomies/Fetus_Boomrat03.png new file mode 100644 index 0000000..4ab4f90 Binary files /dev/null and b/1.5/Textures/Fetus/Boomies/Fetus_Boomrat03.png differ diff --git a/1.5/Textures/Fetus/Boomies/Fetus_Boomrat04.png b/1.5/Textures/Fetus/Boomies/Fetus_Boomrat04.png new file mode 100644 index 0000000..f1cc6b6 Binary files /dev/null and b/1.5/Textures/Fetus/Boomies/Fetus_Boomrat04.png differ diff --git a/1.5/Textures/Fetus/Boomies/Fetus_Boomrat05.png b/1.5/Textures/Fetus/Boomies/Fetus_Boomrat05.png new file mode 100644 index 0000000..c81532b Binary files /dev/null and b/1.5/Textures/Fetus/Boomies/Fetus_Boomrat05.png differ diff --git a/1.5/Textures/Fetus/Bovines/Fetus_Bovine00.png b/1.5/Textures/Fetus/Bovines/Fetus_Bovine00.png new file mode 100644 index 0000000..f6db1ee Binary files /dev/null and b/1.5/Textures/Fetus/Bovines/Fetus_Bovine00.png differ diff --git a/1.5/Textures/Fetus/Bovines/Fetus_Bovine01.png b/1.5/Textures/Fetus/Bovines/Fetus_Bovine01.png new file mode 100644 index 0000000..6f52148 Binary files /dev/null and b/1.5/Textures/Fetus/Bovines/Fetus_Bovine01.png differ diff --git a/1.5/Textures/Fetus/Bovines/Fetus_Bovine02.png b/1.5/Textures/Fetus/Bovines/Fetus_Bovine02.png new file mode 100644 index 0000000..e698b3c Binary files /dev/null and b/1.5/Textures/Fetus/Bovines/Fetus_Bovine02.png differ diff --git a/1.5/Textures/Fetus/Bovines/Fetus_Bovine03.png b/1.5/Textures/Fetus/Bovines/Fetus_Bovine03.png new file mode 100644 index 0000000..23fb87e Binary files /dev/null and b/1.5/Textures/Fetus/Bovines/Fetus_Bovine03.png differ diff --git a/1.5/Textures/Fetus/Bovines/Fetus_Bovine04.png b/1.5/Textures/Fetus/Bovines/Fetus_Bovine04.png new file mode 100644 index 0000000..2f30e24 Binary files /dev/null and b/1.5/Textures/Fetus/Bovines/Fetus_Bovine04.png differ diff --git a/1.5/Textures/Fetus/Bovines/Fetus_Bovine05.png b/1.5/Textures/Fetus/Bovines/Fetus_Bovine05.png new file mode 100644 index 0000000..1678309 Binary files /dev/null and b/1.5/Textures/Fetus/Bovines/Fetus_Bovine05.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine00.png b/1.5/Textures/Fetus/Canines/Fetus_Canine00.png new file mode 100644 index 0000000..224db15 Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine00.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine00_Multiplet_2.png b/1.5/Textures/Fetus/Canines/Fetus_Canine00_Multiplet_2.png new file mode 100644 index 0000000..4a61ebf Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine00_Multiplet_2.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine01.png b/1.5/Textures/Fetus/Canines/Fetus_Canine01.png new file mode 100644 index 0000000..2c891e8 Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine01.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine01_Multiplet_2.png b/1.5/Textures/Fetus/Canines/Fetus_Canine01_Multiplet_2.png new file mode 100644 index 0000000..03822f6 Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine01_Multiplet_2.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine02.png b/1.5/Textures/Fetus/Canines/Fetus_Canine02.png new file mode 100644 index 0000000..549e42a Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine02.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine02_Multiplet_2.png b/1.5/Textures/Fetus/Canines/Fetus_Canine02_Multiplet_2.png new file mode 100644 index 0000000..8b16978 Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine02_Multiplet_2.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine03.png b/1.5/Textures/Fetus/Canines/Fetus_Canine03.png new file mode 100644 index 0000000..1ada107 Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine03.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine03_Multiplet_2.png b/1.5/Textures/Fetus/Canines/Fetus_Canine03_Multiplet_2.png new file mode 100644 index 0000000..57633cf Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine03_Multiplet_2.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine04.png b/1.5/Textures/Fetus/Canines/Fetus_Canine04.png new file mode 100644 index 0000000..5fe5776 Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine04.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine04_Multiplet_2.png b/1.5/Textures/Fetus/Canines/Fetus_Canine04_Multiplet_2.png new file mode 100644 index 0000000..2567e78 Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine04_Multiplet_2.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine05.png b/1.5/Textures/Fetus/Canines/Fetus_Canine05.png new file mode 100644 index 0000000..f658ced Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine05.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine05_Multiplet_2.png b/1.5/Textures/Fetus/Canines/Fetus_Canine05_Multiplet_2.png new file mode 100644 index 0000000..d13fae9 Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine05_Multiplet_2.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine_V00.png b/1.5/Textures/Fetus/Canines/Fetus_Canine_V00.png new file mode 100644 index 0000000..224db15 Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine_V00.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine_V01.png b/1.5/Textures/Fetus/Canines/Fetus_Canine_V01.png new file mode 100644 index 0000000..2c891e8 Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine_V01.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine_V02.png b/1.5/Textures/Fetus/Canines/Fetus_Canine_V02.png new file mode 100644 index 0000000..549e42a Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine_V02.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine_V03.png b/1.5/Textures/Fetus/Canines/Fetus_Canine_V03.png new file mode 100644 index 0000000..1ada107 Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine_V03.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine_V04.png b/1.5/Textures/Fetus/Canines/Fetus_Canine_V04.png new file mode 100644 index 0000000..5fe5776 Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine_V04.png differ diff --git a/1.5/Textures/Fetus/Canines/Fetus_Canine_V05.png b/1.5/Textures/Fetus/Canines/Fetus_Canine_V05.png new file mode 100644 index 0000000..019a873 Binary files /dev/null and b/1.5/Textures/Fetus/Canines/Fetus_Canine_V05.png differ diff --git a/1.5/Textures/Fetus/Cervines/Fetus_Cervine00.png b/1.5/Textures/Fetus/Cervines/Fetus_Cervine00.png new file mode 100644 index 0000000..762788e Binary files /dev/null and b/1.5/Textures/Fetus/Cervines/Fetus_Cervine00.png differ diff --git a/1.5/Textures/Fetus/Cervines/Fetus_Cervine01.png b/1.5/Textures/Fetus/Cervines/Fetus_Cervine01.png new file mode 100644 index 0000000..bc6164f Binary files /dev/null and b/1.5/Textures/Fetus/Cervines/Fetus_Cervine01.png differ diff --git a/1.5/Textures/Fetus/Cervines/Fetus_Cervine02.png b/1.5/Textures/Fetus/Cervines/Fetus_Cervine02.png new file mode 100644 index 0000000..a6cb3e2 Binary files /dev/null and b/1.5/Textures/Fetus/Cervines/Fetus_Cervine02.png differ diff --git a/1.5/Textures/Fetus/Cervines/Fetus_Cervine03.png b/1.5/Textures/Fetus/Cervines/Fetus_Cervine03.png new file mode 100644 index 0000000..9438482 Binary files /dev/null and b/1.5/Textures/Fetus/Cervines/Fetus_Cervine03.png differ diff --git a/1.5/Textures/Fetus/Cervines/Fetus_Cervine04.png b/1.5/Textures/Fetus/Cervines/Fetus_Cervine04.png new file mode 100644 index 0000000..69cc8d7 Binary files /dev/null and b/1.5/Textures/Fetus/Cervines/Fetus_Cervine04.png differ diff --git a/1.5/Textures/Fetus/Cervines/Fetus_Cervine05.png b/1.5/Textures/Fetus/Cervines/Fetus_Cervine05.png new file mode 100644 index 0000000..1b191c6 Binary files /dev/null and b/1.5/Textures/Fetus/Cervines/Fetus_Cervine05.png differ diff --git a/1.5/Textures/Fetus/Elephants/Fetus_Elephant00.png b/1.5/Textures/Fetus/Elephants/Fetus_Elephant00.png new file mode 100644 index 0000000..f6db1ee Binary files /dev/null and b/1.5/Textures/Fetus/Elephants/Fetus_Elephant00.png differ diff --git a/1.5/Textures/Fetus/Elephants/Fetus_Elephant01.png b/1.5/Textures/Fetus/Elephants/Fetus_Elephant01.png new file mode 100644 index 0000000..3bc43c0 Binary files /dev/null and b/1.5/Textures/Fetus/Elephants/Fetus_Elephant01.png differ diff --git a/1.5/Textures/Fetus/Elephants/Fetus_Elephant02.png b/1.5/Textures/Fetus/Elephants/Fetus_Elephant02.png new file mode 100644 index 0000000..d86e95c Binary files /dev/null and b/1.5/Textures/Fetus/Elephants/Fetus_Elephant02.png differ diff --git a/1.5/Textures/Fetus/Elephants/Fetus_Elephant03.png b/1.5/Textures/Fetus/Elephants/Fetus_Elephant03.png new file mode 100644 index 0000000..301dc81 Binary files /dev/null and b/1.5/Textures/Fetus/Elephants/Fetus_Elephant03.png differ diff --git a/1.5/Textures/Fetus/Elephants/Fetus_Elephant04.png b/1.5/Textures/Fetus/Elephants/Fetus_Elephant04.png new file mode 100644 index 0000000..b1c7d0c Binary files /dev/null and b/1.5/Textures/Fetus/Elephants/Fetus_Elephant04.png differ diff --git a/1.5/Textures/Fetus/Elephants/Fetus_Elephant05.png b/1.5/Textures/Fetus/Elephants/Fetus_Elephant05.png new file mode 100644 index 0000000..ee571c9 Binary files /dev/null and b/1.5/Textures/Fetus/Elephants/Fetus_Elephant05.png differ diff --git a/1.5/Textures/Fetus/Felines/Fetus_Feline_D00.png b/1.5/Textures/Fetus/Felines/Fetus_Feline_D00.png new file mode 100644 index 0000000..f6db1ee Binary files /dev/null and b/1.5/Textures/Fetus/Felines/Fetus_Feline_D00.png differ diff --git a/1.5/Textures/Fetus/Felines/Fetus_Feline_D01.png b/1.5/Textures/Fetus/Felines/Fetus_Feline_D01.png new file mode 100644 index 0000000..6f52148 Binary files /dev/null and b/1.5/Textures/Fetus/Felines/Fetus_Feline_D01.png differ diff --git a/1.5/Textures/Fetus/Felines/Fetus_Feline_D02.png b/1.5/Textures/Fetus/Felines/Fetus_Feline_D02.png new file mode 100644 index 0000000..ebc33af Binary files /dev/null and b/1.5/Textures/Fetus/Felines/Fetus_Feline_D02.png differ diff --git a/1.5/Textures/Fetus/Felines/Fetus_Feline_D03.png b/1.5/Textures/Fetus/Felines/Fetus_Feline_D03.png new file mode 100644 index 0000000..f28392f Binary files /dev/null and b/1.5/Textures/Fetus/Felines/Fetus_Feline_D03.png differ diff --git a/1.5/Textures/Fetus/Felines/Fetus_Feline_D04.png b/1.5/Textures/Fetus/Felines/Fetus_Feline_D04.png new file mode 100644 index 0000000..9ffdc22 Binary files /dev/null and b/1.5/Textures/Fetus/Felines/Fetus_Feline_D04.png differ diff --git a/1.5/Textures/Fetus/Felines/Fetus_Feline_D05.png b/1.5/Textures/Fetus/Felines/Fetus_Feline_D05.png new file mode 100644 index 0000000..ad7c81e Binary files /dev/null and b/1.5/Textures/Fetus/Felines/Fetus_Feline_D05.png differ diff --git a/1.5/Textures/Fetus/Felines/Fetus_Feline_W00.png b/1.5/Textures/Fetus/Felines/Fetus_Feline_W00.png new file mode 100644 index 0000000..f6db1ee Binary files /dev/null and b/1.5/Textures/Fetus/Felines/Fetus_Feline_W00.png differ diff --git a/1.5/Textures/Fetus/Felines/Fetus_Feline_W01.png b/1.5/Textures/Fetus/Felines/Fetus_Feline_W01.png new file mode 100644 index 0000000..6f52148 Binary files /dev/null and b/1.5/Textures/Fetus/Felines/Fetus_Feline_W01.png differ diff --git a/1.5/Textures/Fetus/Felines/Fetus_Feline_W02.png b/1.5/Textures/Fetus/Felines/Fetus_Feline_W02.png new file mode 100644 index 0000000..ebc33af Binary files /dev/null and b/1.5/Textures/Fetus/Felines/Fetus_Feline_W02.png differ diff --git a/1.5/Textures/Fetus/Felines/Fetus_Feline_W03.png b/1.5/Textures/Fetus/Felines/Fetus_Feline_W03.png new file mode 100644 index 0000000..f28392f Binary files /dev/null and b/1.5/Textures/Fetus/Felines/Fetus_Feline_W03.png differ diff --git a/1.5/Textures/Fetus/Felines/Fetus_Feline_W04.png b/1.5/Textures/Fetus/Felines/Fetus_Feline_W04.png new file mode 100644 index 0000000..9ffdc22 Binary files /dev/null and b/1.5/Textures/Fetus/Felines/Fetus_Feline_W04.png differ diff --git a/1.5/Textures/Fetus/Felines/Fetus_Feline_W05.png b/1.5/Textures/Fetus/Felines/Fetus_Feline_W05.png new file mode 100644 index 0000000..16de334 Binary files /dev/null and b/1.5/Textures/Fetus/Felines/Fetus_Feline_W05.png differ diff --git a/1.5/Textures/Fetus/Fetus_Default00.png b/1.5/Textures/Fetus/Fetus_Default00.png new file mode 100644 index 0000000..b7911a9 Binary files /dev/null and b/1.5/Textures/Fetus/Fetus_Default00.png differ diff --git a/1.5/Textures/Fetus/Fetus_Default00_Multiplet_2.png b/1.5/Textures/Fetus/Fetus_Default00_Multiplet_2.png new file mode 100644 index 0000000..ec24f44 Binary files /dev/null and b/1.5/Textures/Fetus/Fetus_Default00_Multiplet_2.png differ diff --git a/1.5/Textures/Fetus/Fetus_Default01.png b/1.5/Textures/Fetus/Fetus_Default01.png new file mode 100644 index 0000000..56f5728 Binary files /dev/null and b/1.5/Textures/Fetus/Fetus_Default01.png differ diff --git a/1.5/Textures/Fetus/Fetus_Default01_Multiplet_2.png b/1.5/Textures/Fetus/Fetus_Default01_Multiplet_2.png new file mode 100644 index 0000000..a34d830 Binary files /dev/null and b/1.5/Textures/Fetus/Fetus_Default01_Multiplet_2.png differ diff --git a/1.5/Textures/Fetus/Fetus_Default02.png b/1.5/Textures/Fetus/Fetus_Default02.png new file mode 100644 index 0000000..70fed44 Binary files /dev/null and b/1.5/Textures/Fetus/Fetus_Default02.png differ diff --git a/1.5/Textures/Fetus/Fetus_Default02_Multiplet_2.png b/1.5/Textures/Fetus/Fetus_Default02_Multiplet_2.png new file mode 100644 index 0000000..84ea4f6 Binary files /dev/null and b/1.5/Textures/Fetus/Fetus_Default02_Multiplet_2.png differ diff --git a/1.5/Textures/Fetus/Fetus_Default03.png b/1.5/Textures/Fetus/Fetus_Default03.png new file mode 100644 index 0000000..96e9e7f Binary files /dev/null and b/1.5/Textures/Fetus/Fetus_Default03.png differ diff --git a/1.5/Textures/Fetus/Fetus_Default03_Multiplet_2.png b/1.5/Textures/Fetus/Fetus_Default03_Multiplet_2.png new file mode 100644 index 0000000..67417fb Binary files /dev/null and b/1.5/Textures/Fetus/Fetus_Default03_Multiplet_2.png differ diff --git a/1.5/Textures/Fetus/Fetus_Default04.png b/1.5/Textures/Fetus/Fetus_Default04.png new file mode 100644 index 0000000..8f84cec Binary files /dev/null and b/1.5/Textures/Fetus/Fetus_Default04.png differ diff --git a/1.5/Textures/Fetus/Fetus_Default04_Multiplet_2.png b/1.5/Textures/Fetus/Fetus_Default04_Multiplet_2.png new file mode 100644 index 0000000..fdb4380 Binary files /dev/null and b/1.5/Textures/Fetus/Fetus_Default04_Multiplet_2.png differ diff --git a/1.5/Textures/Fetus/Fetus_Default05.png b/1.5/Textures/Fetus/Fetus_Default05.png new file mode 100644 index 0000000..8f67056 Binary files /dev/null and b/1.5/Textures/Fetus/Fetus_Default05.png differ diff --git a/1.5/Textures/Fetus/Fetus_Default05_Multiplet_2.png b/1.5/Textures/Fetus/Fetus_Default05_Multiplet_2.png new file mode 100644 index 0000000..f4e2581 Binary files /dev/null and b/1.5/Textures/Fetus/Fetus_Default05_Multiplet_2.png differ diff --git a/1.5/Textures/Fetus/Fetus_Old.zip b/1.5/Textures/Fetus/Fetus_Old.zip new file mode 100644 index 0000000..90f4e17 Binary files /dev/null and b/1.5/Textures/Fetus/Fetus_Old.zip differ diff --git a/1.5/Textures/Fetus/Fungi/Fetus_Fungi00.png b/1.5/Textures/Fetus/Fungi/Fetus_Fungi00.png new file mode 100644 index 0000000..e2365e2 Binary files /dev/null and b/1.5/Textures/Fetus/Fungi/Fetus_Fungi00.png differ diff --git a/1.5/Textures/Fetus/Fungi/Fetus_Fungi01.png b/1.5/Textures/Fetus/Fungi/Fetus_Fungi01.png new file mode 100644 index 0000000..5ebdc74 Binary files /dev/null and b/1.5/Textures/Fetus/Fungi/Fetus_Fungi01.png differ diff --git a/1.5/Textures/Fetus/Fungi/Fetus_Fungi02.png b/1.5/Textures/Fetus/Fungi/Fetus_Fungi02.png new file mode 100644 index 0000000..d26b66c Binary files /dev/null and b/1.5/Textures/Fetus/Fungi/Fetus_Fungi02.png differ diff --git a/1.5/Textures/Fetus/Fungi/Fetus_Fungi03.png b/1.5/Textures/Fetus/Fungi/Fetus_Fungi03.png new file mode 100644 index 0000000..b8c6486 Binary files /dev/null and b/1.5/Textures/Fetus/Fungi/Fetus_Fungi03.png differ diff --git a/1.5/Textures/Fetus/Fungi/Fetus_Fungi04.png b/1.5/Textures/Fetus/Fungi/Fetus_Fungi04.png new file mode 100644 index 0000000..f9a6728 Binary files /dev/null and b/1.5/Textures/Fetus/Fungi/Fetus_Fungi04.png differ diff --git a/1.5/Textures/Fetus/Fungi/Fetus_Fungi05.png b/1.5/Textures/Fetus/Fungi/Fetus_Fungi05.png new file mode 100644 index 0000000..cce729f Binary files /dev/null and b/1.5/Textures/Fetus/Fungi/Fetus_Fungi05.png differ diff --git a/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A00.png b/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A00.png new file mode 100644 index 0000000..80b6c8e Binary files /dev/null and b/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A00.png differ diff --git a/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A01.png b/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A01.png new file mode 100644 index 0000000..15cbd76 Binary files /dev/null and b/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A01.png differ diff --git a/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A02.png b/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A02.png new file mode 100644 index 0000000..675400d Binary files /dev/null and b/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A02.png differ diff --git a/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A03.png b/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A03.png new file mode 100644 index 0000000..3a60357 Binary files /dev/null and b/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A03.png differ diff --git a/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A04.png b/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A04.png new file mode 100644 index 0000000..f9a6728 Binary files /dev/null and b/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A04.png differ diff --git a/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A05.png b/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A05.png new file mode 100644 index 0000000..cce729f Binary files /dev/null and b/1.5/Textures/Fetus/Fungi/Fetus_Fungi_A05.png differ diff --git a/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine00.png b/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine00.png new file mode 100644 index 0000000..06f17e5 Binary files /dev/null and b/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine00.png differ diff --git a/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine01.png b/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine01.png new file mode 100644 index 0000000..384d2c3 Binary files /dev/null and b/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine01.png differ diff --git a/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine02.png b/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine02.png new file mode 100644 index 0000000..b16c556 Binary files /dev/null and b/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine02.png differ diff --git a/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine03.png b/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine03.png new file mode 100644 index 0000000..3cad627 Binary files /dev/null and b/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine03.png differ diff --git a/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine04.png b/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine04.png new file mode 100644 index 0000000..bc3ed7f Binary files /dev/null and b/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine04.png differ diff --git a/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine05.png b/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine05.png new file mode 100644 index 0000000..183886c Binary files /dev/null and b/1.5/Textures/Fetus/Humanoids/Fetus_Humanoid_Canine05.png differ diff --git a/1.5/Textures/Fetus/Insects/Fetus_Insect00.png b/1.5/Textures/Fetus/Insects/Fetus_Insect00.png new file mode 100644 index 0000000..bfbf0ad Binary files /dev/null and b/1.5/Textures/Fetus/Insects/Fetus_Insect00.png differ diff --git a/1.5/Textures/Fetus/Insects/Fetus_Insect01.png b/1.5/Textures/Fetus/Insects/Fetus_Insect01.png new file mode 100644 index 0000000..0b14746 Binary files /dev/null and b/1.5/Textures/Fetus/Insects/Fetus_Insect01.png differ diff --git a/1.5/Textures/Fetus/Insects/Fetus_Insect02.png b/1.5/Textures/Fetus/Insects/Fetus_Insect02.png new file mode 100644 index 0000000..13d5264 Binary files /dev/null and b/1.5/Textures/Fetus/Insects/Fetus_Insect02.png differ diff --git a/1.5/Textures/Fetus/Insects/Fetus_Insect03.png b/1.5/Textures/Fetus/Insects/Fetus_Insect03.png new file mode 100644 index 0000000..acc2e56 Binary files /dev/null and b/1.5/Textures/Fetus/Insects/Fetus_Insect03.png differ diff --git a/1.5/Textures/Fetus/Insects/Fetus_Insect04.png b/1.5/Textures/Fetus/Insects/Fetus_Insect04.png new file mode 100644 index 0000000..7b92a2f Binary files /dev/null and b/1.5/Textures/Fetus/Insects/Fetus_Insect04.png differ diff --git a/1.5/Textures/Fetus/Insects/Fetus_Insect05.png b/1.5/Textures/Fetus/Insects/Fetus_Insect05.png new file mode 100644 index 0000000..9af559c Binary files /dev/null and b/1.5/Textures/Fetus/Insects/Fetus_Insect05.png differ diff --git a/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph00.png b/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph00.png new file mode 100644 index 0000000..523884e Binary files /dev/null and b/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph00.png differ diff --git a/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph01.png b/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph01.png new file mode 100644 index 0000000..351c68d Binary files /dev/null and b/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph01.png differ diff --git a/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph02.png b/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph02.png new file mode 100644 index 0000000..6181c3a Binary files /dev/null and b/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph02.png differ diff --git a/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph03.png b/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph03.png new file mode 100644 index 0000000..cbf8f47 Binary files /dev/null and b/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph03.png differ diff --git a/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph04.png b/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph04.png new file mode 100644 index 0000000..fdd26df Binary files /dev/null and b/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph04.png differ diff --git a/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph05.png b/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph05.png new file mode 100644 index 0000000..188c808 Binary files /dev/null and b/1.5/Textures/Fetus/Lagomorphs/Fetus_Lagomorph05.png differ diff --git a/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid00.png b/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid00.png new file mode 100644 index 0000000..fdccd4d Binary files /dev/null and b/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid00.png differ diff --git a/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid01.png b/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid01.png new file mode 100644 index 0000000..8ce0ba8 Binary files /dev/null and b/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid01.png differ diff --git a/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid02.png b/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid02.png new file mode 100644 index 0000000..077f2d1 Binary files /dev/null and b/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid02.png differ diff --git a/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid03.png b/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid03.png new file mode 100644 index 0000000..cd38ccd Binary files /dev/null and b/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid03.png differ diff --git a/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid04.png b/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid04.png new file mode 100644 index 0000000..c597052 Binary files /dev/null and b/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid04.png differ diff --git a/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid05.png b/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid05.png new file mode 100644 index 0000000..b2c02d5 Binary files /dev/null and b/1.5/Textures/Fetus/Mechanoids/Fetus_Mechanoid05.png differ diff --git a/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth00.png b/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth00.png new file mode 100644 index 0000000..468fd46 Binary files /dev/null and b/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth00.png differ diff --git a/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth01.png b/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth01.png new file mode 100644 index 0000000..1279edc Binary files /dev/null and b/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth01.png differ diff --git a/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth02.png b/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth02.png new file mode 100644 index 0000000..cabb343 Binary files /dev/null and b/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth02.png differ diff --git a/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth03.png b/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth03.png new file mode 100644 index 0000000..fd80bd7 Binary files /dev/null and b/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth03.png differ diff --git a/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth04.png b/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth04.png new file mode 100644 index 0000000..05a9474 Binary files /dev/null and b/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth04.png differ diff --git a/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth05.png b/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth05.png new file mode 100644 index 0000000..d82229f Binary files /dev/null and b/1.5/Textures/Fetus/Megasloths/Fetus_Megasloth05.png differ diff --git a/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo00.png b/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo00.png new file mode 100644 index 0000000..762788e Binary files /dev/null and b/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo00.png differ diff --git a/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo01.png b/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo01.png new file mode 100644 index 0000000..bc6164f Binary files /dev/null and b/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo01.png differ diff --git a/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo02.png b/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo02.png new file mode 100644 index 0000000..8f3e65d Binary files /dev/null and b/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo02.png differ diff --git a/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo03.png b/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo03.png new file mode 100644 index 0000000..183d540 Binary files /dev/null and b/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo03.png differ diff --git a/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo04.png b/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo04.png new file mode 100644 index 0000000..fd5beec Binary files /dev/null and b/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo04.png differ diff --git a/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo05.png b/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo05.png new file mode 100644 index 0000000..8f38bcc Binary files /dev/null and b/1.5/Textures/Fetus/Muffalos/Fetus_Muffalo05.png differ diff --git a/1.5/Textures/Fetus/Pigs/Fetus_Pig00.png b/1.5/Textures/Fetus/Pigs/Fetus_Pig00.png new file mode 100644 index 0000000..c99d2ac Binary files /dev/null and b/1.5/Textures/Fetus/Pigs/Fetus_Pig00.png differ diff --git a/1.5/Textures/Fetus/Pigs/Fetus_Pig01.png b/1.5/Textures/Fetus/Pigs/Fetus_Pig01.png new file mode 100644 index 0000000..c2841e5 Binary files /dev/null and b/1.5/Textures/Fetus/Pigs/Fetus_Pig01.png differ diff --git a/1.5/Textures/Fetus/Pigs/Fetus_Pig02.png b/1.5/Textures/Fetus/Pigs/Fetus_Pig02.png new file mode 100644 index 0000000..604c67d Binary files /dev/null and b/1.5/Textures/Fetus/Pigs/Fetus_Pig02.png differ diff --git a/1.5/Textures/Fetus/Pigs/Fetus_Pig03.png b/1.5/Textures/Fetus/Pigs/Fetus_Pig03.png new file mode 100644 index 0000000..ccb7598 Binary files /dev/null and b/1.5/Textures/Fetus/Pigs/Fetus_Pig03.png differ diff --git a/1.5/Textures/Fetus/Pigs/Fetus_Pig04.png b/1.5/Textures/Fetus/Pigs/Fetus_Pig04.png new file mode 100644 index 0000000..711eb14 Binary files /dev/null and b/1.5/Textures/Fetus/Pigs/Fetus_Pig04.png differ diff --git a/1.5/Textures/Fetus/Pigs/Fetus_Pig05.png b/1.5/Textures/Fetus/Pigs/Fetus_Pig05.png new file mode 100644 index 0000000..4563e8e Binary files /dev/null and b/1.5/Textures/Fetus/Pigs/Fetus_Pig05.png differ diff --git a/1.5/Textures/Fetus/Plants/Fetus_Plant_F00.png b/1.5/Textures/Fetus/Plants/Fetus_Plant_F00.png new file mode 100644 index 0000000..22e9036 Binary files /dev/null and b/1.5/Textures/Fetus/Plants/Fetus_Plant_F00.png differ diff --git a/1.5/Textures/Fetus/Plants/Fetus_Plant_F01.png b/1.5/Textures/Fetus/Plants/Fetus_Plant_F01.png new file mode 100644 index 0000000..d70c396 Binary files /dev/null and b/1.5/Textures/Fetus/Plants/Fetus_Plant_F01.png differ diff --git a/1.5/Textures/Fetus/Plants/Fetus_Plant_F02.png b/1.5/Textures/Fetus/Plants/Fetus_Plant_F02.png new file mode 100644 index 0000000..5532eeb Binary files /dev/null and b/1.5/Textures/Fetus/Plants/Fetus_Plant_F02.png differ diff --git a/1.5/Textures/Fetus/Plants/Fetus_Plant_F03.png b/1.5/Textures/Fetus/Plants/Fetus_Plant_F03.png new file mode 100644 index 0000000..aab4b91 Binary files /dev/null and b/1.5/Textures/Fetus/Plants/Fetus_Plant_F03.png differ diff --git a/1.5/Textures/Fetus/Plants/Fetus_Plant_F04.png b/1.5/Textures/Fetus/Plants/Fetus_Plant_F04.png new file mode 100644 index 0000000..0f1f9d3 Binary files /dev/null and b/1.5/Textures/Fetus/Plants/Fetus_Plant_F04.png differ diff --git a/1.5/Textures/Fetus/Plants/Fetus_Plant_F05.png b/1.5/Textures/Fetus/Plants/Fetus_Plant_F05.png new file mode 100644 index 0000000..e4f2039 Binary files /dev/null and b/1.5/Textures/Fetus/Plants/Fetus_Plant_F05.png differ diff --git a/1.5/Textures/Fetus/Plants/Fetus_Plant_G00.png b/1.5/Textures/Fetus/Plants/Fetus_Plant_G00.png new file mode 100644 index 0000000..86be5df Binary files /dev/null and b/1.5/Textures/Fetus/Plants/Fetus_Plant_G00.png differ diff --git a/1.5/Textures/Fetus/Plants/Fetus_Plant_G01.png b/1.5/Textures/Fetus/Plants/Fetus_Plant_G01.png new file mode 100644 index 0000000..1350bd0 Binary files /dev/null and b/1.5/Textures/Fetus/Plants/Fetus_Plant_G01.png differ diff --git a/1.5/Textures/Fetus/Plants/Fetus_Plant_G02.png b/1.5/Textures/Fetus/Plants/Fetus_Plant_G02.png new file mode 100644 index 0000000..4dcce18 Binary files /dev/null and b/1.5/Textures/Fetus/Plants/Fetus_Plant_G02.png differ diff --git a/1.5/Textures/Fetus/Plants/Fetus_Plant_G03.png b/1.5/Textures/Fetus/Plants/Fetus_Plant_G03.png new file mode 100644 index 0000000..201aa10 Binary files /dev/null and b/1.5/Textures/Fetus/Plants/Fetus_Plant_G03.png differ diff --git a/1.5/Textures/Fetus/Plants/Fetus_Plant_G04.png b/1.5/Textures/Fetus/Plants/Fetus_Plant_G04.png new file mode 100644 index 0000000..2dcc968 Binary files /dev/null and b/1.5/Textures/Fetus/Plants/Fetus_Plant_G04.png differ diff --git a/1.5/Textures/Fetus/Plants/Fetus_Plant_G05.png b/1.5/Textures/Fetus/Plants/Fetus_Plant_G05.png new file mode 100644 index 0000000..c4286b4 Binary files /dev/null and b/1.5/Textures/Fetus/Plants/Fetus_Plant_G05.png differ diff --git a/1.5/Textures/Fetus/Primate/Fetus_Primate00.png b/1.5/Textures/Fetus/Primate/Fetus_Primate00.png new file mode 100644 index 0000000..843b61f Binary files /dev/null and b/1.5/Textures/Fetus/Primate/Fetus_Primate00.png differ diff --git a/1.5/Textures/Fetus/Primate/Fetus_Primate01.png b/1.5/Textures/Fetus/Primate/Fetus_Primate01.png new file mode 100644 index 0000000..e2974ad Binary files /dev/null and b/1.5/Textures/Fetus/Primate/Fetus_Primate01.png differ diff --git a/1.5/Textures/Fetus/Primate/Fetus_Primate02.png b/1.5/Textures/Fetus/Primate/Fetus_Primate02.png new file mode 100644 index 0000000..e2c5295 Binary files /dev/null and b/1.5/Textures/Fetus/Primate/Fetus_Primate02.png differ diff --git a/1.5/Textures/Fetus/Primate/Fetus_Primate03.png b/1.5/Textures/Fetus/Primate/Fetus_Primate03.png new file mode 100644 index 0000000..d8d78d5 Binary files /dev/null and b/1.5/Textures/Fetus/Primate/Fetus_Primate03.png differ diff --git a/1.5/Textures/Fetus/Primate/Fetus_Primate04.png b/1.5/Textures/Fetus/Primate/Fetus_Primate04.png new file mode 100644 index 0000000..e87e09b Binary files /dev/null and b/1.5/Textures/Fetus/Primate/Fetus_Primate04.png differ diff --git a/1.5/Textures/Fetus/Primate/Fetus_Primate05.png b/1.5/Textures/Fetus/Primate/Fetus_Primate05.png new file mode 100644 index 0000000..fcb6b8b Binary files /dev/null and b/1.5/Textures/Fetus/Primate/Fetus_Primate05.png differ diff --git a/1.5/Textures/Fetus/Reptiles/Fetus_Reptile00.png b/1.5/Textures/Fetus/Reptiles/Fetus_Reptile00.png new file mode 100644 index 0000000..f46a6b4 Binary files /dev/null and b/1.5/Textures/Fetus/Reptiles/Fetus_Reptile00.png differ diff --git a/1.5/Textures/Fetus/Reptiles/Fetus_Reptile01.png b/1.5/Textures/Fetus/Reptiles/Fetus_Reptile01.png new file mode 100644 index 0000000..620ecc0 Binary files /dev/null and b/1.5/Textures/Fetus/Reptiles/Fetus_Reptile01.png differ diff --git a/1.5/Textures/Fetus/Reptiles/Fetus_Reptile02.png b/1.5/Textures/Fetus/Reptiles/Fetus_Reptile02.png new file mode 100644 index 0000000..1e24ea2 Binary files /dev/null and b/1.5/Textures/Fetus/Reptiles/Fetus_Reptile02.png differ diff --git a/1.5/Textures/Fetus/Reptiles/Fetus_Reptile03.png b/1.5/Textures/Fetus/Reptiles/Fetus_Reptile03.png new file mode 100644 index 0000000..1dc1dee Binary files /dev/null and b/1.5/Textures/Fetus/Reptiles/Fetus_Reptile03.png differ diff --git a/1.5/Textures/Fetus/Reptiles/Fetus_Reptile04.png b/1.5/Textures/Fetus/Reptiles/Fetus_Reptile04.png new file mode 100644 index 0000000..42df9bf Binary files /dev/null and b/1.5/Textures/Fetus/Reptiles/Fetus_Reptile04.png differ diff --git a/1.5/Textures/Fetus/Reptiles/Fetus_Reptile05.png b/1.5/Textures/Fetus/Reptiles/Fetus_Reptile05.png new file mode 100644 index 0000000..2c5827f Binary files /dev/null and b/1.5/Textures/Fetus/Reptiles/Fetus_Reptile05.png differ diff --git a/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros00.png b/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros00.png new file mode 100644 index 0000000..762788e Binary files /dev/null and b/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros00.png differ diff --git a/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros01.png b/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros01.png new file mode 100644 index 0000000..bc6164f Binary files /dev/null and b/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros01.png differ diff --git a/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros02.png b/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros02.png new file mode 100644 index 0000000..9db4a3d Binary files /dev/null and b/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros02.png differ diff --git a/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros03.png b/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros03.png new file mode 100644 index 0000000..3d89f12 Binary files /dev/null and b/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros03.png differ diff --git a/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros04.png b/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros04.png new file mode 100644 index 0000000..8fcbfaa Binary files /dev/null and b/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros04.png differ diff --git a/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros05.png b/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros05.png new file mode 100644 index 0000000..904eb4b Binary files /dev/null and b/1.5/Textures/Fetus/Rhinoceroses/Fetus_Rhinoceros05.png differ diff --git a/1.5/Textures/Fetus/Rodents/Fetus_Rodent00.png b/1.5/Textures/Fetus/Rodents/Fetus_Rodent00.png new file mode 100644 index 0000000..919de6c Binary files /dev/null and b/1.5/Textures/Fetus/Rodents/Fetus_Rodent00.png differ diff --git a/1.5/Textures/Fetus/Rodents/Fetus_Rodent01.png b/1.5/Textures/Fetus/Rodents/Fetus_Rodent01.png new file mode 100644 index 0000000..bd28845 Binary files /dev/null and b/1.5/Textures/Fetus/Rodents/Fetus_Rodent01.png differ diff --git a/1.5/Textures/Fetus/Rodents/Fetus_Rodent02.png b/1.5/Textures/Fetus/Rodents/Fetus_Rodent02.png new file mode 100644 index 0000000..a2f43eb Binary files /dev/null and b/1.5/Textures/Fetus/Rodents/Fetus_Rodent02.png differ diff --git a/1.5/Textures/Fetus/Rodents/Fetus_Rodent03.png b/1.5/Textures/Fetus/Rodents/Fetus_Rodent03.png new file mode 100644 index 0000000..e92e044 Binary files /dev/null and b/1.5/Textures/Fetus/Rodents/Fetus_Rodent03.png differ diff --git a/1.5/Textures/Fetus/Rodents/Fetus_Rodent04.png b/1.5/Textures/Fetus/Rodents/Fetus_Rodent04.png new file mode 100644 index 0000000..f249348 Binary files /dev/null and b/1.5/Textures/Fetus/Rodents/Fetus_Rodent04.png differ diff --git a/1.5/Textures/Fetus/Rodents/Fetus_Rodent05.png b/1.5/Textures/Fetus/Rodents/Fetus_Rodent05.png new file mode 100644 index 0000000..0301628 Binary files /dev/null and b/1.5/Textures/Fetus/Rodents/Fetus_Rodent05.png differ diff --git a/1.5/Textures/Fetus/Slime_Abomi02.png b/1.5/Textures/Fetus/Slime_Abomi02.png new file mode 100644 index 0000000..ebc1722 Binary files /dev/null and b/1.5/Textures/Fetus/Slime_Abomi02.png differ diff --git a/1.5/Textures/Fetus/Snakes/Fetus_Snake00.png b/1.5/Textures/Fetus/Snakes/Fetus_Snake00.png new file mode 100644 index 0000000..ef39c1c Binary files /dev/null and b/1.5/Textures/Fetus/Snakes/Fetus_Snake00.png differ diff --git a/1.5/Textures/Fetus/Snakes/Fetus_Snake01.png b/1.5/Textures/Fetus/Snakes/Fetus_Snake01.png new file mode 100644 index 0000000..39c82ea Binary files /dev/null and b/1.5/Textures/Fetus/Snakes/Fetus_Snake01.png differ diff --git a/1.5/Textures/Fetus/Snakes/Fetus_Snake02.png b/1.5/Textures/Fetus/Snakes/Fetus_Snake02.png new file mode 100644 index 0000000..c9d2661 Binary files /dev/null and b/1.5/Textures/Fetus/Snakes/Fetus_Snake02.png differ diff --git a/1.5/Textures/Fetus/Snakes/Fetus_Snake03.png b/1.5/Textures/Fetus/Snakes/Fetus_Snake03.png new file mode 100644 index 0000000..3d508c8 Binary files /dev/null and b/1.5/Textures/Fetus/Snakes/Fetus_Snake03.png differ diff --git a/1.5/Textures/Fetus/Snakes/Fetus_Snake04.png b/1.5/Textures/Fetus/Snakes/Fetus_Snake04.png new file mode 100644 index 0000000..38d21f0 Binary files /dev/null and b/1.5/Textures/Fetus/Snakes/Fetus_Snake04.png differ diff --git a/1.5/Textures/Fetus/Snakes/Fetus_Snake05.png b/1.5/Textures/Fetus/Snakes/Fetus_Snake05.png new file mode 100644 index 0000000..adbe992 Binary files /dev/null and b/1.5/Textures/Fetus/Snakes/Fetus_Snake05.png differ diff --git a/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo00.png b/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo00.png new file mode 100644 index 0000000..74bd164 Binary files /dev/null and b/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo00.png differ diff --git a/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo01.png b/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo01.png new file mode 100644 index 0000000..864a2fb Binary files /dev/null and b/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo01.png differ diff --git a/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo02.png b/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo02.png new file mode 100644 index 0000000..0add0b4 Binary files /dev/null and b/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo02.png differ diff --git a/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo03.png b/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo03.png new file mode 100644 index 0000000..7cd26b2 Binary files /dev/null and b/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo03.png differ diff --git a/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo04.png b/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo04.png new file mode 100644 index 0000000..0b79b69 Binary files /dev/null and b/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo04.png differ diff --git a/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo05.png b/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo05.png new file mode 100644 index 0000000..2d3770b Binary files /dev/null and b/1.5/Textures/Fetus/Thrumbos/Fetus_Thrumbo05.png differ diff --git a/1.5/Textures/Fetus/Ursids/Fetus_Ursid00.png b/1.5/Textures/Fetus/Ursids/Fetus_Ursid00.png new file mode 100644 index 0000000..0c9e061 Binary files /dev/null and b/1.5/Textures/Fetus/Ursids/Fetus_Ursid00.png differ diff --git a/1.5/Textures/Fetus/Ursids/Fetus_Ursid01.png b/1.5/Textures/Fetus/Ursids/Fetus_Ursid01.png new file mode 100644 index 0000000..0b8ffe8 Binary files /dev/null and b/1.5/Textures/Fetus/Ursids/Fetus_Ursid01.png differ diff --git a/1.5/Textures/Fetus/Ursids/Fetus_Ursid02.png b/1.5/Textures/Fetus/Ursids/Fetus_Ursid02.png new file mode 100644 index 0000000..3d1460e Binary files /dev/null and b/1.5/Textures/Fetus/Ursids/Fetus_Ursid02.png differ diff --git a/1.5/Textures/Fetus/Ursids/Fetus_Ursid03.png b/1.5/Textures/Fetus/Ursids/Fetus_Ursid03.png new file mode 100644 index 0000000..d8db475 Binary files /dev/null and b/1.5/Textures/Fetus/Ursids/Fetus_Ursid03.png differ diff --git a/1.5/Textures/Fetus/Ursids/Fetus_Ursid04.png b/1.5/Textures/Fetus/Ursids/Fetus_Ursid04.png new file mode 100644 index 0000000..a479abe Binary files /dev/null and b/1.5/Textures/Fetus/Ursids/Fetus_Ursid04.png differ diff --git a/1.5/Textures/Fetus/Ursids/Fetus_Ursid05.png b/1.5/Textures/Fetus/Ursids/Fetus_Ursid05.png new file mode 100644 index 0000000..a2fbedb Binary files /dev/null and b/1.5/Textures/Fetus/Ursids/Fetus_Ursid05.png differ diff --git a/1.5/Textures/Fetus/Ursids/Fetus_Ursid05_ALT.png b/1.5/Textures/Fetus/Ursids/Fetus_Ursid05_ALT.png new file mode 100644 index 0000000..9e15468 Binary files /dev/null and b/1.5/Textures/Fetus/Ursids/Fetus_Ursid05_ALT.png differ diff --git a/1.5/Textures/Fetus/~Dev/00.png b/1.5/Textures/Fetus/~Dev/00.png new file mode 100644 index 0000000..4fa4235 Binary files /dev/null and b/1.5/Textures/Fetus/~Dev/00.png differ diff --git a/1.5/Textures/Fetus/~Dev/01.png b/1.5/Textures/Fetus/~Dev/01.png new file mode 100644 index 0000000..36f6a9e Binary files /dev/null and b/1.5/Textures/Fetus/~Dev/01.png differ diff --git a/1.5/Textures/Fetus/~Dev/02.png b/1.5/Textures/Fetus/~Dev/02.png new file mode 100644 index 0000000..6c7c436 Binary files /dev/null and b/1.5/Textures/Fetus/~Dev/02.png differ diff --git a/1.5/Textures/Fetus/~Dev/03.png b/1.5/Textures/Fetus/~Dev/03.png new file mode 100644 index 0000000..aaf4b75 Binary files /dev/null and b/1.5/Textures/Fetus/~Dev/03.png differ diff --git a/1.5/Textures/Fetus/~Dev/04.png b/1.5/Textures/Fetus/~Dev/04.png new file mode 100644 index 0000000..6011650 Binary files /dev/null and b/1.5/Textures/Fetus/~Dev/04.png differ diff --git a/1.5/Textures/Fetus/~Dev/05.png b/1.5/Textures/Fetus/~Dev/05.png new file mode 100644 index 0000000..d799f8b Binary files /dev/null and b/1.5/Textures/Fetus/~Dev/05.png differ diff --git a/1.5/Textures/Fetus/~Dev/~00.png b/1.5/Textures/Fetus/~Dev/~00.png new file mode 100644 index 0000000..492db0b Binary files /dev/null and b/1.5/Textures/Fetus/~Dev/~00.png differ diff --git a/1.5/Textures/Genitals/Anal00.png b/1.5/Textures/Genitals/Anal00.png new file mode 100644 index 0000000..56a35c6 Binary files /dev/null and b/1.5/Textures/Genitals/Anal00.png differ diff --git a/1.5/Textures/Genitals/Anal01.png b/1.5/Textures/Genitals/Anal01.png new file mode 100644 index 0000000..0d7e6fe Binary files /dev/null and b/1.5/Textures/Genitals/Anal01.png differ diff --git a/1.5/Textures/Genitals/Anal02.png b/1.5/Textures/Genitals/Anal02.png new file mode 100644 index 0000000..e6ccd30 Binary files /dev/null and b/1.5/Textures/Genitals/Anal02.png differ diff --git a/1.5/Textures/Genitals/Anal03.png b/1.5/Textures/Genitals/Anal03.png new file mode 100644 index 0000000..24230a2 Binary files /dev/null and b/1.5/Textures/Genitals/Anal03.png differ diff --git a/1.5/Textures/Genitals/Anal04.png b/1.5/Textures/Genitals/Anal04.png new file mode 100644 index 0000000..d4a601e Binary files /dev/null and b/1.5/Textures/Genitals/Anal04.png differ diff --git a/1.5/Textures/Genitals/Anal05.png b/1.5/Textures/Genitals/Anal05.png new file mode 100644 index 0000000..fcf61a1 Binary files /dev/null and b/1.5/Textures/Genitals/Anal05.png differ diff --git a/1.5/Textures/Genitals/BionicAnal00.png b/1.5/Textures/Genitals/BionicAnal00.png new file mode 100644 index 0000000..4bf820a Binary files /dev/null and b/1.5/Textures/Genitals/BionicAnal00.png differ diff --git a/1.5/Textures/Genitals/BionicAnal01.png b/1.5/Textures/Genitals/BionicAnal01.png new file mode 100644 index 0000000..056e118 Binary files /dev/null and b/1.5/Textures/Genitals/BionicAnal01.png differ diff --git a/1.5/Textures/Genitals/BionicAnal02.png b/1.5/Textures/Genitals/BionicAnal02.png new file mode 100644 index 0000000..55f158f Binary files /dev/null and b/1.5/Textures/Genitals/BionicAnal02.png differ diff --git a/1.5/Textures/Genitals/BionicAnal03.png b/1.5/Textures/Genitals/BionicAnal03.png new file mode 100644 index 0000000..0d499db Binary files /dev/null and b/1.5/Textures/Genitals/BionicAnal03.png differ diff --git a/1.5/Textures/Genitals/BionicAnal04.png b/1.5/Textures/Genitals/BionicAnal04.png new file mode 100644 index 0000000..123ac48 Binary files /dev/null and b/1.5/Textures/Genitals/BionicAnal04.png differ diff --git a/1.5/Textures/Genitals/BionicAnal05.png b/1.5/Textures/Genitals/BionicAnal05.png new file mode 100644 index 0000000..d3d7282 Binary files /dev/null and b/1.5/Textures/Genitals/BionicAnal05.png differ diff --git a/1.5/Textures/Genitals/BionicVagina00.png b/1.5/Textures/Genitals/BionicVagina00.png new file mode 100644 index 0000000..ba2f7ef Binary files /dev/null and b/1.5/Textures/Genitals/BionicVagina00.png differ diff --git a/1.5/Textures/Genitals/BionicVagina01.png b/1.5/Textures/Genitals/BionicVagina01.png new file mode 100644 index 0000000..1d0fa81 Binary files /dev/null and b/1.5/Textures/Genitals/BionicVagina01.png differ diff --git a/1.5/Textures/Genitals/BionicVagina02.png b/1.5/Textures/Genitals/BionicVagina02.png new file mode 100644 index 0000000..79513d0 Binary files /dev/null and b/1.5/Textures/Genitals/BionicVagina02.png differ diff --git a/1.5/Textures/Genitals/BionicVagina03.png b/1.5/Textures/Genitals/BionicVagina03.png new file mode 100644 index 0000000..02b9cd7 Binary files /dev/null and b/1.5/Textures/Genitals/BionicVagina03.png differ diff --git a/1.5/Textures/Genitals/BionicVagina04.png b/1.5/Textures/Genitals/BionicVagina04.png new file mode 100644 index 0000000..4c55740 Binary files /dev/null and b/1.5/Textures/Genitals/BionicVagina04.png differ diff --git a/1.5/Textures/Genitals/BionicVagina05.png b/1.5/Textures/Genitals/BionicVagina05.png new file mode 100644 index 0000000..63e8e69 Binary files /dev/null and b/1.5/Textures/Genitals/BionicVagina05.png differ diff --git a/1.5/Textures/Genitals/BionicVagina06.png b/1.5/Textures/Genitals/BionicVagina06.png new file mode 100644 index 0000000..ace296e Binary files /dev/null and b/1.5/Textures/Genitals/BionicVagina06.png differ diff --git a/1.5/Textures/Genitals/BionicVagina07.png b/1.5/Textures/Genitals/BionicVagina07.png new file mode 100644 index 0000000..8626639 Binary files /dev/null and b/1.5/Textures/Genitals/BionicVagina07.png differ diff --git a/1.5/Textures/Genitals/BionicVagina08.png b/1.5/Textures/Genitals/BionicVagina08.png new file mode 100644 index 0000000..fc1f753 Binary files /dev/null and b/1.5/Textures/Genitals/BionicVagina08.png differ diff --git a/1.5/Textures/Genitals/BionicVagina09.png b/1.5/Textures/Genitals/BionicVagina09.png new file mode 100644 index 0000000..88e8b4d Binary files /dev/null and b/1.5/Textures/Genitals/BionicVagina09.png differ diff --git a/1.5/Textures/Genitals/BionicVagina10.png b/1.5/Textures/Genitals/BionicVagina10.png new file mode 100644 index 0000000..528b599 Binary files /dev/null and b/1.5/Textures/Genitals/BionicVagina10.png differ diff --git a/1.5/Textures/Genitals/BionicVagina11.png b/1.5/Textures/Genitals/BionicVagina11.png new file mode 100644 index 0000000..ecd46bf Binary files /dev/null and b/1.5/Textures/Genitals/BionicVagina11.png differ diff --git a/1.5/Textures/Genitals/Genitals_Old.zip b/1.5/Textures/Genitals/Genitals_Old.zip new file mode 100644 index 0000000..bda9dd3 Binary files /dev/null and b/1.5/Textures/Genitals/Genitals_Old.zip differ diff --git a/1.5/Textures/Genitals/Vagina00.png b/1.5/Textures/Genitals/Vagina00.png new file mode 100644 index 0000000..cb44e12 Binary files /dev/null and b/1.5/Textures/Genitals/Vagina00.png differ diff --git a/1.5/Textures/Genitals/Vagina01.png b/1.5/Textures/Genitals/Vagina01.png new file mode 100644 index 0000000..ca2f66e Binary files /dev/null and b/1.5/Textures/Genitals/Vagina01.png differ diff --git a/1.5/Textures/Genitals/Vagina02.png b/1.5/Textures/Genitals/Vagina02.png new file mode 100644 index 0000000..bbeb801 Binary files /dev/null and b/1.5/Textures/Genitals/Vagina02.png differ diff --git a/1.5/Textures/Genitals/Vagina03.png b/1.5/Textures/Genitals/Vagina03.png new file mode 100644 index 0000000..ded7dc7 Binary files /dev/null and b/1.5/Textures/Genitals/Vagina03.png differ diff --git a/1.5/Textures/Genitals/Vagina04.png b/1.5/Textures/Genitals/Vagina04.png new file mode 100644 index 0000000..741d8d1 Binary files /dev/null and b/1.5/Textures/Genitals/Vagina04.png differ diff --git a/1.5/Textures/Genitals/Vagina05.png b/1.5/Textures/Genitals/Vagina05.png new file mode 100644 index 0000000..7488b12 Binary files /dev/null and b/1.5/Textures/Genitals/Vagina05.png differ diff --git a/1.5/Textures/Genitals/Vagina06.png b/1.5/Textures/Genitals/Vagina06.png new file mode 100644 index 0000000..619d0ec Binary files /dev/null and b/1.5/Textures/Genitals/Vagina06.png differ diff --git a/1.5/Textures/Genitals/Vagina07.png b/1.5/Textures/Genitals/Vagina07.png new file mode 100644 index 0000000..6a3fcaa Binary files /dev/null and b/1.5/Textures/Genitals/Vagina07.png differ diff --git a/1.5/Textures/Genitals/Vagina08.png b/1.5/Textures/Genitals/Vagina08.png new file mode 100644 index 0000000..7e80d92 Binary files /dev/null and b/1.5/Textures/Genitals/Vagina08.png differ diff --git a/1.5/Textures/Genitals/Vagina09.png b/1.5/Textures/Genitals/Vagina09.png new file mode 100644 index 0000000..64e778a Binary files /dev/null and b/1.5/Textures/Genitals/Vagina09.png differ diff --git a/1.5/Textures/Genitals/Vagina10.png b/1.5/Textures/Genitals/Vagina10.png new file mode 100644 index 0000000..6c738a8 Binary files /dev/null and b/1.5/Textures/Genitals/Vagina10.png differ diff --git a/1.5/Textures/Genitals/Vagina11.png b/1.5/Textures/Genitals/Vagina11.png new file mode 100644 index 0000000..5fa6410 Binary files /dev/null and b/1.5/Textures/Genitals/Vagina11.png differ diff --git a/1.5/Textures/Milk/Milkbottle_Large.png b/1.5/Textures/Milk/Milkbottle_Large.png new file mode 100644 index 0000000..e84f80a Binary files /dev/null and b/1.5/Textures/Milk/Milkbottle_Large.png differ diff --git a/1.5/Textures/Milk/Milkbottle_Medium.png b/1.5/Textures/Milk/Milkbottle_Medium.png new file mode 100644 index 0000000..133b635 Binary files /dev/null and b/1.5/Textures/Milk/Milkbottle_Medium.png differ diff --git a/1.5/Textures/Milk/Milkbottle_Small.png b/1.5/Textures/Milk/Milkbottle_Small.png new file mode 100644 index 0000000..352428c Binary files /dev/null and b/1.5/Textures/Milk/Milkbottle_Small.png differ diff --git a/1.5/Textures/Ovaries/Ovary_00.png b/1.5/Textures/Ovaries/Ovary_00.png new file mode 100644 index 0000000..4f939ed Binary files /dev/null and b/1.5/Textures/Ovaries/Ovary_00.png differ diff --git a/1.5/Textures/Ovaries/Ovary_01.png b/1.5/Textures/Ovaries/Ovary_01.png new file mode 100644 index 0000000..6853246 Binary files /dev/null and b/1.5/Textures/Ovaries/Ovary_01.png differ diff --git a/1.5/Textures/Ovaries/Ovary_02.png b/1.5/Textures/Ovaries/Ovary_02.png new file mode 100644 index 0000000..423223d Binary files /dev/null and b/1.5/Textures/Ovaries/Ovary_02.png differ diff --git a/1.5/Textures/Textures_old.7z b/1.5/Textures/Textures_old.7z new file mode 100644 index 0000000..a967dfb Binary files /dev/null and b/1.5/Textures/Textures_old.7z differ diff --git a/1.5/Textures/Things/Item/Cyclosporine/Cyclosporine_a.png b/1.5/Textures/Things/Item/Cyclosporine/Cyclosporine_a.png new file mode 100644 index 0000000..1984d94 Binary files /dev/null and b/1.5/Textures/Things/Item/Cyclosporine/Cyclosporine_a.png differ diff --git a/1.5/Textures/Things/Item/Cyclosporine/Cyclosporine_b.png b/1.5/Textures/Things/Item/Cyclosporine/Cyclosporine_b.png new file mode 100644 index 0000000..6a22bf4 Binary files /dev/null and b/1.5/Textures/Things/Item/Cyclosporine/Cyclosporine_b.png differ diff --git a/1.5/Textures/Things/Item/ORPill/ORPill_a.png b/1.5/Textures/Things/Item/ORPill/ORPill_a.png new file mode 100644 index 0000000..641fa33 Binary files /dev/null and b/1.5/Textures/Things/Item/ORPill/ORPill_a.png differ diff --git a/1.5/Textures/Things/Item/ORPill/ORPill_b.png b/1.5/Textures/Things/Item/ORPill/ORPill_b.png new file mode 100644 index 0000000..2c9261f Binary files /dev/null and b/1.5/Textures/Things/Item/ORPill/ORPill_b.png differ diff --git a/1.5/Textures/Things/Item/Pad.png b/1.5/Textures/Things/Item/Pad.png new file mode 100644 index 0000000..5cc5bb6 Binary files /dev/null and b/1.5/Textures/Things/Item/Pad.png differ diff --git a/1.5/Textures/Things/Item/PainReliever/PainReliever_a.png b/1.5/Textures/Things/Item/PainReliever/PainReliever_a.png new file mode 100644 index 0000000..d9f48a9 Binary files /dev/null and b/1.5/Textures/Things/Item/PainReliever/PainReliever_a.png differ diff --git a/1.5/Textures/Things/Item/PainReliever/PainReliever_b.png b/1.5/Textures/Things/Item/PainReliever/PainReliever_b.png new file mode 100644 index 0000000..c1fedaa Binary files /dev/null and b/1.5/Textures/Things/Item/PainReliever/PainReliever_b.png differ diff --git a/1.5/Textures/Things/Item/SIA/SIA_a.png b/1.5/Textures/Things/Item/SIA/SIA_a.png new file mode 100644 index 0000000..3cb46be Binary files /dev/null and b/1.5/Textures/Things/Item/SIA/SIA_a.png differ diff --git a/1.5/Textures/Things/Item/SIA/SIA_b.png b/1.5/Textures/Things/Item/SIA/SIA_b.png new file mode 100644 index 0000000..46d30ed Binary files /dev/null and b/1.5/Textures/Things/Item/SIA/SIA_b.png differ diff --git a/1.5/Textures/Things/Item/Tampon.png b/1.5/Textures/Things/Item/Tampon.png new file mode 100644 index 0000000..fadac31 Binary files /dev/null and b/1.5/Textures/Things/Item/Tampon.png differ diff --git a/1.5/Textures/Things/Item/Tampon/Tampon_a.png b/1.5/Textures/Things/Item/Tampon/Tampon_a.png new file mode 100644 index 0000000..fadac31 Binary files /dev/null and b/1.5/Textures/Things/Item/Tampon/Tampon_a.png differ diff --git a/1.5/Textures/Things/Item/Tampon/Tampon_b.png b/1.5/Textures/Things/Item/Tampon/Tampon_b.png new file mode 100644 index 0000000..fdb575d Binary files /dev/null and b/1.5/Textures/Things/Item/Tampon/Tampon_b.png differ diff --git a/1.5/Textures/UI/Genes/DoubleEggLifetime.png b/1.5/Textures/UI/Genes/DoubleEggLifetime.png new file mode 100644 index 0000000..4fce3ef Binary files /dev/null and b/1.5/Textures/UI/Genes/DoubleEggLifetime.png differ diff --git a/1.5/Textures/UI/Genes/DoubleOvulation.png b/1.5/Textures/UI/Genes/DoubleOvulation.png new file mode 100644 index 0000000..114aff7 Binary files /dev/null and b/1.5/Textures/UI/Genes/DoubleOvulation.png differ diff --git a/1.5/Textures/UI/Genes/Files.zip b/1.5/Textures/UI/Genes/Files.zip new file mode 100644 index 0000000..b569056 Binary files /dev/null and b/1.5/Textures/UI/Genes/Files.zip differ diff --git a/1.5/Textures/UI/Genes/FullEstrus.png b/1.5/Textures/UI/Genes/FullEstrus.png new file mode 100644 index 0000000..1126439 Binary files /dev/null and b/1.5/Textures/UI/Genes/FullEstrus.png differ diff --git a/1.5/Textures/UI/Genes/NeverEstrus.png b/1.5/Textures/UI/Genes/NeverEstrus.png new file mode 100644 index 0000000..0b093e7 Binary files /dev/null and b/1.5/Textures/UI/Genes/NeverEstrus.png differ diff --git a/1.5/Textures/UI/Genes/NoBleeding.png b/1.5/Textures/UI/Genes/NoBleeding.png new file mode 100644 index 0000000..aa845f6 Binary files /dev/null and b/1.5/Textures/UI/Genes/NoBleeding.png differ diff --git a/1.5/Textures/UI/Genes/Placeholder.png b/1.5/Textures/UI/Genes/Placeholder.png new file mode 100644 index 0000000..9927017 Binary files /dev/null and b/1.5/Textures/UI/Genes/Placeholder.png differ diff --git a/1.5/Textures/UI/Genes/QuadEggLifetime.png b/1.5/Textures/UI/Genes/QuadEggLifetime.png new file mode 100644 index 0000000..872740e Binary files /dev/null and b/1.5/Textures/UI/Genes/QuadEggLifetime.png differ diff --git a/1.5/Textures/UI/Genes/QuadOvulation.png b/1.5/Textures/UI/Genes/QuadOvulation.png new file mode 100644 index 0000000..fb8bb04 Binary files /dev/null and b/1.5/Textures/UI/Genes/QuadOvulation.png differ diff --git a/1.5/Textures/UI/Genes/ShortEggLifetime.png b/1.5/Textures/UI/Genes/ShortEggLifetime.png new file mode 100644 index 0000000..375a8c3 Binary files /dev/null and b/1.5/Textures/UI/Genes/ShortEggLifetime.png differ diff --git a/1.5/Textures/UI/Icon/EggRegeneration.png b/1.5/Textures/UI/Icon/EggRegeneration.png new file mode 100644 index 0000000..af60909 Binary files /dev/null and b/1.5/Textures/UI/Icon/EggRegeneration.png differ diff --git a/1.5/Textures/Womb/Empty.png b/1.5/Textures/Womb/Empty.png new file mode 100644 index 0000000..4d6978c Binary files /dev/null and b/1.5/Textures/Womb/Empty.png differ diff --git a/1.5/Textures/Womb/ImplantedEgg.png b/1.5/Textures/Womb/ImplantedEgg.png new file mode 100644 index 0000000..8fbb580 Binary files /dev/null and b/1.5/Textures/Womb/ImplantedEgg.png differ diff --git a/1.5/Textures/Womb/ImplantedEgg_Multiplet_2.png b/1.5/Textures/Womb/ImplantedEgg_Multiplet_2.png new file mode 100644 index 0000000..ead613b Binary files /dev/null and b/1.5/Textures/Womb/ImplantedEgg_Multiplet_2.png differ diff --git a/1.5/Textures/Womb/ImplantedEgg_triplet_3.png b/1.5/Textures/Womb/ImplantedEgg_triplet_3.png new file mode 100644 index 0000000..f419977 Binary files /dev/null and b/1.5/Textures/Womb/ImplantedEgg_triplet_3.png differ diff --git a/1.5/Textures/Womb/Insect_Egged/Womb_Egged_L00.png b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_L00.png new file mode 100644 index 0000000..3ee5737 Binary files /dev/null and b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_L00.png differ diff --git a/1.5/Textures/Womb/Insect_Egged/Womb_Egged_L01.png b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_L01.png new file mode 100644 index 0000000..95cd300 Binary files /dev/null and b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_L01.png differ diff --git a/1.5/Textures/Womb/Insect_Egged/Womb_Egged_L02.png b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_L02.png new file mode 100644 index 0000000..e104e56 Binary files /dev/null and b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_L02.png differ diff --git a/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S00.png b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S00.png new file mode 100644 index 0000000..baa0fb7 Binary files /dev/null and b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S00.png differ diff --git a/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S01.png b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S01.png new file mode 100644 index 0000000..e636380 Binary files /dev/null and b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S01.png differ diff --git a/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S02.png b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S02.png new file mode 100644 index 0000000..2cdb78b Binary files /dev/null and b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S02.png differ diff --git a/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S03.png b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S03.png new file mode 100644 index 0000000..5d0cb9c Binary files /dev/null and b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S03.png differ diff --git a/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S04.png b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S04.png new file mode 100644 index 0000000..4a6eb29 Binary files /dev/null and b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_S04.png differ diff --git a/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_00.png b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_00.png new file mode 100644 index 0000000..a7b547a Binary files /dev/null and b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_00.png differ diff --git a/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_01.png b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_01.png new file mode 100644 index 0000000..caf66ec Binary files /dev/null and b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_01.png differ diff --git a/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_02.png b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_02.png new file mode 100644 index 0000000..c24716a Binary files /dev/null and b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_02.png differ diff --git a/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_03.png b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_03.png new file mode 100644 index 0000000..3abc96e Binary files /dev/null and b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_03.png differ diff --git a/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_04.png b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_04.png new file mode 100644 index 0000000..055c699 Binary files /dev/null and b/1.5/Textures/Womb/Insect_Egged/Womb_Egged_Stuffed_04.png differ diff --git a/1.5/Textures/Womb/Womb.png b/1.5/Textures/Womb/Womb.png new file mode 100644 index 0000000..4fa4235 Binary files /dev/null and b/1.5/Textures/Womb/Womb.png differ diff --git a/1.5/Textures/Womb/Womb.zip b/1.5/Textures/Womb/Womb.zip new file mode 100644 index 0000000..475b690 Binary files /dev/null and b/1.5/Textures/Womb/Womb.zip differ diff --git a/1.5/Textures/Womb/Womb_Bleeding.png b/1.5/Textures/Womb/Womb_Bleeding.png new file mode 100644 index 0000000..6669b0e Binary files /dev/null and b/1.5/Textures/Womb/Womb_Bleeding.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_00.png b/1.5/Textures/Womb/Womb_Cum_00.png new file mode 100644 index 0000000..ec656b9 Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_00.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_01.png b/1.5/Textures/Womb/Womb_Cum_01.png new file mode 100644 index 0000000..0c07275 Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_01.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_02.png b/1.5/Textures/Womb/Womb_Cum_02.png new file mode 100644 index 0000000..74d73c7 Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_02.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_03.png b/1.5/Textures/Womb/Womb_Cum_03.png new file mode 100644 index 0000000..b7dd6b5 Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_03.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_04.png b/1.5/Textures/Womb/Womb_Cum_04.png new file mode 100644 index 0000000..530401e Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_04.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_05.png b/1.5/Textures/Womb/Womb_Cum_05.png new file mode 100644 index 0000000..610220b Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_05.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_06.png b/1.5/Textures/Womb/Womb_Cum_06.png new file mode 100644 index 0000000..ed1d9be Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_06.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_07.png b/1.5/Textures/Womb/Womb_Cum_07.png new file mode 100644 index 0000000..05f1d6e Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_07.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_08.png b/1.5/Textures/Womb/Womb_Cum_08.png new file mode 100644 index 0000000..790c90e Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_08.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_09.png b/1.5/Textures/Womb/Womb_Cum_09.png new file mode 100644 index 0000000..79535b2 Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_09.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_10.png b/1.5/Textures/Womb/Womb_Cum_10.png new file mode 100644 index 0000000..f4b5dad Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_10.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_11.png b/1.5/Textures/Womb/Womb_Cum_11.png new file mode 100644 index 0000000..c338860 Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_11.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_12.png b/1.5/Textures/Womb/Womb_Cum_12.png new file mode 100644 index 0000000..f7a2d46 Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_12.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_13.png b/1.5/Textures/Womb/Womb_Cum_13.png new file mode 100644 index 0000000..3e21af2 Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_13.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_14.png b/1.5/Textures/Womb/Womb_Cum_14.png new file mode 100644 index 0000000..5afc08b Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_14.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_15.png b/1.5/Textures/Womb/Womb_Cum_15.png new file mode 100644 index 0000000..43092eb Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_15.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_16.png b/1.5/Textures/Womb/Womb_Cum_16.png new file mode 100644 index 0000000..74cfdf7 Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_16.png differ diff --git a/1.5/Textures/Womb/Womb_Cum_17.png b/1.5/Textures/Womb/Womb_Cum_17.png new file mode 100644 index 0000000..bf62126 Binary files /dev/null and b/1.5/Textures/Womb/Womb_Cum_17.png differ diff --git a/1.5/Textures/Womb/Womb_Implanted.png b/1.5/Textures/Womb/Womb_Implanted.png new file mode 100644 index 0000000..e43e714 Binary files /dev/null and b/1.5/Textures/Womb/Womb_Implanted.png differ diff --git a/1.5/Textures/Womb/Womb_Implanted_Multiplet_2.png b/1.5/Textures/Womb/Womb_Implanted_Multiplet_2.png new file mode 100644 index 0000000..79e712a Binary files /dev/null and b/1.5/Textures/Womb/Womb_Implanted_Multiplet_2.png differ diff --git a/1.5/Textures/Womb/Womb_Implanted_Multiplet_3.png b/1.5/Textures/Womb/Womb_Implanted_Multiplet_3.png new file mode 100644 index 0000000..95398da Binary files /dev/null and b/1.5/Textures/Womb/Womb_Implanted_Multiplet_3.png differ diff --git a/1.5/Textures/Womb/Womb_Implanted_Multiplet_4.png b/1.5/Textures/Womb/Womb_Implanted_Multiplet_4.png new file mode 100644 index 0000000..4b4e3d5 Binary files /dev/null and b/1.5/Textures/Womb/Womb_Implanted_Multiplet_4.png differ diff --git a/1.5/Textures/Womb/Womb_Implanted_Multiplet_5.png b/1.5/Textures/Womb/Womb_Implanted_Multiplet_5.png new file mode 100644 index 0000000..d2be223 Binary files /dev/null and b/1.5/Textures/Womb/Womb_Implanted_Multiplet_5.png differ diff --git a/1.5/source/RJW_Menstruation/MilkModule/JobDriver_MilkSelf.cs b/1.5/source/RJW_Menstruation/MilkModule/JobDriver_MilkSelf.cs new file mode 100644 index 0000000..1a1cfd4 --- /dev/null +++ b/1.5/source/RJW_Menstruation/MilkModule/JobDriver_MilkSelf.cs @@ -0,0 +1,119 @@ +using Milk; +using RJW_Menstruation; +using Verse; + +namespace MilkModule +{ + public class JobDriver_MilkSelf_MC : JobDriver_MilkSelf + { + HumanCompHasGatherableBodyResource comp; + HediffComp_Breast breastcomp; + + protected override float Fullness + { + get + { + return comp?.Fullness ?? 0f; + } + } + + protected override void PreMakeNewToils() + { + comp = GetMilkComp(pawn); + breastcomp = pawn.GetBreastComp(); + } + + protected override void Gathered() + { + comp?.Gathered(pawn); + } + + protected override void PostTickAction() + { + breastcomp?.AdjustNippleProgress(Rand.Range(0.0f, 0.000005f) * Configurations.MaxNippleIncrementFactor); + } + + + public static HumanCompHasGatherableBodyResource GetMilkComp(Pawn pawn) + { + HumanCompHasGatherableBodyResource result; + if (pawn.health.hediffSet.HasHediff(VariousDefOf.Hediff_Heavy_Lactating_Permanent)) + { + result = pawn.TryGetComp(); + + } + else + { + result = pawn.TryGetComp(); + } + return result; + } + + + + } + + + //public class JobDriver_HumanMilkSelf : JobDriver + //{ + // const float milkingTime = 250f;//ticks - 120 = 2 real seconds, 3 in-game minutes + // + // public override bool TryMakePreToilReservations(bool errorOnFailed) + // { + // return pawn.Reserve(pawn, job, 1, -1, null, errorOnFailed); + // } + // + // protected override IEnumerable MakeNewToils() + // { + // + // HumanCompHasGatherableBodyResource Comp = GetMilkComp(pawn); + // HediffComp_Breast breastcomp = pawn.GetBreastComp(); + // this.FailOn(delegate + // { + // return !(Comp.Fullness > 0.01f); + // }); + // Toil milking = Toils_General.Wait((int)(50 + milkingTime * Comp.Fullness), TargetIndex.None);//duration of + // + // milking.WithProgressBarToilDelay(TargetIndex.A); + // milking.tickAction = delegate () + // { + // if (breastcomp != null) + // { + // breastcomp.AdjustAreolaSize(Rand.Range(0.0f,0.0001f * Configurations.NipplePermanentTransitionVariance)); + // breastcomp.AdjustNippleSize(Rand.Range(0.0f,0.0001f * Configurations.NipplePermanentTransitionVariance)); + // } + // + // }; + // yield return milking; + // yield return new Toil() + // { + // initAction = delegate () + // { + // Comp.Gathered(pawn); + // } + // }; + // //yield return excreting; + // yield break; + // + // } + // + // + // public static HumanCompHasGatherableBodyResource GetMilkComp(Pawn pawn) + // { + // HumanCompHasGatherableBodyResource result; + // if (pawn.health.hediffSet.HasHediff(VariousDefOf.Hediff_Heavy_Lactating_Permanent)) + // { + // result = pawn.TryGetComp(); + // } + // else + // { + // result = pawn.TryGetComp(); + // } + // return result; + // } + // + // + //} + + +} diff --git a/1.5/source/RJW_Menstruation/MilkModule/MilkModule.csproj b/1.5/source/RJW_Menstruation/MilkModule/MilkModule.csproj new file mode 100644 index 0000000..646ba34 --- /dev/null +++ b/1.5/source/RJW_Menstruation/MilkModule/MilkModule.csproj @@ -0,0 +1,104 @@ + + + + + Debug + AnyCPU + {3591B3C1-EB57-44BF-AB69-A613E097A7F8} + Library + Properties + MilkModule + MilkModule + v4.8 + 512 + true + + + + true + full + false + ..\..\..\MilkModule\Assemblies\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\..\MilkModule\Assemblies\ + TRACE + prompt + 4 + + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll + False + + + ..\..\..\..\..\rjw-mc\1.3\Assemblies\Milk.dll + False + + + + + + + + + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.IMGUIModule.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.TextCoreModule.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.TextRenderingModule.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.UI.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.UIElementsModule.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.UIModule.dll + False + + + + + + + + + + {eed2f3b9-8c20-4194-919e-8d151b29f70b} + RJW_Menstruation + False + + + + + 2.2.2 + runtime + compile; build; native; contentfiles; analyzers; buildtransitive + + + + \ No newline at end of file diff --git a/1.5/source/RJW_Menstruation/MilkModule/Milk_Patch.cs b/1.5/source/RJW_Menstruation/MilkModule/Milk_Patch.cs new file mode 100644 index 0000000..3167822 --- /dev/null +++ b/1.5/source/RJW_Menstruation/MilkModule/Milk_Patch.cs @@ -0,0 +1,28 @@ +using HarmonyLib; +using Milk; +using RJW_Menstruation; +using System.Reflection; +using Verse; + +namespace MilkModule +{ + internal static class First + { + static First() + { + Harmony har = new Harmony("RJW_Menstruation_MilkModule"); + har.PatchAll(Assembly.GetExecutingAssembly()); + } + } + + [HarmonyPatch(typeof(HumanCompHasGatherableBodyResource), nameof(HumanCompHasGatherableBodyResource.Gathered))] + public static class Milk_Patch + { + public static void Postfix(HumanCompHasGatherableBodyResource __instance) + { + if (__instance.parent is Pawn pawn) + pawn.GetBreastComp()?.AdjustNippleProgress(Rand.Range(0.0f, 0.005f) * Configurations.MaxNippleIncrementFactor); + } + + } +} diff --git a/1.5/source/RJW_Menstruation/MilkModule/Properties/AssemblyInfo.cs b/1.5/source/RJW_Menstruation/MilkModule/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c526740 --- /dev/null +++ b/1.5/source/RJW_Menstruation/MilkModule/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해 +// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면 +// 이러한 특성 값을 변경하세요. +[assembly: AssemblyTitle("MilkModule")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MilkModule")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에 +// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면 +// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요. +[assembly: ComVisible(false)] + +// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다. +[assembly: Guid("3591b3c1-eb57-44bf-ab69-a613e097a7f8")] + +// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다. +// +// 주 버전 +// 부 버전 +// 빌드 번호 +// 수정 버전 +// +// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를 +// 기본값으로 할 수 있습니다. +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/1.5/source/RJW_Menstruation/MilkModule/packages.config b/1.5/source/RJW_Menstruation/MilkModule/packages.config new file mode 100644 index 0000000..3299dfc --- /dev/null +++ b/1.5/source/RJW_Menstruation/MilkModule/packages.config @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation.sln b/1.5/source/RJW_Menstruation/RJW_Menstruation.sln new file mode 100644 index 0000000..37d1010 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32929.385 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RJW_Menstruation", "RJW_Menstruation\RJW_Menstruation.csproj", "{EED2F3B9-8C20-4194-919E-8D151B29F70B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EED2F3B9-8C20-4194-919E-8D151B29F70B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EED2F3B9-8C20-4194-919E-8D151B29F70B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EED2F3B9-8C20-4194-919E-8D151B29F70B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EED2F3B9-8C20-4194-919E-8D151B29F70B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0E4B1D09-2A81-4440-AC1E-32ACCECBEE0B} + EndGlobalSection +EndGlobal diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/App.config b/1.5/source/RJW_Menstruation/RJW_Menstruation/App.config new file mode 100644 index 0000000..4bfa005 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/CompBiosculpterPod_EggRestorationCycle.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/CompBiosculpterPod_EggRestorationCycle.cs new file mode 100644 index 0000000..b7656c8 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/CompBiosculpterPod_EggRestorationCycle.cs @@ -0,0 +1,30 @@ +using RimWorld; +using System.Linq; +using Verse; + +namespace RJW_Menstruation +{ + public class CompProperties_BiosculpterPod_EggRestorationCycle : CompProperties_BiosculpterPod_BaseCycle + { + public CompProperties_BiosculpterPod_EggRestorationCycle() + { + compClass = typeof(CompBiosculpterPod_EggRestorationCycle); + } + + public float yearsToRestore; + } + + public class CompBiosculpterPod_EggRestorationCycle : CompBiosculpterPod_Cycle + { + + public override void CycleCompleted(Pawn occupant) + { + foreach (HediffComp_Menstruation comp in occupant.GetMenstruationComps()) + comp.RestoreEggs(((CompProperties_BiosculpterPod_EggRestorationCycle)Props).yearsToRestore); + + Messages.Message(Translations.EggRestorationCompleted(occupant.Named("PAWN")), occupant, MessageTypeDefOf.PositiveEvent); + if (occupant.GetMenstruationComps().Any()) + occupant.needs.mood?.thoughts?.memories?.TryGainMemoryFast(VariousDefOf.EggRestorationReceived); + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Compatibility/AnimalGeneticsCompatibility.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Compatibility/AnimalGeneticsCompatibility.cs new file mode 100644 index 0000000..9cbb425 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Compatibility/AnimalGeneticsCompatibility.cs @@ -0,0 +1,40 @@ +using AnimalGenetics; +using RimWorld; +using System.Collections.Generic; +using Verse; + +namespace RJW_Menstruation +{ + public static class AnimalGeneticsCompatibility + { + public static void PreConception(Pawn mother, Pawn father) + { + GeneticInformation motherGeneticInformation = mother?.AnimalGenetics(); + GeneticInformation fatherGeneticInformation = father?.AnimalGenetics(); + + ParentReferences.Push(new ParentReferences.Record { Mother = motherGeneticInformation, Father = fatherGeneticInformation }); + } + + public static void PostConception() + { + ParentReferences.Pop(); + } + + public static void CopyGenes(Pawn baby, Pawn original) + { + Dictionary babyRecords = baby.AnimalGenetics()?.GeneRecords; + Dictionary originalRecords = original.AnimalGenetics()?.GeneRecords; + + if (babyRecords == null || originalRecords == null) return; + + foreach(KeyValuePair record in originalRecords) + { + GeneRecord originalRecord = record.Value; + if (!babyRecords.TryGetValue(record.Key, out GeneRecord babyRecord)) continue; // Shouldn't fail, but best to be safe + + babyRecord.Parent = originalRecord.Parent; + babyRecord.Value = originalRecord.Value; + } + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Compatibility/HARCompatibility.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Compatibility/HARCompatibility.cs new file mode 100644 index 0000000..1100c71 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Compatibility/HARCompatibility.cs @@ -0,0 +1,34 @@ +using AlienRace; +using System.Collections.Generic; +using UnityEngine; +using Verse; + +namespace RJW_Menstruation +{ + public static class HARCompatibility + { + + public static bool IsHAR(this Pawn pawn) + { + if (!Configurations.HARActivated) return false; + return GenTypes.GetTypeInAnyAssembly("AlienRace.ThingDef_AlienRace").IsInstanceOfType(pawn?.def); + } + + public static void CopyHARProperties(Pawn baby, Pawn original) + { + AlienPartGenerator.AlienComp babyHARComp = baby?.TryGetComp(); + AlienPartGenerator.AlienComp originalHARComp = original?.TryGetComp(); + if (babyHARComp == null || originalHARComp == null) return; + + babyHARComp.addonVariants = new List(originalHARComp.addonVariants); + foreach (KeyValuePair> channel in originalHARComp.ColorChannels) + { + babyHARComp.OverwriteColorChannel(channel.Key, channel.Value.first, channel.Value.second); + } + babyHARComp.headVariant = originalHARComp.headVariant; + babyHARComp.bodyVariant = originalHARComp.bodyVariant; + babyHARComp.headMaskVariant = originalHARComp.headMaskVariant; + babyHARComp.bodyMaskVariant = originalHARComp.bodyMaskVariant; + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Configurations.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Configurations.cs new file mode 100644 index 0000000..72724c0 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Configurations.cs @@ -0,0 +1,553 @@ +using RimWorld; +using rjw; +using System; +using System.Collections.Generic; +using UnityEngine; +using Verse; + +namespace RJW_Menstruation +{ + public class Configurations : ModSettings + { + public const float ImplantationChanceDefault = 0.65f; + public const int ImplantationChanceAdjustDefault = 65; + public const float FertilizeChanceDefault = 0.15f; + public const int FertilizeChanceAdjustDefault = 150; + public const float CumDecayRatioDefault = 0.15f; + public const int CumDecayRatioAdjustDefault = 150; + public const float CumFertilityDecayRatioDefault = 0.05f; + public const int CumFertilityDecayRatioAdjustDefault = 50; + public const int CycleAccelerationDefault = 6; + public const int ColonistTickIntervalDefault = GenDate.TicksPerHour; + public const int NonColonistTickIntervalDefault = GenDate.TicksPerHour; + public const int AnimalTickIntervalDefault = GenDate.TicksPerHour; + public const int TickIntervalMinimum = GenTicks.TicksPerRealSecond / 3; + public const int TickIntervalMaximum = 4 * GenDate.TicksPerHour; + public const float EnzygoticTwinsChanceDefault = 0.002f; + public const int EnzygoticTwinsChanceAdjustDefault = 2; + public const int MaxEnzygoticTwinsDefault = 9; + public const int BleedingAmountDefault = 50; + public const float MaxBreastIncrementFactorDefault = 1.0f; + public const float MaxBreastIncrementFactorMax = 2.5f; + public const float MaxNippleIncrementFactorDefault = 1.0f; + public const float MaxNippleIncrementFactorMax = 2.5f; + public const float PermanentNippleChangeDefault = 0.1f; + public const float PermanentNippleChangeMax = 0.25f; + public const float EggLifespanMultiplierDefault = 1.0f; + public const float VaginaMorphPowerDefault = 0.2f; + + public static DetailLevel infoDetail = DetailLevel.All; + + public static float ImplantationChance = ImplantationChanceDefault; + public static int ImplantationChanceAdjust = ImplantationChanceAdjustDefault; + public static float FertilizeChance = FertilizeChanceDefault; + public static int FertilizeChanceAdjust = FertilizeChanceAdjustDefault; + public static float CumDecayRatio = CumDecayRatioDefault; + public static int CumDecayRatioAdjust = CumDecayRatioAdjustDefault; + public static float CumFertilityDecayRatio = CumFertilityDecayRatioDefault; + public static int CumFertilityDecayRatioAdjust = CumFertilityDecayRatioAdjustDefault; + public static int CycleAcceleration = CycleAccelerationDefault; + public static int ColonistTickInterval = ColonistTickIntervalDefault; + public static int NonColonistTickInterval = NonColonistTickIntervalDefault; + public static int AnimalTickInterval = AnimalTickIntervalDefault; + public static bool EnableWombIcon = true; + public static bool EnableDraftedIcon = true; + public static bool EnableAnimalCycle = false; + public static bool DrawWombStatus = true; + public static bool DrawVaginaStatus = true; + public static bool DrawEggOverlay = true; + public static bool Debug = false; + public static bool EnableMenopause = true; + public static bool EnablePheromones = true; + public static float AnimalPheromoneEffect = 0.0f; + public static DetailLevel InfoDetail => infoDetail; + public static bool EstrusOverridesHookupSettings = false; + public static float EstrusFuckabilityToHookup = RJWHookupSettings.MinimumFuckabilityToHookup; + public static float EstrusAttractivenessToHookup = RJWHookupSettings.MinimumAttractivenessToHookup; + public static float EstrusRelationshipToHookup = RJWHookupSettings.MinimumRelationshipToHookup; + public static PregnancyType PregnancySource = PregnancyType.MultiplePregnancy; + public static bool EnableBiotechTwins = false; + public static bool EnableHeteroOvularTwins = true; + public static bool EnableEnzygoticTwins = true; + public static float EnzygoticTwinsChance = EnzygoticTwinsChanceDefault; + public static int EnzygoticTwinsChanceAdjust = EnzygoticTwinsChanceAdjustDefault; + public static int MaxEnzygoticTwins = MaxEnzygoticTwinsDefault; + public static int BleedingAmount = BleedingAmountDefault; + public static bool EnableButtonInHT = false; + public static PawnFlags ShowFlag = PawnFlags.Colonist | PawnFlags.Prisoner; + public static bool UseHybridExtention = true; + public static bool AllowShrinkIcon = false; + public static float EggLifespanMultiplier = EggLifespanMultiplierDefault; + public static bool EnableBirthVaginaMorph = false; + public static float VaginaMorphPower = VaginaMorphPowerDefault; + public static float MaxBreastIncrementFactor = MaxBreastIncrementFactorDefault; + public static float MaxNippleIncrementFactor = MaxNippleIncrementFactorDefault; + public static float PermanentNippleChange = PermanentNippleChangeDefault; + public static void SetToDefault() + { + ImplantationChanceAdjust = ImplantationChanceAdjustDefault; + FertilizeChanceAdjust = FertilizeChanceAdjustDefault; + CumDecayRatioAdjust = CumDecayRatioAdjustDefault; + CumFertilityDecayRatioAdjust = CumFertilityDecayRatioAdjustDefault; + EnableWombIcon = true; + EnableDraftedIcon = true; + EnableAnimalCycle = false; + EnableMenopause = true; + EnablePheromones = true; + AnimalPheromoneEffect = 0.0f; + CycleAcceleration = CycleAccelerationDefault; + ColonistTickInterval = ColonistTickIntervalDefault; + NonColonistTickInterval = NonColonistTickIntervalDefault; + AnimalTickInterval = AnimalTickIntervalDefault; + EstrusOverridesHookupSettings = false; + EstrusFuckabilityToHookup = RJWHookupSettings.MinimumFuckabilityToHookup; + EstrusAttractivenessToHookup = RJWHookupSettings.MinimumAttractivenessToHookup; + EstrusRelationshipToHookup = RJWHookupSettings.MinimumRelationshipToHookup; + EnzygoticTwinsChanceAdjust = EnzygoticTwinsChanceAdjustDefault; + EnableBiotechTwins = false; + EnableEnzygoticTwins = true; + EnableHeteroOvularTwins = true; + PregnancySource = PregnancyType.MultiplePregnancy; + MaxEnzygoticTwins = MaxEnzygoticTwinsDefault; + BleedingAmount = BleedingAmountDefault; + MaxBreastIncrementFactor = MaxBreastIncrementFactorDefault; + MaxNippleIncrementFactor= MaxNippleIncrementFactorDefault; + PermanentNippleChange = PermanentNippleChangeDefault; + EggLifespanMultiplier = EggLifespanMultiplierDefault; + VaginaMorphPower = VaginaMorphPowerDefault; + } + + + public static List HybridOverride = new List(); + + + public static bool HARActivated = false; + public static bool AnimalGeneticsActivated = false; + + public enum DetailLevel + { + All, + OnReveal, + HideFetusInfo, + Hide + } + + public static string LevelString(DetailLevel level) + { + switch (level) + { + case DetailLevel.All: + return "All"; + case DetailLevel.OnReveal: + return "On reveal"; + case DetailLevel.HideFetusInfo: + return "Hide fetus info"; + case DetailLevel.Hide: + return "Hide"; + default: + return ""; + } + + + } + public static string HybridString(bool b) + { + if (b) return Translations.Option23_Label_1; + else return Translations.Option23_Label_2; + } + + public static bool IsOverrideExist(ThingDef def) + { + List removeList = new List(); + if (!HybridOverride.NullOrEmpty()) + foreach (HybridInformations o in HybridOverride) + { + if (o.IsNull) removeList.Add(o); + if (o.DefName == def.defName) return true; + } + foreach (HybridInformations o in removeList) + { + HybridOverride.Remove(o); + } + return false; + } + + [Flags] + public enum PawnFlags + { + None = 0, + Colonist = 1, + Prisoner = 2, + Ally = 4, + Neutral = 8, + Hostile = 16 + } + + public enum PregnancyType + { + BaseRJW, + MultiplePregnancy, + Biotech + } + + public override void ExposeData() + { + Scribe_Values.Look(ref ImplantationChanceAdjust, "ImplantationChanceAdjust", ImplantationChanceAdjustDefault); + Scribe_Values.Look(ref ImplantationChance, "ImplantationChance", ImplantationChanceDefault); + Scribe_Values.Look(ref FertilizeChanceAdjust, "FertilizeChanceAdjust", FertilizeChanceAdjustDefault); + Scribe_Values.Look(ref FertilizeChance, "FertilizeChance", FertilizeChanceDefault); + Scribe_Values.Look(ref CumDecayRatioAdjust, "CumDecayRatioAdjust", CumDecayRatioAdjustDefault); + Scribe_Values.Look(ref CumDecayRatio, "CumDecayRatio", CumDecayRatioDefault); + Scribe_Values.Look(ref CumFertilityDecayRatioAdjust, "CumFertilityDecayRatioAdjust", CumFertilityDecayRatioAdjustDefault); + Scribe_Values.Look(ref CumFertilityDecayRatio, "CumFertilityDecayRatio", CumFertilityDecayRatioDefault); + Scribe_Values.Look(ref CycleAcceleration, "CycleAcceleration", CycleAccelerationDefault); + Scribe_Values.Look(ref ColonistTickInterval, "ColonistTickInterval", ColonistTickIntervalDefault); + Scribe_Values.Look(ref NonColonistTickInterval, "NonColonistTickInterval", NonColonistTickIntervalDefault); + Scribe_Values.Look(ref AnimalTickInterval, "AnimalTickInterval", AnimalTickIntervalDefault); + Scribe_Values.Look(ref EnableWombIcon, "EnableWombIcon", true); + Scribe_Values.Look(ref EnableDraftedIcon, "EnableDraftedIcon", true); + Scribe_Values.Look(ref EnableAnimalCycle, "EnableAnimalCycle", false); + Scribe_Values.Look(ref DrawWombStatus, "DrawWombStatus", true); + Scribe_Values.Look(ref DrawVaginaStatus, "DrawVaginaStatus", true); + Scribe_Values.Look(ref DrawEggOverlay, "DrawEggOvray", true); + Scribe_Values.Look(ref Debug, "Debug", false); + Scribe_Values.Look(ref infoDetail, "InfoDetail", DetailLevel.All); + Scribe_Values.Look(ref EnableMenopause, "EnableMenopause", true); + Scribe_Values.Look(ref EnablePheromones, "EnablePheromones", true); + Scribe_Values.Look(ref AnimalPheromoneEffect, "AnimalPheromoneEffect", 0.0f); + Scribe_Values.Look(ref EstrusOverridesHookupSettings, "EstrusOverridesHookupSettings", false); + Scribe_Values.Look(ref EstrusFuckabilityToHookup, "EstrusFuckabilityToHookup", EstrusFuckabilityToHookup, true); + Scribe_Values.Look(ref EstrusAttractivenessToHookup, "EstrusAttractivenessToHookup", EstrusAttractivenessToHookup, true); + Scribe_Values.Look(ref EstrusRelationshipToHookup, "EstrusRelationshipToHookup", EstrusRelationshipToHookup, true); + Scribe_Values.Look(ref PregnancySource, "PregnancySource", PregnancyType.MultiplePregnancy); + Scribe_Values.Look(ref EnableBiotechTwins, "EnableBiotechTwins", false); + Scribe_Values.Look(ref EnableHeteroOvularTwins, "EnableHeteroOvularTwins", true); + Scribe_Values.Look(ref EnableEnzygoticTwins, "EnableEnzygoticTwins", true); + Scribe_Values.Look(ref EnzygoticTwinsChance, "EnzygoticTwinsChance", EnzygoticTwinsChanceDefault); + Scribe_Values.Look(ref EnzygoticTwinsChanceAdjust, "EnzygoticTwinsChanceAdjust", EnzygoticTwinsChanceAdjustDefault); + Scribe_Values.Look(ref MaxEnzygoticTwins, "MaxEnzygoticTwins", MaxEnzygoticTwinsDefault); + Scribe_Values.Look(ref BleedingAmount, "BleedingAmount", BleedingAmountDefault); + Scribe_Values.Look(ref EnableButtonInHT, "EnableButtonInHT", false); + Scribe_Values.Look(ref ShowFlag, "ShowFlag", PawnFlags.Colonist | PawnFlags.Prisoner); + Scribe_Values.Look(ref UseHybridExtention, "UseHybridExtention", true); + Scribe_Values.Look(ref MaxBreastIncrementFactor, "MaxBreastIncrementFactor", MaxBreastIncrementFactorDefault); + Scribe_Values.Look(ref MaxNippleIncrementFactor, "MaxNippleIncrementFactor", MaxNippleIncrementFactorDefault); + Scribe_Values.Look(ref PermanentNippleChange, "PermanentNippleChange", PermanentNippleChangeDefault); + Scribe_Values.Look(ref AllowShrinkIcon, "AllowShrinkIcon", false); + Scribe_Values.Look(ref EggLifespanMultiplier, "EggLifespanMultiplier", EggLifespanMultiplierDefault); + Scribe_Values.Look(ref EnableBirthVaginaMorph, "EnableBirthVaginaMorph", false); + Scribe_Values.Look(ref VaginaMorphPower, "VaginaMorphPower", VaginaMorphPowerDefault); + Scribe_Collections.Look(ref HybridOverride, saveDestroyedThings: true, label: "HybridOverride", lookMode: LookMode.Deep, ctorArgs: new object[0]); + base.ExposeData(); + } + + + + } + + + public class RJW_Menstruation : Mod + { + + private static Vector2 scroll; + + + + public static float EstimatedBleedingAmount + { + get + { + int days = VariousDefOf.HumanVaginaCompProperties.bleedingIntervalDays; + return days * 0.03f * Configurations.BleedingAmount * 6; + } + } + + public static float EstimatedBleedingAmountPerHour + { + get + { + return 0.03f * Configurations.BleedingAmount * Configurations.CycleAcceleration; + } + } + + + public RJW_Menstruation(ModContentPack content) : base(content) + { + GetSettings(); + if (!ModsConfig.BiotechActive && Configurations.PregnancySource == Configurations.PregnancyType.Biotech) + Configurations.PregnancySource = Configurations.PregnancyType.MultiplePregnancy; + Configurations.HARActivated = ModsConfig.IsActive("erdelf.HumanoidAlienRaces"); + Configurations.AnimalGeneticsActivated = ModsConfig.IsActive("Mlie.AnimalGenetics"); + } + + + + public override string SettingsCategory() + { + return Translations.Mod_Title; + } + + public override void DoSettingsWindowContents(Rect inRect) + { + Rect outRect = new Rect(0f, 30f, inRect.width, inRect.height - 30f); + float mainRectHeight = 126f + + (Configurations.EnableWombIcon || Configurations.EnableButtonInHT ? 400f : 0f) + + (Configurations.EnableAnimalCycle ? 48f : 0f) + + (Configurations.EnableAnimalCycle && Configurations.EnablePheromones ? 48f : 0f) + + (Configurations.EstrusOverridesHookupSettings ? 144f : 0f) + + (Configurations.PregnancySource == Configurations.PregnancyType.MultiplePregnancy ? (Configurations.EnableEnzygoticTwins ? 175f : 75f) : 0f) + + (Configurations.PregnancySource == Configurations.PregnancyType.Biotech ? 75f : 0f) + + (Configurations.PregnancySource == Configurations.PregnancyType.Biotech ? (Configurations.EnableBiotechTwins ? 175f : 75f) : 0f) + + (Configurations.EnableBirthVaginaMorph ? 48f : 0f); + Rect mainRect = new Rect(0f, 0f, inRect.width - 30f, Math.Max(inRect.height + mainRectHeight, 1f)); + int Adjust; + Listing_Standard listmain = new Listing_Standard + { + maxOneColumn = true + }; + Widgets.BeginScrollView(outRect, ref scroll, mainRect); + listmain.Begin(mainRect); + listmain.Gap(20f); + Rect firstLine = listmain.GetRect(30f); + firstLine.SplitVertically(firstLine.width / 3, out Rect leftCell, out Rect middleAndRightCells); + Widgets.CheckboxLabeled(leftCell, Translations.Option1_Label_1, ref Configurations.EnableWombIcon, false, null, null, true); + Widgets.CheckboxLabeled(middleAndRightCells.LeftHalf(), Translations.Option1_Label_2, ref Configurations.EnableButtonInHT, false, null, null, true); + if (Configurations.EnableWombIcon || Configurations.EnableButtonInHT) + { + Listing_Standard wombsection = listmain.BeginSection(380); + wombsection.CheckboxLabeled(Translations.Option9_Label, ref Configurations.DrawWombStatus, Translations.Option9_Desc); + if (Configurations.DrawWombStatus) + { + wombsection.CheckboxLabeled(Translations.Option18_Label, ref Configurations.DrawEggOverlay, Translations.Option18_Desc); + } + + wombsection.CheckboxLabeled(Translations.Option10_Label, ref Configurations.DrawVaginaStatus, Translations.Option10_Desc); + wombsection.CheckboxLabeled(Translations.Option29_Label, ref Configurations.AllowShrinkIcon, Translations.Option29_Desc); + wombsection.CheckboxLabeled(Translations.Option_EnableDraftedIcon_Label, ref Configurations.EnableDraftedIcon, Translations.Option_EnableDraftedIcon_Desc); + if (wombsection.ButtonText(Translations.Option11_Label + ": " + Configurations.LevelString(Configurations.infoDetail))) + { + if (Configurations.infoDetail == Configurations.DetailLevel.Hide) Configurations.infoDetail = Configurations.DetailLevel.All; + else Configurations.infoDetail++; + } + switch (Configurations.infoDetail) + { + case Configurations.DetailLevel.All: + wombsection.Label(Translations.Option11_Desc_1); + break; + case Configurations.DetailLevel.OnReveal: + wombsection.Label(Translations.Option11_Desc_2); + break; + case Configurations.DetailLevel.HideFetusInfo: + wombsection.Label(Translations.Option11_Desc_3); + break; + case Configurations.DetailLevel.Hide: + wombsection.Label(Translations.Option11_Desc_4); + break; + } + wombsection.Label(Translations.Option21_Label + " " + Configurations.ShowFlag, -1, Translations.Option21_Desc); + Rect flagrect = wombsection.GetRect(30f); + Rect[] flagrects = new Rect[5]; + for (int i = 0; i < 5; i++) + { + flagrects[i] = new Rect(flagrect.x + (flagrect.width / 5) * i, flagrect.y, flagrect.width / 5, flagrect.height); + } + + if (Widgets.ButtonText(flagrects[0], Translations.Option20_Label_1 + ": " + Configurations.ShowFlag.HasFlag(Configurations.PawnFlags.Colonist))) + { + Configurations.ShowFlag ^= Configurations.PawnFlags.Colonist; + } + if (Widgets.ButtonText(flagrects[1], Translations.Option20_Label_2 + ": " + Configurations.ShowFlag.HasFlag(Configurations.PawnFlags.Prisoner))) + { + Configurations.ShowFlag ^= Configurations.PawnFlags.Prisoner; + } + if (Widgets.ButtonText(flagrects[2], Translations.Option20_Label_3 + ": " + Configurations.ShowFlag.HasFlag(Configurations.PawnFlags.Ally))) + { + Configurations.ShowFlag ^= Configurations.PawnFlags.Ally; + } + if (Widgets.ButtonText(flagrects[3], Translations.Option20_Label_4 + ": " + Configurations.ShowFlag.HasFlag(Configurations.PawnFlags.Neutral))) + { + Configurations.ShowFlag ^= Configurations.PawnFlags.Neutral; + } + if (Widgets.ButtonText(flagrects[4], Translations.Option20_Label_5 + ": " + Configurations.ShowFlag.HasFlag(Configurations.PawnFlags.Hostile))) + { + Configurations.ShowFlag ^= Configurations.PawnFlags.Hostile; + } + + Adjust = (int)(Configurations.MaxBreastIncrementFactor * 1000 / Configurations.MaxBreastIncrementFactorMax); + wombsection.Label(Translations.Option_MaxBreastIncrementFactor_Label + " " + Configurations.MaxBreastIncrementFactor * 100 + "%", -1, Translations.Option_MaxBreastIncrementFactor_Desc); + Adjust = (int)wombsection.Slider(Adjust, 0, 1000); + Configurations.MaxBreastIncrementFactor = (float)Adjust / (1000 / Configurations.MaxBreastIncrementFactorMax); + + Adjust = (int)(Configurations.MaxNippleIncrementFactor * 1000 / Configurations.MaxNippleIncrementFactorMax); + wombsection.Label(Translations.Option_MaxNippleIncrementFactor_Label + " " + Configurations.MaxNippleIncrementFactor * 100 + "%", -1, Translations.Option_MaxNippleIncrementFactor_Desc); + Adjust = (int)wombsection.Slider(Adjust, 0, 1000); + Configurations.MaxNippleIncrementFactor = (float)Adjust / (1000 / Configurations.MaxNippleIncrementFactorMax); + + Adjust = (int)(Configurations.PermanentNippleChange * 1000 / Configurations.PermanentNippleChangeMax); + wombsection.Label(Translations.Option_PermanentNippleChange_Label + " " + Configurations.PermanentNippleChange, -1, Translations.Option_PermanentNippleChange_Desc); + Adjust = (int)wombsection.Slider(Adjust, 0, 1000); + Configurations.PermanentNippleChange = (float)Adjust / (1000 / Configurations.PermanentNippleChangeMax); + + listmain.EndSection(wombsection); + } + + listmain.CheckboxLabeled(Translations.Option2_Label, ref Configurations.EnableAnimalCycle, Translations.Option2_Desc); + + listmain.CheckboxLabeled(Translations.Option12_Label, ref Configurations.EnableMenopause, Translations.Option12_Desc); + + listmain.CheckboxLabeled(Translations.Option_EnablePheromones_Label, ref Configurations.EnablePheromones, Translations.Option_EnablePheromones_Desc); + if (Configurations.EnablePheromones && Configurations.EnableAnimalCycle) + { + Adjust = (int)(Configurations.AnimalPheromoneEffect * 1000); + listmain.Label(Translations.Option_AnimalPheromoneEffect_Label + " " + Configurations.AnimalPheromoneEffect * 100 + "%", -1, Translations.Option_AnimalPheromoneEffect_Desc); + Adjust = (int)listmain.Slider(Adjust, 0, 1000); + Configurations.AnimalPheromoneEffect = (float)Adjust / 1000f; + } + else Configurations.AnimalPheromoneEffect = 0.0f; + + listmain.Label(Translations.Option3_Label + " " + Configurations.ImplantationChance * 100 + "%", -1, Translations.Option3_Desc); + Configurations.ImplantationChanceAdjust = (int)listmain.Slider(Configurations.ImplantationChanceAdjust, 0, 1000); + Configurations.ImplantationChance = (float)Configurations.ImplantationChanceAdjust / 100; + + string tenMl = String.Format("10 ml: {0:0}%", (1.0f - Mathf.Pow(1.0f - Configurations.FertilizeChance, 10)) * 100f); + listmain.LabelDouble(Translations.Option4_Label + " " + Configurations.FertilizeChance * 100 + "%", tenMl, Translations.Option4_Desc); + Configurations.FertilizeChanceAdjust = (int)listmain.Slider(Configurations.FertilizeChanceAdjust, 0, 1000); + Configurations.FertilizeChance = (float)Configurations.FertilizeChanceAdjust / 1000; + + listmain.Label(Translations.Option5_Label + " " + Configurations.CumDecayRatio * 100 + "%", -1, Translations.Option5_Desc); + Configurations.CumDecayRatioAdjust = (int)listmain.Slider(Configurations.CumDecayRatioAdjust, 0, 1000); + Configurations.CumDecayRatio = (float)Configurations.CumDecayRatioAdjust / 1000; + + + Adjust = (int)(Configurations.EggLifespanMultiplier * 20); + float lifespan = (24f / Configurations.CycleAcceleration * Configurations.EggLifespanMultiplier); + listmain.LabelDouble(Translations.Option30_Label + " x" + Configurations.EggLifespanMultiplier, Translations.EstimatedEggLifespan + String.Format(": {0:0}h", (int)lifespan), Translations.Option30_Desc); + Adjust = (int)listmain.Slider(Adjust, 20, 1000); + Configurations.EggLifespanMultiplier = (float)Adjust / 20; + + + int semenlifespan = (int)(-5 / ((float)Math.Log10((1 - Configurations.CumFertilityDecayRatio) * (1 - Configurations.CumDecayRatio) * 10) - 1)) + 1; + string estimatedlifespan; + if (semenlifespan < 0) + { + estimatedlifespan = string.Format(": Infinite", semenlifespan); + } + else + { + estimatedlifespan = string.Format(": {0:0}h", semenlifespan); + } + listmain.LabelDouble(Translations.Option6_Label + " " + Configurations.CumFertilityDecayRatio * 100 + "%", Translations.EstimatedCumLifespan + estimatedlifespan, Translations.Option6_Desc); + Configurations.CumFertilityDecayRatioAdjust = (int)listmain.Slider(Configurations.CumFertilityDecayRatioAdjust, 0, 1000); + Configurations.CumFertilityDecayRatio = (float)Configurations.CumFertilityDecayRatioAdjust / 1000; + + listmain.Label(Translations.Option7_Label + " x" + Configurations.CycleAcceleration, -1, Translations.Option7_Desc); + Configurations.CycleAcceleration = (int)listmain.Slider(Configurations.CycleAcceleration, 1, 50); + + listmain.LabelDouble(Translations.Option_ColonistUpdateInterval_Label, GenDate.ToStringTicksToPeriod(Configurations.ColonistTickInterval), Translations.Option_ColonistUpdateInterval_Desc); + Configurations.ColonistTickInterval = (int)Mathf.Exp(listmain.Slider(Mathf.Log(Configurations.ColonistTickInterval), Mathf.Log(Configurations.TickIntervalMinimum), Mathf.Log(Configurations.TickIntervalMaximum))); + + listmain.LabelDouble(Translations.Option_NonColonistUpdateInterval_Label, GenDate.ToStringTicksToPeriod(Configurations.NonColonistTickInterval), Translations.Option_NonColonistUpdateInterval_Desc); + Configurations.NonColonistTickInterval = (int)Mathf.Exp(listmain.Slider(Mathf.Log(Configurations.NonColonistTickInterval), Mathf.Log(Configurations.TickIntervalMinimum), Mathf.Log(Configurations.TickIntervalMaximum))); + + if(Configurations.EnableAnimalCycle) + { + listmain.LabelDouble(Translations.Option_AnimalUpdateInterval_Label, GenDate.ToStringTicksToPeriod(Configurations.AnimalTickInterval), Translations.Option_AnimalUpdateInterval_Desc); + Configurations.AnimalTickInterval = (int)Mathf.Exp(listmain.Slider(Mathf.Log(Configurations.AnimalTickInterval), Mathf.Log(Configurations.TickIntervalMinimum), Mathf.Log(Configurations.TickIntervalMaximum))); + } + + float var2 = EstimatedBleedingAmountPerHour; + float var1 = Math.Max(EstimatedBleedingAmount, var2); + listmain.LabelDouble(Translations.Option19_Label_1, Translations.Option19_Label_2 + ": " + var1 + "ml, " + var2 + "ml/h", Translations.Option19_Desc); + Configurations.BleedingAmount = (int)listmain.Slider(Configurations.BleedingAmount, 0, 200); + + listmain.CheckboxLabeled(Translations.Option_EstrusOverride_Label, ref Configurations.EstrusOverridesHookupSettings, Translations.Option_EstrusOverride_Desc); + if (Configurations.EstrusOverridesHookupSettings) + { + listmain.Label(Translations.Option_EstrusFuckability_Label + ": " + (int)(Configurations.EstrusFuckabilityToHookup * 100) + "%"); + Configurations.EstrusFuckabilityToHookup = listmain.Slider(Configurations.EstrusFuckabilityToHookup, 0.1f, 1.0f); + listmain.Label(Translations.Option_EstrusAttractability_Label + ": " + (int)(Configurations.EstrusAttractivenessToHookup * 100) + "%"); + Configurations.EstrusAttractivenessToHookup = listmain.Slider(Configurations.EstrusAttractivenessToHookup, 0.0f, 1.0f); + listmain.Label(Translations.Option_EstrusRelationship_Label + ": " + Configurations.EstrusRelationshipToHookup); + Configurations.EstrusRelationshipToHookup = listmain.Slider((int)Configurations.EstrusRelationshipToHookup, -100f, 100f); + } + + if (listmain.RadioButton(Translations.Option_PregnancyFromBaseRJW_Label, Configurations.PregnancySource == Configurations.PregnancyType.BaseRJW)) + Configurations.PregnancySource = Configurations.PregnancyType.BaseRJW; + if (listmain.RadioButton(Translations.Option_PregnancyFromMultiplePregnancy_Label, Configurations.PregnancySource == Configurations.PregnancyType.MultiplePregnancy)) + Configurations.PregnancySource = Configurations.PregnancyType.MultiplePregnancy; + if (ModsConfig.BiotechActive && listmain.RadioButton(Translations.Option_PregnancyFromBiotech_Label, Configurations.PregnancySource == Configurations.PregnancyType.Biotech)) + Configurations.PregnancySource = Configurations.PregnancyType.Biotech; + if (Configurations.PregnancySource == Configurations.PregnancyType.Biotech) + listmain.CheckboxLabeled(Translations.Option_EnableBiotechTwins_Label, ref Configurations.EnableBiotechTwins, Translations.Option_EnableBiotechTwins_Desc); + if (Configurations.PregnancySource == Configurations.PregnancyType.MultiplePregnancy || + (Configurations.PregnancySource == Configurations.PregnancyType.Biotech && Configurations.EnableBiotechTwins)) + { + float sectionheight = 75f; + if (Configurations.EnableEnzygoticTwins) sectionheight += 100; + Listing_Standard twinsection = listmain.BeginSection(sectionheight); + Rect hybridrect = twinsection.GetRect(25); + Widgets.CheckboxLabeled(hybridrect.LeftHalf(), Translations.Option22_Label, ref Configurations.UseHybridExtention, false, null, null, true); + if (Widgets.ButtonText(hybridrect.RightHalf(), Translations.Option28_Label)) + { + Dialog_HybridCustom.ToggleWindow(); + //Configurations.MotherFirst = !Configurations.MotherFirst; + } + TooltipHandler.TipRegion(hybridrect, Translations.Option28_Tooltip); + + twinsection.CheckboxLabeled(Translations.Option14_Label, ref Configurations.EnableHeteroOvularTwins, Translations.Option14_Desc); + twinsection.CheckboxLabeled(Translations.Option15_Label, ref Configurations.EnableEnzygoticTwins, Translations.Option15_Desc); + if (Configurations.EnableEnzygoticTwins) + { + twinsection.Label(Translations.Option16_Label + " " + Configurations.EnzygoticTwinsChance * 100 + "%", -1, Translations.Option16_Desc); + Configurations.EnzygoticTwinsChanceAdjust = (int)twinsection.Slider(Configurations.EnzygoticTwinsChanceAdjust, 0, 1000); + Configurations.EnzygoticTwinsChance = (float)Configurations.EnzygoticTwinsChanceAdjust / 1000; + + twinsection.Label(Translations.Option17_Label + " " + Configurations.MaxEnzygoticTwins, -1, Translations.Option17_Desc); + Configurations.MaxEnzygoticTwins = (int)twinsection.Slider(Configurations.MaxEnzygoticTwins, 2, 100); + } + listmain.EndSection(twinsection); + } + + listmain.CheckboxLabeled(Translations.Option31_Label, ref Configurations.EnableBirthVaginaMorph, Translations.Option31_Desc); + if (Configurations.EnableBirthVaginaMorph) + { + float sectionheight = 48f; + Listing_Standard vmsection = listmain.BeginSection(sectionheight); + + LabelwithTextfield(vmsection.GetRect(24f), Translations.Option32_Label, Translations.Option32_Desc, ref Configurations.VaginaMorphPower, 0, 100f); + Adjust = (int)(Configurations.VaginaMorphPower * 1000); + Adjust = (int)vmsection.Slider(Adjust, 0, 1000); + Configurations.VaginaMorphPower = Adjust / 1000f; + + + listmain.EndSection(vmsection); + } + + listmain.CheckboxLabeled(Translations.Option8_Label, ref Configurations.Debug, Translations.Option8_Desc); + if (listmain.ButtonText(Translations.Button_ResetToDefault)) + { + Configurations.SetToDefault(); + } + + listmain.End(); + Widgets.EndScrollView(); + } + + + public void LabelwithTextfield(Rect rect, string label, string tooltip, ref float value, float min, float max) + { + Rect textfieldRect = new Rect(rect.xMax - 100f, rect.y, 100f, rect.height); + string valuestr = value.ToString(); + Widgets.Label(rect, label); + Widgets.TextFieldNumeric(textfieldRect, ref value, ref valuestr, min, max); + Widgets.DrawHighlightIfMouseover(rect); + TooltipHandler.TipRegion(rect, tooltip); + } + + + } + + + + +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Cum.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Cum.cs new file mode 100644 index 0000000..60394b0 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Cum.cs @@ -0,0 +1,279 @@ +using RimWorld; +using System; +using System.Collections.Generic; +using System.Text; +using UnityEngine; +using Verse; + +namespace RJW_Menstruation +{ + public class Cum : IExposable + { + public Pawn pawn; + + protected float volume; // ml + public float fertility = 1.0f; + public bool notcum = false; // for other fluids + public string notcumLabel = ""; + protected bool useCustomColor = false; + protected float notcumthickness = 0; + protected float cumthickness = 1.0f; + protected Thing internalThing; + + public float Volume + { + get + { + return volume; + } + } + + public float FertVolume + { + get + { + return volume * fertility; + } + } + + public float CumThickness + { + get + { + return cumthickness; + } + } + + public float DecayResist + { + get + { + if (!notcum) return DNA.cumThickness; + else return notcumthickness; + } + set + { + notcumthickness = value; + } + } + protected Color customColor; + + public PawnDNAModExtension DNA + { + get + { + if (DNAcache != null) return DNAcache; + try + { + DNAcache = pawn.def.GetModExtension(); + } + catch (NullReferenceException) + { + DNAcache = ThingDefOf.Human.GetModExtension(); + } + if (DNAcache == null) + { + DNAcache = ThingDefOf.Human.GetModExtension(); + } + return DNAcache; + } + } + protected PawnDNAModExtension DNAcache = null; + public ThingDef FilthDef + { + get + { + if (filthDef == null) return VariousDefOf.CumFilth; + else return filthDef; + } + set + { + filthDef = value; + } + } + protected ThingDef filthDef = null; + public Color Color + { + get + { + if (!useCustomColor) return DNA.CumColor; + else return customColor; + } + + set + { + useCustomColor = true; + customColor = value; + } + } + + public Thing CumThing + { + get + { + if (internalThing == null) + { + internalThing = ThingMaker.MakeThing(VariousDefOf.CumFilth); + internalThing.stackCount = (int)volume; + } + internalThing.stackCount = (int)volume; + return internalThing; + } + } + + public Cum() { } + + public Cum(Pawn pawn) + { + this.pawn = pawn; + volume = 1.0f; + fertility = 1.0f; + } + + /// + /// Not Cum + /// + /// + /// + /// + /// + /// + public Cum(Pawn pawn, float volume, string notcumlabel, float decayresist = 0, ThingDef filthDef = null) + { + this.pawn = pawn; + this.volume = volume; + this.fertility = 0f; + this.notcum = true; + this.notcumLabel = notcumlabel; + this.notcumthickness = decayresist; + this.filthDef = filthDef; + } + + public Cum(Pawn pawn, float volume, float fertility, ThingDef filthDef = null) + { + this.pawn = pawn; + this.volume = volume; + this.fertility = fertility; + this.filthDef = filthDef; + } + + + + public virtual void ExposeData() + { + Scribe_References.Look(ref pawn, "pawn", true); + Scribe_Values.Look(ref volume, "volume", volume, true); + Scribe_Values.Look(ref fertility, "fertility", fertility, true); + Scribe_Values.Look(ref notcumthickness, "notcumthickness", 0); + Scribe_Values.Look(ref notcum, "notcum", false); + Scribe_Values.Look(ref notcumLabel, "notcumLabel", ""); + Scribe_Values.Look(ref useCustomColor, "useCustomColor", false); + Scribe_Values.Look(ref customColor, "customColor", default); + Scribe_Defs.Look(ref filthDef, "filthDef"); + } + + public void MakeThinner(float speed) + { + cumthickness = cumthickness.LerpMultiple(DecayResist, 0.3f, speed); + } + + public void MergeWithCum(float volumein, float fertility, ThingDef updatefilthDef = null) + { + if (updatefilthDef != null) filthDef = updatefilthDef; + volume += volumein; + this.fertility = (this.volume * this.fertility + volumein * fertility) / (this.volume + volumein); + cumthickness = Mathf.Lerp(cumthickness, 1.0f, volumein / volume); + } + + public void MergeWithFluid(float volumein, float thickness, ThingDef updatefilthDef = null) + { + if (updatefilthDef != null) filthDef = updatefilthDef; + volume += volumein; + fertility = volume * fertility / (volume + volumein); + notcumthickness = Mathf.Lerp(notcumthickness, thickness, volumein / volume); + } + + public bool ShouldRemove() + { + if ((notcum || FertVolume < 0.001f) && volume < 0.01f) return true; + return false; + } + + public float DismishNatural(float leakfactor, HediffComp_Menstruation comp, float antisperm = 0.0f) + { + // comp is used for Hydrogen's RJW Muscle Injury + float totalleak = volume; + float decayPerInterval = 1 - Mathf.Pow(1 - Configurations.CumDecayRatio, comp.HoursBetweenSimulations); + float fertilityDecayPerInterval = 1 - Mathf.Pow(1 - Configurations.CumFertilityDecayRatio, comp.HoursBetweenSimulations); + antisperm *= comp.HoursBetweenSimulations; + volume *= Math.Max(0, 1 - decayPerInterval * (1 - DecayResist) * leakfactor); + fertility *= Math.Max(0, 1 - (fertilityDecayPerInterval * (1 - DecayResist) + antisperm)); + CutMinor(); + totalleak -= volume; + return totalleak; + } + + public float DismishForce(float portion, float leakfactor = 1.0f) + { + float totalleak = volume; + volume *= Math.Max(0, 1 - (portion * (1 - DecayResist / 10)) * leakfactor); + CutMinor(); + totalleak -= volume; + return totalleak; + } + + public void CumEffects(Pawn pawn) + { + if (notcum || DNA?.ingestionOutcomeDoers == null || volume < 1.0f) return; + + foreach (IngestionOutcomeDoer doer in DNA.ingestionOutcomeDoers) + doer.DoIngestionOutcome(pawn, CumThing); + } + + protected void CutMinor() + { + if (volume < 0.01f) volume = 0f; + } + } + + public class CumMixture : Cum + { + protected List cums; + public bool ispurecum = true; + public List Getingredients => cums; + + public CumMixture() + { + notcum = true; + cums = new List(); + } + + public CumMixture(Pawn pawn, float volume, List cums, Color color, ThingDef mixtureDef, bool pure) + { + this.pawn = pawn; + this.volume = volume; + this.cums = cums; + this.customColor = color; + this.useCustomColor = true; + ispurecum = pure; + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Collections.Look(ref cums, "cumslabel", LookMode.Value, new object[0]); + } + + public string GetIngredients() + { + StringBuilder res = new StringBuilder(); + + if (!cums.NullOrEmpty()) for (int i = 0; i < cums.Count; i++) + { + res.Append(cums[i]); + if (i < cums.Count - 1) res.Append(", "); + } + return res.ToString(); + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/DebugActions.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/DebugActions.cs new file mode 100644 index 0000000..55f34db --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/DebugActions.cs @@ -0,0 +1,90 @@ +using RimWorld; +using Verse; + +#pragma warning disable IDE0051 // Remove unused private members +namespace RJW_Menstruation +{ + public static class DebugToolsMenstruation + { + [DebugAction("RJW Menstruation", "Set pawn's state to follicular", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] + private static void SetFollicular(Pawn p) + { + foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) + { + comp.GoNextStage(HediffComp_Menstruation.Stage.Follicular); + comp.RemoveAllEggs(); + } + Messages.Message($"{p} is now follicular", p, MessageTypeDefOf.NeutralEvent, false); + } + + [DebugAction("RJW Menstruation", "Set pawn's state to ovulatory", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] + private static void SetOvulatory(Pawn p) + { + foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) + comp.GoNextStage(HediffComp_Menstruation.Stage.Ovulatory); + Messages.Message($"{p} is now ovulatory", p, MessageTypeDefOf.NeutralEvent, false); + } + + [DebugAction("RJW Menstruation", "Set pawn's state to luteal", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] + private static void SetLuteal(Pawn p) + { + foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) + comp.GoNextStage(HediffComp_Menstruation.Stage.Luteal); + Messages.Message($"{p} is now luteal", p, MessageTypeDefOf.NeutralEvent, false); + } + + [DebugAction("RJW Menstruation", "Set pawn's state to bleeding", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] + private static void SetBleeding(Pawn p) + { + foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) + { + comp.GoNextStage(HediffComp_Menstruation.Stage.Bleeding); + comp.RemoveAllEggs(); + } + Messages.Message($"{p} is now bleeding", p, MessageTypeDefOf.NeutralEvent, false); + } + /* + [DebugAction("RJW Menstruation", "Set pawn's state to recovering", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] + private static void setRecover(Pawn p) + { + p.GetMenstruationComp().curStage = HediffComp_Menstruation.Stage.Recover; + } + + [DebugAction("RJW Menstruation", "Set pawn's state to young", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] + private static void setYoung(Pawn p) + { + p.GetMenstruationComp().curStage = HediffComp_Menstruation.Stage.Young; + } + */ + [DebugAction("RJW Menstruation", "Remove all cum from pawn's womb", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] + private static void RemoveCums(Pawn p) + { + foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) + comp.RemoveAllCums(); + Messages.Message($"All cum removed from {p}'s womb", p, MessageTypeDefOf.NeutralEvent, false); + } + [DebugAction("RJW Menstruation", "Remove all eggs from pawn's womb", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] + private static void RemoveEggs(Pawn p) + { + foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) + comp.RemoveAllEggs(); + Messages.Message($"All eggs removed from {p}'s womb", p, MessageTypeDefOf.NeutralEvent, false); + } + [DebugAction("RJW Menstruation", "Add egg to pawn's next ovulation", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] + private static void AddEgg(Pawn p) + { + foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) + comp.eggstack++; + Messages.Message($"1 egg added to {p}'s next ovulation ({p.GetFirstMenstruationComp().eggstack})", p, MessageTypeDefOf.NeutralEvent, false); + } + + [DebugAction("RJW Menstruation", "Recalculate pawn's ovary power", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)] + private static void RecalculateOvaryPower(Pawn p) + { + foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) + comp.ovarypower = comp.GetOvaryPowerByAge(); + Messages.Message($"{p}'s ovarypower recalculated ({p.GetFirstMenstruationComp().ovarypower})", p, MessageTypeDefOf.NeutralEvent, false); + } + } +} +#pragma warning restore IDE0051 // Remove unused private members \ No newline at end of file diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/DrugOutcomeDoers.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/DrugOutcomeDoers.cs new file mode 100644 index 0000000..5017740 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/DrugOutcomeDoers.cs @@ -0,0 +1,95 @@ +using RimWorld; +using System.Collections.Generic; +using Verse; + +namespace RJW_Menstruation +{ + public class FertPillOutcomeDoer : IngestionOutcomeDoer + { + protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) + { + foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps()) + if (comp.curStage.Equals(HediffComp_Menstruation.Stage.Follicular) + || comp.curStage.Equals(HediffComp_Menstruation.Stage.Luteal) + || comp.curStage.Equals(HediffComp_Menstruation.Stage.Anestrus) + ) + { + comp.SetEstrus(); + comp.GoNextStage(HediffComp_Menstruation.Stage.Ovulatory); + comp.ovarypower--; + } + } + } + + public class InduceOvulationOutcomeDoer : IngestionOutcomeDoer + { + protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) + { + foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps()) + if (comp.curStage.Equals(HediffComp_Menstruation.Stage.Follicular) + || comp.curStage.Equals(HediffComp_Menstruation.Stage.Anestrus) + ) + { + comp.SetEstrus(); + comp.GoNextStage(HediffComp_Menstruation.Stage.Ovulatory); + comp.eggstack += ingested.stackCount - 1; + } + } + } + + public class IngestionOutcomeDoer_AdjustSeverity : IngestionOutcomeDoer + { + public HediffDef hediffDef; + public float severity; + + protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) + { + Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(hediffDef); + if (hediff != null) hediff.Severity += severity; + } + + } + + public class OvaryPillOutcomeDoer : IngestionOutcomeDoer + { + public float effectOffset; + + + protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) + { + foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps()) + if (Configurations.EnableMenopause) comp.RecoverOvary(1 + effectOffset); + } + } + + public class SuperOvulationOutcomeDoer : IngestionOutcomeDoer + { + protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) + { + foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps()) + comp.eggstack += Rand.Range(1, 4); + } + } + + public class ContraceptiveOutcomeDoer : IngestionOutcomeDoer + { + protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) + { + + List memories = pawn.needs?.mood?.thoughts?.memories?.Memories.FindAll( + x => + x.def == VariousDefOf.CameInsideF + || x.def == VariousDefOf.CameInsideFFetish + || x.def == VariousDefOf.HaterCameInsideF); + if (memories.NullOrEmpty()) return; + foreach (Thought_Memory m in memories) + { + if (m.def == VariousDefOf.HaterCameInsideF) m.moodPowerFactor = 0.5f; + else m.moodPowerFactor = 0.3f; + + } + if (pawn.IsProPregnancy(out _)) pawn.needs.mood.thoughts.memories.TryGainMemoryFast(VariousDefOf.HateTookContraceptivePill); + else pawn.needs.mood.thoughts.memories.TryGainMemoryFast(VariousDefOf.TookContraceptivePill); + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/EstrusPartKindUsageRule.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/EstrusPartKindUsageRule.cs new file mode 100644 index 0000000..3062feb --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/EstrusPartKindUsageRule.cs @@ -0,0 +1,40 @@ +using rjw; +using rjw.Modules.Interactions.Contexts; +using rjw.Modules.Interactions.Enums; +using rjw.Modules.Interactions.Rules.PartKindUsageRules; +using rjw.Modules.Shared; +using System.Collections.Generic; +using Verse; + +namespace RJW_Menstruation.Interactions +{ + public class EstrusPartKindUsageRule : IPartPreferenceRule + { + private const float visible_estrus_multiplier = Multipliers.Doubled; + private const float concealed_estrus_multiplier = 1.1f; + + private bool WillingAndAble(Pawn fucker, Pawn fucked, bool visible) + { + return + fucked.IsInEstrus(visible) + && + PregnancyHelper.CanImpregnate(fucker, fucked); + } + + public IEnumerable> ModifiersForDominant(InteractionContext context) + { + if (WillingAndAble(context.Internals.Submissive.Pawn, context.Internals.Dominant.Pawn, true)) + yield return new Weighted(visible_estrus_multiplier, LewdablePartKind.Vagina); + else if (WillingAndAble(context.Internals.Submissive.Pawn, context.Internals.Dominant.Pawn, false)) + yield return new Weighted(concealed_estrus_multiplier, LewdablePartKind.Vagina); + } + + public IEnumerable> ModifiersForSubmissive(InteractionContext context) + { + if (WillingAndAble(context.Internals.Dominant.Pawn, context.Internals.Submissive.Pawn, true)) + yield return new Weighted(visible_estrus_multiplier, LewdablePartKind.Vagina); + else if (WillingAndAble(context.Internals.Dominant.Pawn, context.Internals.Submissive.Pawn, false)) + yield return new Weighted(concealed_estrus_multiplier, LewdablePartKind.Vagina); + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/FilthMaker_Colored.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/FilthMaker_Colored.cs new file mode 100644 index 0000000..fbb4723 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/FilthMaker_Colored.cs @@ -0,0 +1,56 @@ +using RimWorld; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Verse; + +namespace RJW_Menstruation +{ + public class FilthMaker_Colored + { + + public static bool TryMakeFilth(IntVec3 c, Map map, ThingDef filthDef, IEnumerable sources, Color color, bool shouldPropagate, FilthSourceFlags additionalFlags = FilthSourceFlags.None) + { + Filth_Colored filth = (Filth_Colored)(from t in c.GetThingList(map) + where t.def == filthDef + select t).FirstOrDefault(); + if (!c.Walkable(map) || (filth != null && !filth.CanBeThickened)) + { + if (shouldPropagate) + { + List list = GenAdj.AdjacentCells8WayRandomized(); + for (int i = 0; i < 8; i++) + { + IntVec3 c2 = c + list[i]; + if (c2.InBounds(map) && TryMakeFilth(c2, map, filthDef, sources, color, false, FilthSourceFlags.None)) + { + return true; + } + } + } + filth?.AddSources(sources); + return false; + } + if (filth != null) + { + filth.ThickenFilth(); + filth.AddSources(sources); + } + else + { + if (!FilthMaker.CanMakeFilth(c, map, filthDef, additionalFlags)) + { + return false; + } + Filth_Colored filth2 = (Filth_Colored)ThingMaker.MakeThing(filthDef, null); + filth2.DrawColor = color; + filth2.AddSources(sources); + GenSpawn.Spawn(filth2, c, map, WipeMode.Vanish); + } + //FilthMonitor.Notify_FilthSpawned(); + return true; + } + + + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Breast.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Breast.cs new file mode 100644 index 0000000..eacab7d --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Breast.cs @@ -0,0 +1,395 @@ +using RimWorld; +using RimWorld.Planet; +using rjw; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Verse; + +namespace RJW_Menstruation +{ + public class CompProperties_Breast : HediffCompProperties + { + public static readonly ColorInt DefaultBlacknippleColor = new ColorInt(55, 20, 0); + public string BreastTex = "Breasts/Breast"; + public ColorInt BlacknippleColor = new ColorInt(55, 20, 0); + + + public Color BlackNippleColor + { + get + { + return BlacknippleColor.ToColor; + } + } + + + public CompProperties_Breast() + { + compClass = typeof(HediffComp_Breast); + } + } + + public class HediffComp_Breast : HediffComp + { + public const int tickInterval = GenDate.TicksPerHour * 3 / 2; + public const float breastGrowthStart = 1f / 6f; + public const float breastGrowthEnd = 1f / 3f; + public static readonly SimpleCurve nippleTransitions = new SimpleCurve() + { + new CurvePoint(0f,0f), + new CurvePoint(0.1f,0f), + new CurvePoint(0.333f,0.167f), + new CurvePoint(0.667f,0.833f), + new CurvePoint(1.0f,1.0f) + }; + public const float nippleChange = 0.2f; + + public CompProperties_Breast Props; + + protected long ageOfLastBirth = 0; + protected float maxBreastIncrement = -1f; + protected float breastSizeIncreased = 0f; + protected string debugGrowthStatus = "(Growth/shrink not yet calculated; run for 1.5h to update)"; + protected float nippleProgress = 0f; + protected float baseAlpha = -1f; // Will grow in response to pregnancy + protected float baseAreola = -1f; + protected float baseNipple = -1f; + protected float cachedAlpha = -1f; // Calculated dynamically instead of saved + protected float cachedAreola = -1f; // Actual size = these * breast size + protected float cachedNipple = -1f; + protected float babyHalfAge = -1f; + + protected Color cachedColor; + protected bool loaded = false; + + protected float BabyHalfAge + { + get + { + if (babyHalfAge > 0f) return babyHalfAge; + List ages = Pawn.RaceProps.lifeStageAges; + if (ages?.Count > 1) + babyHalfAge = ages[1].minAge / 2; + + if (babyHalfAge <= 0) babyHalfAge = 1.2f / 2; // Default to human + + return babyHalfAge; + } + } + + protected void ShrinkBreasts() + { + // The natural rate will take them from full to empty during the second half of their child's babyhood + float shrinkRate = tickInterval * MaxBreastIncrement / (BabyHalfAge * GenDate.TicksPerYear); + float shrinkAmount = Mathf.Min(shrinkRate, breastSizeIncreased); + breastSizeIncreased -= shrinkAmount; + parent.Severity -= shrinkAmount; + } + + protected float MaxBreastIncrement + { + get + { + return maxBreastIncrement * Configurations.MaxBreastIncrementFactor; + } + } + + public Color NippleColor + { + get + { + return cachedColor; + } + } + public float Alpha + { + get + { + return cachedAlpha; + } + } + public float NippleSize + { + get + { + return cachedNipple * parent.Severity; + } + } + public float AreolaSize + { + get + { + return cachedAreola * parent.Severity; + } + } + + public float BreastSizeIncreased + { + get + { + return breastSizeIncreased; + } + } + + public override void CompExposeData() + { + base.CompExposeData(); + + Scribe_Values.Look(ref ageOfLastBirth, "ageOfLastBirth", -1); + Scribe_Values.Look(ref maxBreastIncrement, "maxBreastIncrement", maxBreastIncrement, true); + Scribe_Values.Look(ref breastSizeIncreased, "breastSizeIncreased", 0.0f); + Scribe_Values.Look(ref nippleProgress, "nippleProgress", 0.0f); + Scribe_Values.Look(ref baseAlpha, "baseAlpha", baseAlpha, true); + Scribe_Values.Look(ref baseAreola, "baseAreola", baseAreola, true); + Scribe_Values.Look(ref baseNipple, "baseNipple", baseNipple, true); + if (Scribe.mode == LoadSaveMode.PostLoadInit) + Initialize(); + } + + public bool ShouldSimulate() + { + if (!Pawn.ShouldCycle()) return false; + if (Pawn.SpawnedOrAnyParentSpawned || Pawn.IsCaravanMember() || PawnUtility.IsTravelingInTransportPodWorldObject(Pawn)) return true; + + return false; + } + + public override void CompPostTick(ref float severityAdjustment) + { + base.CompPostTick(ref severityAdjustment); + // If an exception makes it out, RW will remove the hediff, so catch it here + try + { + if ( + !Pawn.IsHashIntervalTick(tickInterval) || + !ShouldSimulate() + ) + { + return; + } + CalculateBreastSize(); + CalculateNipples(); + UpdateNipples(); + } + catch (Exception ex) + { + Log.Error($"Error processing breasts of {Pawn}: {ex}"); + } + + } + + public override void CompPostPostAdd(DamageInfo? dinfo) + { + if (!loaded) Initialize(); + if (ageOfLastBirth > Pawn.ageTracker.AgeChronologicalTicks) ageOfLastBirth = CalculateLastBirth(); // catch transplant issues + } + + public override void CompPostPostRemoved() + { + if (Pawn.health.hediffSet.hediffs.Contains(parent)) + { + Log.Warning($"Attempted to remove breast comp from wrong pawn ({Pawn})."); + return; + } + base.CompPostPostRemoved(); + } + + protected long CalculateLastBirth() + { + long youngestAge = -1; + + if ((Pawn.relations == null)) return youngestAge; + + List rjwPregnancies = new List(); + Pawn.health.hediffSet.GetHediffs(ref rjwPregnancies); + + bool hasChild = Pawn.relations.Children. + Where(child => !rjwPregnancies.Any(preg => preg.babies.Contains(child))). // no fetuses + Where(child => child.GetMother() == Pawn). // not Dad + TryMinBy(child => child.ageTracker.AgeBiologicalTicks, out Pawn youngest); + + if (hasChild) youngestAge = Math.Max(Pawn.ageTracker.AgeBiologicalTicks - youngest.ageTracker.AgeBiologicalTicks, -1); + + return youngestAge; + } + + public void Initialize() + { + Props = (CompProperties_Breast)props; + + if (maxBreastIncrement <= 0f) + { + maxBreastIncrement = Utility.RandGaussianLike(0.088f, 0.202f); + } + if (ageOfLastBirth == 0 || ageOfLastBirth < -1) + { + ageOfLastBirth = CalculateLastBirth(); + } + if (baseAlpha <= 0f) + { + baseAlpha = Utility.RandGaussianLike(0.0f, 0.3f) + Rand.Range(0.0f, 0.5f); + } + if (baseAreola <= 0f) + { + baseAreola = Utility.RandGaussianLike(0.0f, 1.0f); + } + if (baseNipple <= 0f) + { + baseNipple = Utility.RandGaussianLike(0.0f, 1.0f); + } + UpdateNipples(); + loaded = true; + } + + protected void CalculateBreastSize() + { + // Ageless pawns can't depend on the chrono age, so just disable their growth entirely + if (Pawn.ageTracker.BiologicalTicksPerTick <= 0f && breastSizeIncreased > 0) + { + ShrinkBreasts(); + debugGrowthStatus = "Base size (ageless)"; + } + // The youngest child is less than halfway into babyhood: Full size + else if (ageOfLastBirth > 0 && ageOfLastBirth + BabyHalfAge * GenDate.TicksPerYear > Pawn.ageTracker.AgeBiologicalTicks) + { + debugGrowthStatus = "Full size due to young child"; + if (breastSizeIncreased < MaxBreastIncrement) + { + parent.Severity += (MaxBreastIncrement - breastSizeIncreased); + breastSizeIncreased = MaxBreastIncrement; + } + } + // Pregnant, grow in the second half of first trimester + else if (Pawn.IsRJWPregnant() || Pawn.IsBiotechPregnant()) + { + float pregnancySize = Mathf.InverseLerp(breastGrowthStart, breastGrowthEnd, Pawn.GetFarthestPregnancyProgress()) * MaxBreastIncrement; + if (breastSizeIncreased > pregnancySize) + { + debugGrowthStatus = "Shrinking due to being oversize for pregnancy"; + // Breasts still large from the last kid + ShrinkBreasts(); + } + else if (breastSizeIncreased < MaxBreastIncrement) + { + // Time to grow + float growAmount = pregnancySize - breastSizeIncreased; + if (growAmount != 0) + debugGrowthStatus = "Growing due to pregnancy"; + else + debugGrowthStatus = "Pregnant, but not time to grow"; + breastSizeIncreased += growAmount; + parent.Severity += growAmount; + } + else debugGrowthStatus = "Pregnant and full size"; + } + // Not (or very early) pregnant and youngest child nonexistent or more than halfway into babyhood, time to shrink + else if (breastSizeIncreased > 0) + { + debugGrowthStatus = "Shrinking due to no pregnancy nor young child"; + ShrinkBreasts(); + } + else debugGrowthStatus = "Base size"; + } + + protected void CalculateNipples() + { + float newNippleProgress; + if (Pawn.ageTracker.BiologicalTicksPerTick <= 0f) + newNippleProgress = 0f; + else if (ageOfLastBirth > 0 && ageOfLastBirth + BabyHalfAge * GenDate.TicksPerYear > Pawn.ageTracker.AgeBiologicalTicks) + newNippleProgress = 1f; + else if (Pawn.IsRJWPregnant() || Pawn.IsBiotechPregnant()) + newNippleProgress = nippleTransitions.Evaluate(Pawn.GetFarthestPregnancyProgress()); + else + newNippleProgress = 0f; + + if (newNippleProgress < 0) newNippleProgress = 0; + + if (newNippleProgress == nippleProgress) return; // Nothing to change + else if (newNippleProgress > nippleProgress) + { + float progressDifference = newNippleProgress - nippleProgress; + // All nipple growth has a slight effect on the base + // Not mathematically precise in hitting the goal at the end of the term, but close enough + baseAlpha *= 1.0f + progressDifference * Configurations.PermanentNippleChange; + if (baseAlpha > 1.0f) baseAlpha = 1.0f; + baseAreola *= 1.0f + progressDifference * Configurations.PermanentNippleChange; + if (baseAreola > 1.0f) baseAreola = 1.0f; + baseNipple *= 1.0f + progressDifference * Configurations.PermanentNippleChange; + if (baseNipple > 1.0f) baseNipple = 1.0f; + nippleProgress = newNippleProgress; + } + else + { + nippleProgress -= tickInterval / (BabyHalfAge * GenDate.TicksPerYear); + if (nippleProgress < newNippleProgress) nippleProgress = newNippleProgress; + } + } + + public void GaveBirth() + { + ageOfLastBirth = Pawn.ageTracker.AgeBiologicalTicks; + } + + public void AdjustNippleProgress(float amount) + { + nippleProgress = Mathf.Clamp01(nippleProgress + amount); + UpdateNipples(); + } + + public void AdjustNippleSizeImmediately(float amount) + { + baseNipple = Mathf.Clamp01(baseNipple + amount); + UpdateNipples(); + } + + public void AdjustNippleColorImmediately(float amount) + { + baseAlpha = Mathf.Clamp01(baseAlpha + amount); + UpdateNipples(); + } + + public void AdjustAreolaSizeImmediately(float amount) + { + baseAreola = Mathf.Clamp01(baseAreola + amount); + UpdateNipples(); + } + + public void UpdateNipples() + { + cachedAlpha = baseAlpha + nippleProgress * nippleChange; + cachedAreola = baseAreola + nippleProgress * nippleChange; + cachedNipple = baseNipple + nippleProgress * nippleChange; + + // For some reason, Props can go null when RJW relocates the chest (e.g. some animals), so catch that + cachedColor = Colors.CMYKLerp(Utility.SafeSkinColor(Pawn), (Props?.BlackNippleColor ?? CompProperties_Breast.DefaultBlacknippleColor.ToColor), Alpha); + } + + public void CopyBreastProperties(HediffComp_Breast original) + { + maxBreastIncrement = original.maxBreastIncrement; + baseAlpha = original.baseAlpha; + baseAreola = original.baseAreola; + baseNipple = original.baseNipple; + UpdateNipples(); + } + + public string DebugInfo() + { + return "Size: " + parent.Severity + + "\nIncrease: " + breastSizeIncreased + + "\n" + debugGrowthStatus + + "\nNipple progress: " + nippleProgress + + "\nBase alpha: " + baseAlpha + + "\nAlpha: " + cachedAlpha + + "\nBase areola: " + baseAreola + + "\nAreola: " + cachedAreola + + "\nDisplayed areola: " + AreolaSize + + "\nBase nipple: " + baseNipple + + "\nNipple: " + cachedNipple + + "\nDisplayed nipple: " + NippleSize; + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_InducedOvulator.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_InducedOvulator.cs new file mode 100644 index 0000000..3b4ab9c --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_InducedOvulator.cs @@ -0,0 +1,115 @@ +using RimWorld; +using UnityEngine; +using Verse; + +namespace RJW_Menstruation +{ + public class CompProperties_InducedOvulator : CompProperties_Menstruation + { + public CompProperties_InducedOvulator() + { + compClass = typeof(HediffComp_InducedOvulator); + } + + } + + public class HediffComp_InducedOvulator : HediffComp_Menstruation + { + protected bool hadOvulatoryStage = false; // Regardless of whether an egg was actually produced + + protected override void InitializeExtraValues() + { + base.InitializeExtraValues(); + hadOvulatoryStage |= IsEggExist; + } + + public override string GetCurStageDesc + { + get + { + switch (CurrentVisibleStage) + { + case Stage.Follicular: + return Translations.Stage_Follicular_Induced_Desc + (EggHealth < 1f ? " " + Translations.Stage_Climacteric_Desc : ""); + default: + return base.GetCurStageDesc; + } + } + } + + // In an induced ovulator, about 65% of eggs ovulated will become pregnancies, so the expected lifetime supply + // is the number of pregnancies they could have, with some extra to be sure. + // An IUD or a poor fertility mate could run this down quicker. Oh well. + protected override float RaceCyclesPerYear() + { + // Don't bother with breeding season, since so much time is planned to be spent pregnant. + float pregnanciesPerYear = GenDate.DaysPerYear / Mathf.Max(1, Pawn.RaceProps.gestationPeriodDays); + + return 2 * pregnanciesPerYear / Configurations.ImplantationChanceDefault; + } + + // There's really no good way to estimate the number of times it's been induced, so this is all we can do + protected override int PawnEggsUsed(float pawnCyclesElapsed, float avglittersize) + { + return Mathf.CeilToInt((Pawn.relations?.ChildrenCount ?? 0) / Configurations.ImplantationChanceDefault); + } + + public override void CompExposeData() + { + base.CompExposeData(); + Scribe_Values.Look(ref hadOvulatoryStage, "hadOvulatoryStage", false); + } + + protected override void GoOvulatoryStage() + { + estrusflag = false; + hadOvulatoryStage = false; + GoNextStage(Stage.Luteal); + } + + protected override void OvulatoryAction() + { + base.OvulatoryAction(); + hadOvulatoryStage = true; + } + + protected override void LutealAction() + { + base.LutealAction(); + if (curStage != Stage.Luteal) hadOvulatoryStage = false; + } + + protected override void AfterCumIn(Pawn cummer) + { + base.AfterCumIn(cummer); + if (curStage == Stage.Follicular) GoNextStage(Stage.Ovulatory); + } + + public override bool IsDangerDay + { + get + { + if (Pawn.HasIUD()) return false; + + switch (curStage) + { + case Stage.Follicular: + case Stage.Ovulatory: + return true; + case Stage.Luteal: + return hadOvulatoryStage && curStageTicks < EggLifespanTicks; + default: + return false; + } + } + } + + protected override bool ShouldBeInEstrus() + { + if (curStage == Stage.Luteal && !hadOvulatoryStage) return false; + else return base.ShouldBeInEstrus(); + } + + protected override float RandomOvulationChance => 0; + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Menstruation.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Menstruation.cs new file mode 100644 index 0000000..3518b5c --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Menstruation.cs @@ -0,0 +1,2027 @@ +using RimWorld; +using RimWorld.Planet; +using rjw; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using Verse; + +namespace RJW_Menstruation +{ + [Flags] + public enum SeasonalBreed + { + Always = 0, + Spring = 1, + Summer = 2, + Fall = 4, + Winter = 8, + FirstHalf = Spring | Summer, + SecondHalf = Fall | Winter + } + + + public class CompProperties_Menstruation : HediffCompProperties + { + public float maxCumCapacity; // ml + public float baseImplantationChanceFactor; + public float basefertilizationChanceFactor; + public int follicularIntervalDays = 14; //before ovulation including beginning of bleeding + public int ovulationIntervalHours = 12; //between the end of follicular and the egg emerging + public int lutealIntervalDays = 14; //after ovulation until bleeding + public int bleedingIntervalDays = 6; //must be less than folicularIntervalDays + public int recoveryIntervalDays = 10; //additional infertile days after gave birth + public int eggLifespanDays = 2; //fertiledays = ovaluationday - spermlifespan ~ ovaluationday + egglifespanday + public string wombTex = "Womb/Womb"; //fertiledays = ovaluationday - spermlifespan ~ ovaluationday + egglifespanday + public string vagTex = "Genitals/Vagina"; //fertiledays = ovaluationday - spermlifespan ~ ovaluationday + egglifespanday + public bool infertile = false; + public bool concealedEstrus = false; + public SeasonalBreed breedingSeason = SeasonalBreed.Always; + public int estrusDaysBeforeOvulation = 3; + public int eggMultiplier = 1; + + + public CompProperties_Menstruation() + { + + compClass = typeof(HediffComp_Menstruation); + } + } + + + public class CompProperties_Anus : HediffCompProperties + { + public string analTex = "Genitals/Anal"; + + public CompProperties_Anus() + { + compClass = typeof(HediffComp_Anus); + } + } + + public class HediffComp_Menstruation : HediffComp + { + const float minmakefilthvalue = 1.0f; + const int maxImplantDelayHours = 30 * GenDate.HoursPerDay; + const int minImplantAgeHours = 3 * GenDate.HoursPerDay; + const float fluidLeakThreshold = 3.5f; + const float pulloutSuccessRate = 0.8f; + const float fetishPulloutSuccessModifier = 0.25f; + + public CompProperties_Menstruation Props; + public Stage curStage = Stage.Follicular; + public int curStageTicks = 0; // Actual number of ticks equals this / cycleAcceleration + private int tickInterval = -1; + const int recalculateTickInterval = GenTicks.TickLongInterval; + public bool loaded = false; + public bool initError = false; + public int ovarypower = -100000; + public int eggstack = 0; + public bool DoCleanWomb = false; + + public enum Stage + { + Follicular, + Ovulatory, + Luteal, + Bleeding, + Pregnant, + Recover, + None, + Infertile, + Anestrus + } + + public enum EstrusLevel + { + None, + Concealed, + Visible + } + + public static readonly Dictionary StageTexture = new Dictionary() + { + { Stage.Follicular, TextureCache.FollicularTexture }, + { Stage.Ovulatory, TextureCache.OvulatoryTexture }, + { Stage.Luteal, TextureCache.LutealTexture }, + { Stage.Bleeding, TextureCache.BleedingTexture }, + { Stage.Pregnant, TextureCache.PregnantTexture }, + { Stage.Recover, TextureCache.RecoverTexture } + }; + + + protected List cums; + protected List eggs; + protected float cycleSpeed = -1; + protected float cycleVariability = -1; + protected int currentIntervalTicks = -1; // Actual number of ticks equals this / cycleAcceleration + protected float crampPain = -1; + protected float fluidToLeak = 0; + protected Need sexNeed = null; + protected string customwombtex = null; + protected string customvagtex = null; + protected bool estrusflag = false; + protected float? ovulationChanceCache = null; // Dirtied every simulation + protected float? implantationChanceCache = null; + protected int opcache = -1; + protected float antisperm = 0.0f; + // RJW pregnancy, or Biotech pregnancy/labor/laborpushing + protected Hediff pregnancy = null; + + protected int eggLifeSpanTicks = 2 * GenDate.TicksPerDay; + protected EstrusLevel estrusLevel = EstrusLevel.Visible; + protected float ovulationFactor = 1f; + protected bool noBleeding = false; + + private static readonly SimpleCurve SexFrequencyCurve = new SimpleCurve() + { + new CurvePoint(0.4f,0.05f), + new CurvePoint(0.6f,0.1f), + new CurvePoint(0.8f,0.25f), + new CurvePoint(1.0f,0.5f) + }; + + private static readonly SimpleCurve SexSatisfactionCurve = new SimpleCurve() + { + new CurvePoint(0.4f,0.5f), + new CurvePoint(0.6f,0.6f), + new CurvePoint(0.8f,0.7f), + new CurvePoint(1.0f,0.8f) + }; + + private static readonly SimpleCurve FertilityCurve = new SimpleCurve() + { + new CurvePoint(0.4f,0.01f), + new CurvePoint(0.6f,0.1f), + new CurvePoint(0.8f,0.25f), + new CurvePoint(1.0f,0.5f) + }; + + protected int TickInterval + { + get + { + if (tickInterval <= 0) + { + if (Pawn.IsAnimal()) tickInterval = Configurations.AnimalTickInterval; + else if (Pawn.IsColonist || Pawn.IsPrisonerOfColony || Pawn.IsSlaveOfColony) tickInterval = Configurations.ColonistTickInterval; + else tickInterval = Configurations.NonColonistTickInterval; + if (tickInterval < Configurations.TickIntervalMinimum) tickInterval = Configurations.TickIntervalMinimum; + else if (tickInterval > Configurations.TickIntervalMaximum) tickInterval = Configurations.TickIntervalMaximum; + } + return tickInterval; + } + set => tickInterval = value; + } + + public float HoursBetweenSimulations => (float)TickInterval / GenDate.TicksPerHour; + + public Hediff Pregnancy + { + get + { + if (pregnancy == null) return null; + else if (!Pawn.health.hediffSet.hediffs.Contains(pregnancy)) + { + pregnancy = null; + return null; + } + else return pregnancy; + } + set => pregnancy = value; + } + + public int OvaryPowerThreshold + { + get + { + if (opcache > 0) return opcache; + const float yearsBeforeMenopause = 6.0f; + opcache = (int)(RaceCyclesPerYear() * + AverageLitterSize() * + yearsBeforeMenopause * + (Pawn.RaceProps.lifeExpectancy / ThingDefOf.Human.race.lifeExpectancy)); + if (opcache == 0) opcache = 1; + return opcache; + } + } + + // >= 1: Normal cycles + // 1 - 0: Climacteric + // <= 0: Menopause + public float EggHealth + { + get + { + if (!Configurations.EnableMenopause || Props.infertile) return Mathf.Max(1.0f, ovarypower / OvaryPowerThreshold); + else return (float)ovarypower / OvaryPowerThreshold; + } + } + + public float SexFrequencyModifier + { + get + { + float eggHealth = EggHealth; + if (eggHealth >= 1) return 1.0f; + else if (eggHealth <= 0) return 0.01f; + else return SexFrequencyCurve.Evaluate(eggHealth); + } + } + + public float SexSatisfactionModifier + { + get + { + float eggHealth = EggHealth; + if (eggHealth >= 1) return 1.0f; + else if (eggHealth <= 0) return 0.5f; + else return SexSatisfactionCurve.Evaluate(eggHealth); + } + } + + public float FertilityModifier + { + get + { + float eggHealth = EggHealth; + if (eggHealth >= 1) return 1.0f; + else if (eggHealth <= 0) return 0.0f; + else return FertilityCurve.Evaluate(eggHealth); + } + } + + public float TotalCum + { + get => cums?.Sum(cum => cum.Volume) ?? 0; + } + public float TotalFertCum + { + get => cums?.Where(cum => CumCanFertilize(cum)).Sum(cum => cum.FertVolume) ?? 0; + } + public float TotalCumPercent + { + get => cums?.Sum(cum => cum.Volume) / Props.maxCumCapacity ?? 0; + } + public float CumCapacity + { + get + { + float res = Props.maxCumCapacity * Pawn.BodySize; + if (curStage != Stage.Pregnant || (pregnancy?.Severity ?? 0f) < 0.175f) res *= 500f; + return res; + } + } + //make follicular interval into half and double egg lifespan + public float CycleFactor + { + get + { + if (Pawn.IsBreeder()) return 0.5f; + + return 1.0f; + } + } + + // I hate doing this, but it's the least bad option + private bool calculatingOvulationChance = false; + public bool CalculatingOvulationChance { get => calculatingOvulationChance; } + + private float CalculatedOvulationChance() + { + float ovulationChance = 1.0f; + if (EggHealth <= 0.0f) return 0.0f; + if (EggHealth < 1.0f / 3.0f) ovulationChance = 0.8f; + if (ModsConfig.BiotechActive && xxx.is_human(Pawn)) + { + if (Pawn.SterileGenes()) return 0.0f; + if (!Pawn.RaceHasFertility()) return 0.0f; + if (AndroidsCompatibility.IsAndroid(Pawn) && parent.def != Genital_Helper.archotech_vagina) return 0.0f; + + float ageFactor = 1.0f; + StatDefOf.Fertility.GetStatPart()?.TransformValue(StatRequest.For(Pawn), ref ageFactor); + if (ageFactor <= 0.0f) return 0.0f; // Too young or too old + + if (Pawn.IsBreeder()) ovulationChance *= 10.0f; + try + { + calculatingOvulationChance = true; + ovulationChance *= PawnCapacityUtility.CalculateCapacityLevel(Pawn.health.hediffSet, xxx.reproduction); + } + finally { calculatingOvulationChance = false; } + } + return ovulationChance; + } + + private float CalculatedImplantChance() + { + if (ModsConfig.BiotechActive && xxx.is_human(Pawn)) + { + // Implant factor will be based solely on pawn age, plus any rollover from ovulation chance + float factor = 1.0f; + StatDefOf.Fertility.GetStatPart()?.TransformValue(StatRequest.For(Pawn), ref factor); + if (factor <= 0.0f) return 0.0f; + if (OvulationChance > 1.0f) factor *= OvulationChance; + return Props.baseImplantationChanceFactor * FertilityModifier * factor; + } + else + { + return Pawn.health.capacities.GetLevel(xxx.reproduction) * Props.baseImplantationChanceFactor * FertilityModifier * (Pawn.IsBreeder() ? 10.0f : 1.0f); + } + } + + public float OvulationChance + { + get + { + if (ovulationChanceCache == null) ovulationChanceCache = CalculatedOvulationChance(); + return ovulationChanceCache.Value; + } + } + + // Before configuration setting + public float ImplantChance + { + get + { + if (implantationChanceCache == null) implantationChanceCache = CalculatedImplantChance(); + return implantationChanceCache.Value; + } + } + + public IEnumerable GetCumsInfo + { + get + { + if (cums.NullOrEmpty()) yield return Translations.Info_noCum; + else foreach (Cum cum in cums) + yield return string.Format("{0}: {1:0.##}ml", cum.notcum ? cum.notcumLabel : cum.pawn?.Label, cum.Volume); + } + } + public Color GetCumMixtureColor + { + get + { + Color mixedcolor = Color.white; + + if (cums.NullOrEmpty()) return mixedcolor; + + float mixedsofar = 0; + foreach (Cum cum in cums) + { + if (cum.Volume > 0) + { + mixedcolor = Colors.CMYKLerp(mixedcolor, cum.Color, cum.Volume / (mixedsofar + cum.Volume)); + mixedsofar += cum.Volume; + } + } + return mixedcolor; + } + } + + public Stage CurrentVisibleStage + { + get + { + if (curStage == Stage.Pregnant) + { + if (Configurations.InfoDetail == Configurations.DetailLevel.All || (pregnancy?.Visible ?? false)) + return Stage.Pregnant; + else + return Stage.Luteal; + } + return curStage; + } + } + + public string GetCurStageLabel + { + get + { + switch (CurrentVisibleStage) + { + case Stage.Follicular: + return Translations.Stage_Follicular + (EggHealth < 1f ? " " + Translations.Stage_Climacteric : ""); + case Stage.Ovulatory: + return Translations.Stage_Ovulatory + (EggHealth < 1f ? " " + Translations.Stage_Climacteric : ""); + case Stage.Luteal: + return Translations.Stage_Luteal + (EggHealth < 1f ? " " + Translations.Stage_Climacteric : ""); + case Stage.Bleeding: + return Translations.Stage_Bleeding + (EggHealth < 1f ? " " + Translations.Stage_Climacteric : ""); + case Stage.Pregnant: + return Translations.Stage_Pregnant; + case Stage.Recover: + return Translations.Stage_Recover; + case Stage.None: + case Stage.Infertile: + if (EggHealth <= 0f) return Translations.Stage_Menopause; + else return Translations.Stage_None; + case Stage.Anestrus: + return Translations.Stage_Anestrus; + default: + return ""; + } + } + + } + public virtual string GetCurStageDesc + { + get + { + switch (CurrentVisibleStage) + { + case Stage.Follicular: + return Translations.Stage_Follicular_Desc + (EggHealth < 1f ? " " + Translations.Stage_Climacteric_Desc : ""); + case Stage.Ovulatory: + return Translations.Stage_Ovulatory_Desc + (EggHealth < 1f ? " " + Translations.Stage_Climacteric_Desc : ""); + case Stage.Luteal: + return Translations.Stage_Luteal_Desc + (EggHealth < 1f ? " " + Translations.Stage_Climacteric_Desc : ""); + case Stage.Bleeding: + return Translations.Stage_Bleeding_Desc + (EggHealth < 1f ? " " + Translations.Stage_Climacteric_Desc : ""); + case Stage.Pregnant: + return Translations.Stage_Pregnant_Desc; + case Stage.Recover: + return Translations.Stage_Recover_Desc; + case Stage.None: + case Stage.Infertile: + if (EggHealth <= 0f) return Translations.Stage_Menopause_Desc; + else return Translations.Stage_None_Desc; + case Stage.Anestrus: + return Translations.Stage_Anestrus_Desc; + default: + return ""; + } + } + } + + public string WombTex + { + get => customwombtex ?? Props.wombTex; + set => customwombtex = value; + } + public string VagTex + { + get => customvagtex ?? Props.vagTex; + set => customvagtex = value; + } + public string GetFertilizingInfo + { + get + { + if (eggs.NullOrEmpty()) return ""; + + StringBuilder res = new StringBuilder(); + int fertilized = eggs.Count(egg => egg.fertilized); + if (fertilized != 0) res.AppendFormat("{0} {1}", fertilized, Translations.Dialog_WombInfo05); + if (fertilized != 0 && eggs.Count - fertilized != 0) res.Append(", "); + if (cums.NullOrEmpty() || TotalFertCum == 0) + { + if (eggs.Count - fertilized != 0) res.AppendFormat("{0} {1}", eggs.Count - fertilized, Translations.Dialog_WombInfo07); + } + else + { + if (eggs.Count - fertilized != 0) res.AppendFormat("{0} {1}", eggs.Count - fertilized, Translations.Dialog_WombInfo06); + } + return res.ToString(); + } + } + public bool IsEggFertilizing + { + get + { + if (eggs.NullOrEmpty()) return false; + return cums?.Any(cum => cum.FertVolume > 0) ?? false; + } + } + /// + /// returns fertstage. if not fertilized returns -1 + /// + public int EggFertilizedTime + { + get + { + if (eggs?.All(egg => !egg.fertilized) ?? true) return -1; + return eggs.Max(egg => egg.ticksSinceFertilization); + } + } + public IEnumerable GetCummersAndFertilizers() + { + if (!cums.NullOrEmpty()) + foreach (Cum cum in cums) + yield return cum.pawn; + if (!eggs.NullOrEmpty()) + foreach (Egg egg in eggs) + yield return egg.fertilizer; + } + public bool IsEggExist + { + get => !eggs.NullOrEmpty(); + } + + public int EggLifespanTicks + { + get => eggLifeSpanTicks; + } + + public virtual bool IsDangerDay + { + get + { + if (Pawn.HasIUD()) return false; + + switch (curStage) + { + case Stage.Follicular: + return curStageTicks > 0.7f * currentIntervalTicks; + case Stage.Ovulatory: + return true; + case Stage.Luteal: + return curStageTicks < EggLifespanTicks; + default: + return false; + } + } + } + public int GetNumOfEggs + { + get => eggs?.Count ?? 0; + } + public Color BloodColor + { + get + { + try + { + Color c = Pawn.RaceProps.BloodDef.graphicData.color; + return c; + } + catch + { + return Colors.blood; + } + } + } + + public int CurStageIntervalTicks + { + get => currentIntervalTicks; + } + + public float StageProgress + { + get + { + if (pregnancy == null) return Mathf.Clamp01((float)curStageTicks / currentIntervalTicks); + bool is_discovered = false; + switch (pregnancy) + { + case Hediff_BasePregnancy rjw_preg: + is_discovered = rjw_preg.is_discovered; + break; + case Hediff_Pregnant vanilla_preg: + is_discovered = vanilla_preg.Visible; + break; + case Hediff_Labor _: + case Hediff_LaborPushing _: + return 1.0f; + } + + if (is_discovered || Configurations.infoDetail == Configurations.DetailLevel.All) return pregnancy.Severity; + + // Luteal will appear to progress, hitting the end of the phase when the pregnancy is discovered + float discoveryTime = 0.5f; + if (Pawn.story?.bodyType == BodyTypeDefOf.Thin) discoveryTime = 0.25f; + else if (Pawn.story?.bodyType == BodyTypeDefOf.Female) discoveryTime = 0.35f; + // Estimated; there's no way to get the exact value after the fact without writing it into the save + float lutealProgressWhenImplanted = Math.Min(0.5f, maxImplantDelayHours / (Props.lutealIntervalDays * GenDate.HoursPerDay)); + + return GenMath.LerpDouble(0, discoveryTime, lutealProgressWhenImplanted, 1.0f, pregnancy.Severity); + } + } + + public float StageProgessNextUpdate + { + get + { + if (pregnancy != null) return StageProgress; + return Mathf.Clamp01((float)(curStageTicks + TickInterval * Configurations.CycleAcceleration) / currentIntervalTicks); + } + } + + public Texture2D GetStageTexture + { + get + { + if (!StageTexture.TryGetValue(CurrentVisibleStage, out Texture2D tex)) tex = TextureCache.PregnantTexture; + return tex; + } + } + + public override void CompExposeData() + { + base.CompExposeData(); + if (Scribe.mode == LoadSaveMode.LoadingVars) + { + int curStageHrs = -1; + int currentIntervalHours = -1; + Scribe_Values.Look(ref curStageHrs, "curStageHrs", curStageHrs, true); + Scribe_Values.Look(ref currentIntervalHours, "currentIntervalHours", currentIntervalHours, true); + if (curStageHrs >= 0) curStageTicks = curStageHrs * GenDate.TicksPerHour; + if (currentIntervalHours >= 0) currentIntervalTicks = currentIntervalHours * GenDate.TicksPerHour; + } + + Scribe_Collections.Look(ref cums, saveDestroyedThings: true, label: "cums", lookMode: LookMode.Deep, ctorArgs: new object[0]); + Scribe_Collections.Look(ref eggs, saveDestroyedThings: true, label: "eggs", lookMode: LookMode.Deep, ctorArgs: new object[0]); + Scribe_Values.Look(ref curStage, "curStage", curStage, true); + Scribe_Values.Look(ref curStageTicks, "curStageTicks", curStageTicks, true); + Scribe_Values.Look(ref cycleSpeed, "cycleSpeed", cycleSpeed, true); + Scribe_Values.Look(ref cycleVariability, "cycleVariability", cycleVariability, true); + Scribe_Values.Look(ref currentIntervalTicks, "currentIntervalTicks", currentIntervalTicks, true); + Scribe_Values.Look(ref crampPain, "crampPain", crampPain, true); + Scribe_Values.Look(ref fluidToLeak, "fluidToLeak", 0); + Scribe_Values.Look(ref ovarypower, "ovarypower", ovarypower, true); + Scribe_Values.Look(ref eggstack, "eggstack", 0); + Scribe_Values.Look(ref estrusflag, "estrusflag", false); + Scribe_Values.Look(ref DoCleanWomb, "DoCleanWomb", false); + Scribe_References.Look(ref pregnancy, "pregnancy"); + if (Scribe.mode == LoadSaveMode.PostLoadInit) + Initialize(); + } + + + public override void CompPostPostAdd(DamageInfo? dinfo) + { + if (!loaded) + { + Initialize(); + } + } + + public void Notify_UpdatedGenes() + { + eggLifeSpanTicks = Props.eggLifespanDays * GenDate.TicksPerDay; + estrusLevel = Props.concealedEstrus ? EstrusLevel.Concealed : EstrusLevel.Visible; + ovulationFactor = 1f; + noBleeding = false; + opcache = -1; + + if (Pawn.genes == null || !ModsConfig.BiotechActive) return; + foreach (MenstruationModExtension extension in Pawn.genes.GenesListForReading.Select(gene => gene.def.GetModExtension()).Where(ext => ext != null)) + { + eggLifeSpanTicks = (int)(eggLifeSpanTicks * extension.eggLifeTimeFactor); + if (extension.alwaysEstrus) estrusLevel = EstrusLevel.Visible; + else if (extension.neverEstrus) estrusLevel = EstrusLevel.None; + ovulationFactor *= extension.ovulationFactor; + if (extension.noBleeding) noBleeding = true; + } + if (eggLifeSpanTicks < 0) eggLifeSpanTicks = 0; + if (ovulationFactor < 0f) ovulationFactor = 0f; + } + + public bool ShouldSimulate() + { + if (!Pawn.ShouldCycle()) return false; + if (Pawn.SpawnedOrAnyParentSpawned || Pawn.IsCaravanMember() || PawnUtility.IsTravelingInTransportPodWorldObject(Pawn)) return true; + + return false; + } + + public bool ShouldBeInfertile() + { + if (pregnancy != null) return false; + if (ImplantChance <= 0.0f) return true; + // Give the last egg ovulated a chance to implant + if (curStage == Stage.Luteal || curStage == Stage.Bleeding || curStage == Stage.Recover) return false; + if (EggHealth <= 0.0f) return true; + return false; + } + + public override void CompPostTick(ref float severityAdjustment) + { + base.CompPostTick(ref severityAdjustment); + // If an exception makes it out, RW will remove the hediff, so catch it here + try + { + if (Pawn.IsHashIntervalTick(recalculateTickInterval)) TickInterval = -1; // Every so often, force TickInterval to be recalculated in case the pawn's status changed. + if (!Pawn.IsHashIntervalTick(TickInterval)) return; + + if (!ShouldSimulate()) return; + + // Initialize immediately if needed, but if there's an error, then don't spam it every tick + if (!loaded && !initError) + { + Log.Warning($"{Pawn}'s womb is ticking, but was not initialized first"); + Initialize(); + } + + if (initError) Log.Warning($"Attempting to process {Pawn}'s womb uninitialized"); + + if (Pregnancy != null && curStage != Stage.Pregnant) + { + Log.Warning($"{Pawn}'s womb has a pregnancy, but was not in the pregnant stage"); + GoNextStage(Stage.Pregnant); + } + + BeforeSimulator(); + + if (ShouldBeInfertile()) GoNextStage(Stage.Infertile); + switch (curStage) + { + case Stage.Follicular: + FollicularAction(); + break; + case Stage.Ovulatory: + OvulatoryAction(); + break; + case Stage.Luteal: + LutealAction(); + break; + case Stage.Bleeding: + BleedingAction(); + break; + case Stage.Pregnant: + PregnantAction(); + break; + case Stage.Recover: + RecoverAction(); + break; + case Stage.None: + break; + case Stage.Infertile: + InfertileAction(); + break; + case Stage.Anestrus: + AnestrusAction(); + break; + default: + GoNextStage(Stage.Follicular); + break; + } + AfterSimulator(); + } + catch (Exception ex) + { + Log.Error($"Error processing womb of {Pawn}: {ex}"); + } + } + + public override void CompPostPostRemoved() + { + // If a hediff is removed from a pawn that does not have it, CompPostPostRemoved is still called on the pawn that does. + // If it was a legitimate removal, then it won't be in this pawn's hediff list anymore, as that removal occurs first + if (Pawn.health.hediffSet.hediffs.Contains(parent)) + { + Log.Warning($"Attempted to remove menstruation comp from wrong pawn ({Pawn})."); + return; + } + switch (pregnancy) + { + case null: + case Hediff_MechanoidPregnancy _: + break; + case Hediff_BasePregnancy rjw_preg: + rjw_preg.Miscarry(); + break; + case Hediff_Pregnant vanilla_preg: + Pawn.health.RemoveHediff(vanilla_preg); + break; + } + + base.CompPostPostRemoved(); + } + + public override string CompTipStringExtra + { + get + { + if (Pawn.Dead) return null; + StringBuilder tip = new StringBuilder(); + tip.Append(Translations.Dialog_WombInfo01); + tip.Append(": "); + tip.Append(GetCurStageLabel); + string fertInfo = GetFertilizingInfo; + if (CurrentVisibleStage == Stage.Luteal && fertInfo.Length > 0) + { + tip.AppendLine(); + tip.Append(fertInfo); + } + return tip.ToString(); + } + } + + protected virtual int TicksToNextStage() + { + return Math.Max(0, (currentIntervalTicks - curStageTicks) / Configurations.CycleAcceleration); + } + + public override string CompDebugString() + { + if (Pawn.Dead || curStage == Stage.None || curStage == Stage.Infertile || curStage == Stage.Pregnant) return null; + StringBuilder debugString = new StringBuilder(); + debugString.Append($"Time to next state: "); + debugString.Append(GenDate.ToStringTicksToPeriod(TicksToNextStage())); + return debugString.ToString(); + } + + /// + /// Get fluid in womb that not a cum + /// + /// + /// + public Cum GetNotCum(string notcumlabel) + { + return cums?.Find(cum => cum.notcum && cum.notcumLabel.Equals(notcumlabel)); + } + + /// + /// Get pawn's cum in womb + /// + /// + /// + public Cum GetCum(Pawn pawn) + { + return cums?.Find(cum => !cum.notcum && cum.pawn == pawn); + } + + /// + /// Inject pawn's cum into womb + /// + /// + /// + /// + /// + public void CumIn(Pawn cummer, float volume, float fertility = 1.0f, bool precum = false) + { + if (volume <= 0) return; + if (!precum && fertility > 0 && IsDangerDay && cummer.relations.GetPregnancyApproachForPartner(Pawn) == PregnancyApproach.AvoidPregnancy) + { + float successChance = pulloutSuccessRate; + if (cummer.HasImpregnationFetish()) successChance *= fetishPulloutSuccessModifier; + if (Pawn.HasImpregnationFetish()) successChance *= fetishPulloutSuccessModifier; + if (Rand.Chance(successChance)) return; + } + if (Pawn.HasIUD()) fertility /= 100f; + float cumd = TotalCumPercent; + float tmp = TotalCum + volume; + if (tmp > CumCapacity) + { + float cumoutrate = 1 - (CumCapacity / tmp); + bool merged = false; + if (!cums.NullOrEmpty()) foreach (Cum cum in cums) + { + if (cum.pawn?.Equals(cummer) ?? false) + { + cum.MergeWithCum(volume, fertility); + merged = true; + } + cum.DismishForce(cumoutrate); + } + if (!merged) cums.Add(new Cum(cummer, volume * (1 - cumoutrate), fertility)); + } + else + { + + bool merged = false; + if (!cums.NullOrEmpty()) foreach (Cum cum in cums) + { + if (cum.pawn?.Equals(cummer) ?? false) + { + cum.MergeWithCum(volume, fertility); + merged = true; + } + } + if (!merged) cums.Add(new Cum(cummer, volume, fertility)); + } + cumd = TotalCumPercent - cumd; + + if (!precum) + { + Pawn.records.AddTo(VariousDefOf.AmountofCreampied, volume); + AfterCumIn(cummer); + AfterFluidIn(cumd); + } + } + + /// + /// Inject pawn's fluid into womb + /// + /// + /// + /// + /// + /// + public void CumIn(Pawn cummer, float volume, string notcumlabel, float decayresist = 0, ThingDef filthdef = null) + { + if (volume <= 0) return; + float tmp = TotalCum + volume; + float cumd = TotalCumPercent; + if (tmp > CumCapacity) + { + float cumoutrate = 1 - (CumCapacity / tmp); + bool merged = false; + if (!cums.NullOrEmpty()) foreach (Cum cum in cums) + { + if (cum.notcum && (cum.pawn?.Equals(cummer) ?? false) && cum.notcumLabel.Equals(notcumlabel)) + { + cum.MergeWithFluid(volume, decayresist, filthdef); + merged = true; + } + cum.DismishForce(cumoutrate); + } + if (!merged) cums.Add(new Cum(cummer, volume * (1 - cumoutrate), notcumlabel, decayresist, filthdef)); + } + else + { + + bool merged = false; + if (!cums.NullOrEmpty()) foreach (Cum cum in cums) + { + if (cum.notcum && (cum.pawn?.Equals(cummer) ?? false) && cum.notcumLabel.Equals(notcumlabel)) + { + cum.MergeWithFluid(volume, decayresist, filthdef); + merged = true; + } + } + if (!merged) cums.Add(new Cum(cummer, volume, notcumlabel, decayresist, filthdef)); + } + cumd = TotalCumPercent - cumd; + AfterNotCumIn(); + AfterFluidIn(cumd); + } + + protected virtual void AfterCumIn(Pawn cummer) + { + ThoughtCumInside(cummer); + TaleCumInside(cummer); + } + + protected virtual void AfterNotCumIn() + { + + } + + /// + /// Action for both Cum and NotCum + /// + /// Fluid deviation + protected virtual void AfterFluidIn(float fd) + { + + + } + + + protected void BeforeCumOut(out Absorber absorber) + { + Hediff asa = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_ASA); + float asafactor = asa?.Severity ?? 0f; + + if (Pawn.HasIUD()) antisperm = 0.70f + asafactor; + else antisperm = 0.0f + asafactor; + + absorber = (Absorber)Pawn.apparel?.WornApparel?.Find(x => x is Absorber); + if (absorber != null) + { + absorber.WearEffect(TickInterval); + if (absorber.dirty && absorber.EffectAfterDirty) absorber.DirtyEffect(TickInterval); + } + } + + /// + /// For natural leaking + /// + protected virtual void AfterCumOut(float amount, List filthlabels) + { + fluidToLeak += amount; + if (fluidToLeak > fluidLeakThreshold) Pawn.needs?.mood?.thoughts?.memories?.TryGainMemory(VariousDefOf.LeakingFluids); + for (; fluidToLeak > fluidLeakThreshold; fluidToLeak -= fluidLeakThreshold) + { + if (cums.Count > 1) MakeCumFilthMixture(fluidLeakThreshold, filthlabels); + else if (cums.Count == 1) MakeCumFilth(cums.First(), fluidLeakThreshold); + } + } + + /// + /// For all type of leaking + /// + /// + protected virtual void AfterFluidOut(float fd) + { + + } + + + + + /// + /// Excrete cums in womb naturally + /// + public void CumOut() + { + float leakfactor = 1.0f; + float totalleak = 0f; + float cumd = TotalCumPercent; + List filthlabels = new List(); + BeforeCumOut(out Absorber absorber); + if (cums.NullOrEmpty()) return; + if (TotalCum > Props.maxCumCapacity * Pawn.BodySize) leakfactor = Math.Min(1 + (TotalCum - Props.maxCumCapacity * Pawn.BodySize) / 10, 2f); + if (absorber != null && absorber.dirty && !absorber.LeakAfterDirty) leakfactor = 0f; + if (Pawn.CurJobDef == xxx.knotted) leakfactor = 0f; + foreach (Cum cum in cums) + { + if (Rand.Chance(HoursBetweenSimulations)) cum.CumEffects(Pawn); + float vd = cum.DismishNatural(leakfactor, this, antisperm); + cum.MakeThinner((float)Configurations.CycleAcceleration * HoursBetweenSimulations); + totalleak += AbsorbCum(vd, absorber); + string tmp = "FilthLabelWithSource".Translate(cum.FilthDef.label, cum.pawn?.LabelShort ?? "Unknown", 1.ToString()); + filthlabels.Add(tmp.Replace(" x1", "")); + } + AfterCumOut(totalleak, filthlabels); + cums.RemoveAll(cum => cum.ShouldRemove()); + if (cums.NullOrEmpty()) fluidToLeak = 0; + cumd = TotalCumPercent - cumd; + AfterFluidOut(cumd); + } + + /// + /// Force excrete cums in womb and get excreted amount of specific cum. + /// + /// + /// + /// Amount of target cum + public float CumOut(Cum targetcum, float portion = 0.1f) + { + if (cums.NullOrEmpty()) return 0; + float totalleak = 0; + List filthlabels = new List(); + float outcum = 0; + float cumd = TotalCumPercent; + HashSet removecums = new HashSet(); + foreach (Cum cum in cums) + { + float vd = cum.DismishForce(portion); + if (cum.Equals(targetcum)) outcum = vd; + //MakeCumFilth(cum, vd - cum.volume); + string tmp = "FilthLabelWithSource".Translate(cum.FilthDef.label, cum.pawn?.LabelShort ?? "Unknown", 1.ToString()); + filthlabels.Add(tmp.Replace(" x1", "")); + totalleak += vd; + if (cum.ShouldRemove()) removecums.Add(cum); + } + if (cums.Count > 1) MakeCumFilthMixture(totalleak, filthlabels); + else if (cums.Count == 1) MakeCumFilth(cums.First(), totalleak); + cums.RemoveAll(cum => removecums.Contains(cum)); + if (cums.NullOrEmpty()) fluidToLeak = 0; + cumd = TotalCumPercent - cumd; + AfterFluidOut(cumd); + return outcum; + } + + /// + /// Force excrete cums in womb and get mixture of cum. + /// + /// + /// + /// + public CumMixture MixtureOut(ThingDef mixtureDef, float portion = 0.1f) + { + if (cums.NullOrEmpty()) return null; + Color color = GetCumMixtureColor; + float totalleak = 0; + List cumlabels = new List(); + HashSet removecums = new HashSet(); + bool pure = true; + foreach (Cum cum in cums) + { + float vd = cum.DismishForce(portion); + string tmp = "FilthLabelWithSource".Translate(cum.FilthDef.label, cum.pawn?.LabelShort ?? "Unknown", 1.ToString()); + cumlabels.Add(tmp.Replace(" x1", "")); + totalleak += vd; + if (cum.ShouldRemove()) removecums.Add(cum); + if (cum.notcum) pure = false; + } + cums.RemoveAll(cum => removecums.Contains(cum)); + if (cums.NullOrEmpty()) fluidToLeak = 0; + return new CumMixture(Pawn, totalleak, cumlabels, color, mixtureDef, pure); + } + + /// + /// Debug: Remove all cums from a womb + /// + /// + public void RemoveAllCums() + { + cums.Clear(); + } + + public void RemoveAllEggs() + { + eggs.Clear(); + } + + + /// + /// Fertilize eggs and return the result + /// + /// + protected void FertilizationCheck() + { + if (eggs.NullOrEmpty()) return; + foreach (Egg egg in eggs) + { + if (!egg.fertilized) egg.fertilizer = Fertilize(); + if (egg.fertilizer != null) + { + egg.fertilized = true; + } + } + } + + public void Initialize() + { + initError = true; + Props = (CompProperties_Menstruation)props; + + if (cums == null) cums = new List(); + if (eggs == null) eggs = new List(); + + PreInitialize(); + + if (Props.infertile) + { + curStage = Stage.None; + loaded = true; + initError = false; + return; + } + + if (cycleSpeed < 0f) cycleSpeed = Utility.RandGaussianLike(0.8f, 1.2f); + if (cycleVariability < 0f) cycleVariability = MenstruationUtility.RandomVariabilityPercent(); + + InitOvary(); + + if (currentIntervalTicks < 0) + { + if (ShouldBeInfertile()) curStage = Stage.Infertile; + else if (!IsBreedingSeason()) curStage = Stage.Anestrus; + else curStage = RandomStage(); + if (curStage == Stage.Follicular) + currentIntervalTicks = PeriodRandomizer(Stage.Follicular) - PeriodRandomizer(Stage.Bleeding); + else + currentIntervalTicks = PeriodRandomizer(curStage); + if (currentIntervalTicks < 0) currentIntervalTicks = 0; + else if (currentIntervalTicks < curStageTicks) curStageTicks = currentIntervalTicks; + } + if (crampPain < 0) crampPain = PainRandomizer(); + InitializeExtraValues(); + + TakeLoosePregnancy(); + + //Log.Message(Pawn.Label + " - Initialized menstruation comp"); + loaded = true; + initError = false; + } + + protected virtual void PreInitialize() + { + Notify_UpdatedGenes(); + } + + protected virtual void InitializeExtraValues() + { + } + + protected float AverageLitterSize() + { + float avglittersize; + try + { + avglittersize = Mathf.Max(Rand.ByCurveAverage(Pawn.RaceProps.litterSizeCurve), 1.0f); + } + catch (NullReferenceException) + { + avglittersize = 1.0f; + } + avglittersize *= ovulationFactor; + return avglittersize; + } + + protected virtual float RaceCyclesPerYear() + { + int breedingSeasons = 0; + if (Props.breedingSeason == SeasonalBreed.Always) breedingSeasons = 4; + else + { + if ((Props.breedingSeason & SeasonalBreed.Spring) != 0) breedingSeasons++; + if ((Props.breedingSeason & SeasonalBreed.Summer) != 0) breedingSeasons++; + if ((Props.breedingSeason & SeasonalBreed.Fall) != 0) breedingSeasons++; + if ((Props.breedingSeason & SeasonalBreed.Winter) != 0) breedingSeasons++; + } + float breedingRatio = breedingSeasons / 4.0f; + return breedingRatio * GenDate.DaysPerYear / ((float)(Props.follicularIntervalDays + Props.lutealIntervalDays) / Configurations.CycleAccelerationDefault); + } + + protected virtual int PawnEggsUsed(float pawnCyclesElapsed, float avglittersize) + { + return (int)(pawnCyclesElapsed * avglittersize); + } + + public int GetOvaryPowerByAge() + { + float avglittersize = AverageLitterSize(); + + float fertStartAge = Pawn.RaceProps.lifeStageAges?.Find(stage => stage.def.reproductive)?.minAge ?? 0.0f; + float fertEndAge = Pawn.RaceProps.lifeExpectancy * (Pawn.IsAnimal() ? RJWPregnancySettings.fertility_endage_female_animal : RJWPregnancySettings.fertility_endage_female_humanlike); + if (fertEndAge < fertStartAge) fertEndAge = fertStartAge; + + float raceCyclesPerYear = RaceCyclesPerYear(); + int lifetimeCycles = (int)(raceCyclesPerYear * (fertEndAge - fertStartAge)); + int lifetimeEggs = (int)(lifetimeCycles * avglittersize * Props.eggMultiplier * Utility.RandGaussianLike(0.70f, 1.30f, 5)); + + float pawnCyclesPerYear = raceCyclesPerYear * cycleSpeed; + float pawnCyclesElapsed = Mathf.Max((Pawn.ageTracker.AgeBiologicalYearsFloat - fertStartAge) * pawnCyclesPerYear, 0.0f); + int pawnEggsUsed = PawnEggsUsed(pawnCyclesElapsed, avglittersize); + + return Math.Max(lifetimeEggs - pawnEggsUsed, 0); + } + + protected void InitOvary() + { + if (ovarypower < -50000) + { + ovarypower = GetOvaryPowerByAge(); + if (Props.infertile) curStage = Stage.None; + else if (ovarypower < 1) + { + curStage = Stage.Infertile; + } + } + } + + public void RecoverOvary(float multiply = 1.2f) + { + ovarypower = Math.Max(0, (int)(ovarypower * multiply)); + } + + protected virtual void BeforeSimulator() + { + ovulationChanceCache = null; + implantationChanceCache = null; + CumOut(); + } + + protected virtual void AfterSimulator() + { + if (EggHealth < 1f) + { + if (sexNeed == null) sexNeed = Pawn.needs.TryGetNeed(VariousDefOf.SexNeed); + if (sexNeed == null) return; + if (sexNeed.CurLevel < 0.5f) sexNeed.CurLevel += 0.01f * HoursBetweenSimulations / Math.Max(1, Pawn.GetMenstruationComps().Count()); + } + } + + protected virtual bool ShouldBeInEstrus() + { + if (!loaded) + Initialize(); + switch (curStage) + { + case Stage.Follicular: + return curStageTicks > currentIntervalTicks - Props.estrusDaysBeforeOvulation * GenDate.TicksPerDay; + case Stage.Ovulatory: + return true; + case Stage.Luteal: + return curStageTicks < EggLifespanTicks; + default: + return false; + } + } + + public EstrusLevel GetEstrusLevel() + { + if (!ShouldBeInEstrus()) return EstrusLevel.None; + else return estrusLevel; + } + + public void SetEstrus() + { + if (estrusLevel == EstrusLevel.None) return; + Hediff hediff = HediffMaker.MakeHediff(estrusLevel == EstrusLevel.Concealed ? VariousDefOf.Hediff_Estrus_Concealed : VariousDefOf.Hediff_Estrus, Pawn); + Pawn.health.AddHediff(hediff); + } + + public bool IsBreedingSeason() + { + if (Props.breedingSeason == SeasonalBreed.Always) return true; + + int tile = Pawn.Tile; + if (tile < 0) tile = Find.AnyPlayerHomeMap?.Tile ?? -1; + if (tile < 0) return true; + switch (GenLocalDate.Season(tile)) + { + case Season.Spring: + return (Props.breedingSeason & SeasonalBreed.Spring) != 0; + case Season.Summer: + case Season.PermanentSummer: + return (Props.breedingSeason & SeasonalBreed.Summer) != 0; + case Season.Fall: + return (Props.breedingSeason & SeasonalBreed.Fall) != 0; + case Season.Winter: + case Season.PermanentWinter: + return (Props.breedingSeason & SeasonalBreed.Winter) != 0; + default: + return false; + } + } + + public bool CumCanFertilize(Cum cum) + { + return !cum.notcum && + cum.FertVolume > 0 && + !(cum.pawn?.Destroyed ?? true) && + (RJWPregnancySettings.bestial_pregnancy_enabled || xxx.is_animal(Pawn) == xxx.is_animal(cum.pawn)); + } + + protected Pawn Fertilize() + { + if (cums.NullOrEmpty()) return null; + List eligibleCum = cums.FindAll(cum => CumCanFertilize(cum)); + if (eligibleCum.Count == 0) return null; + + float totalFertPower = eligibleCum.Sum(cum => cum.FertVolume); + + //float fertFailChancePerHour = Mathf.Pow(1.0f - Configurations.FertilizeChance, totalFertPower * Props.basefertilizationChanceFactor); + //float fertFailChancePerInterval = Mathf.Pow(fertFailChancePerHour, (float)TickInterval / GenDate.TicksPerHour); + float fertFailChancePerInterval = Mathf.Pow(1.0f - Configurations.FertilizeChance, totalFertPower * Props.basefertilizationChanceFactor * HoursBetweenSimulations); + + if (Rand.Chance(fertFailChancePerInterval)) return null; + + Pawn.records.AddTo(VariousDefOf.AmountofFertilizedEggs, 1); + float selection = Rand.Range(0.0f, totalFertPower); + + foreach (Cum cum in eligibleCum) + { + selection -= cum.FertVolume; + if (selection <= 0) return cum.pawn; + } + + // We shouldn't reach here, but floating point errors exist, so just to be sure, select whomever came the most + return eligibleCum.MaxBy(cum => cum.FertVolume).pawn; + } + + + protected bool Implant() + { + if (eggs.NullOrEmpty()) return false; + + HashSet deadeggs = new HashSet(); + bool pregnant = false; + foreach (Egg egg in eggs) + { + if (!egg.fertilized || + egg.ticksSinceFertilization < minImplantAgeHours * GenDate.TicksPerHour || + egg.ageTicks < Math.Min(Props.lutealIntervalDays * GenDate.TicksPerDay / 2, maxImplantDelayHours * GenDate.TicksPerHour)) + continue; + else if (egg.fertilizer == null) + { + if (Configurations.Debug) Log.Message($"Could not implant {Pawn}'s egg due to null father"); + deadeggs.Add(egg); + continue; + } + else if (Pawn.health.hediffSet.GetFirstHediff() != null || pregnancy is Hediff_MechanoidPregnancy) + { + if (Configurations.Debug) Log.Message($"Could not implant {Pawn}'s egg due to insect or mechanoid pregnancy"); + deadeggs.Add(egg); + continue; + } + else if (Rand.Chance(Configurations.ImplantationChance * ImplantChance * InterspeciesImplantFactor(egg.fertilizer))) + { + try + { + if (Configurations.Debug) Log.Message($"Implanting fertilized egg of {Pawn} into {parent}, father {egg.fertilizer}"); + if (pregnancy == null) + { + Configurations.PregnancyType usePregnancy = xxx.is_human(Pawn) ? Configurations.PregnancySource : Configurations.PregnancyType.MultiplePregnancy; + switch (usePregnancy) + { + case Configurations.PregnancyType.BaseRJW: + + if (Configurations.Debug) Log.Message($"Creating new base RJW pregnancy"); + PregnancyHelper.AddPregnancyHediff(Pawn, egg.fertilizer); + // I hate having to do this, but it gets the newest pregnancy + List pregnancies = new List(); + Pawn.health.hediffSet.GetHediffs(ref pregnancies); + pregnancy = pregnancies.MaxBy(hediff => hediff.loadID); + pregnant = true; + break; + + case Configurations.PregnancyType.MultiplePregnancy: + if (Configurations.Debug) Log.Message($"Creating new menstruation pregnancy"); + pregnancy = Hediff_BasePregnancy.Create(Pawn, egg.fertilizer); + pregnant = true; + deadeggs.Add(egg); + break; + + case Configurations.PregnancyType.Biotech: + if (Configurations.Debug) Log.Message($"Creating new biotech pregnancy"); + pregnancy = HediffMaker.MakeHediff(HediffDefOf.PregnantHuman, Pawn); + if (Configurations.EnableBiotechTwins) + pregnancy.TryGetComp().AddNewBaby(Pawn, egg.fertilizer); + ((Hediff_Pregnant)pregnancy).SetParents(Pawn, egg.fertilizer, PregnancyUtility.GetInheritedGeneSet(egg.fertilizer, Pawn)); + Pawn.health.AddHediff(pregnancy); + pregnant = true; + deadeggs.Add(egg); + break; + } + if (pregnancy is Hediff_BasePregnancy rjw_preg) + { + // TODO: advance biotech pregnancy + rjw_preg.p_start_tick -= egg.ticksSinceFertilization / Configurations.CycleAcceleration; + rjw_preg.p_end_tick -= egg.ticksSinceFertilization / Configurations.CycleAcceleration; + } + } + else + { + switch (pregnancy) + { + case Hediff_Pregnant vanillaPreg: // Not going to do the labor ones + if (!Configurations.EnableBiotechTwins || !Configurations.EnableHeteroOvularTwins) goto default; + if (Configurations.Debug) Log.Message($"Adding to existing Biotech pregnancy {vanillaPreg.GetUniqueLoadID()}"); + HediffComp_PregeneratedBabies comp = vanillaPreg.TryGetComp(); + if (comp == null) Log.Warning($"Trying to add Biotech egg to {Pawn}'s pregnancy without a pregenerated baby comp: {vanillaPreg.GetUniqueLoadID()}"); + else + comp.AddNewBaby(Pawn, egg.fertilizer); + pregnant = true; + deadeggs.Add(egg); + break; + case Hediff_MultiplePregnancy multiPreg: + if (!Configurations.EnableHeteroOvularTwins) goto default; + if (Configurations.Debug) Log.Message($"Adding to existing pregnancy {multiPreg.GetUniqueLoadID()}"); + multiPreg.AddNewBaby(Pawn, egg.fertilizer); + pregnant = true; + deadeggs.Add(egg); + break; + case Hediff_BasePregnancy _: + default: + pregnant = true; + deadeggs.Add(egg); + break; + } + } + } + catch (Exception ex) + { + Log.Error($"Error creating pregnancy in {Pawn}'s womb, father {egg.fertilizer}: {ex}"); + TakeLoosePregnancy(); + deadeggs.Add(egg); + } + } + else + { + if (Configurations.Debug) + { + float interspeciesFactor = InterspeciesImplantFactor(egg.fertilizer); + float implantChance = Configurations.ImplantationChance * ImplantChance * interspeciesFactor; + Log.Message($"Fertilized egg of {Pawn} failed to implant (chance {implantChance.ToStringPercent()}, " + + (interspeciesFactor < 1.0f ? $"interspecies factor {interspeciesFactor.ToStringPercent()}, " : "") + + $"father {egg.fertilizer})"); + } + deadeggs.Add(egg); + } + } + + bool clearAllEggs = true; + switch (Configurations.PregnancySource) + { + case Configurations.PregnancyType.BaseRJW: + clearAllEggs = true; + break; + case Configurations.PregnancyType.MultiplePregnancy: + clearAllEggs = !Configurations.EnableHeteroOvularTwins; + break; + case Configurations.PregnancyType.Biotech: + clearAllEggs = !(Configurations.EnableBiotechTwins && Configurations.EnableHeteroOvularTwins); + break; + } + + if (pregnant && clearAllEggs) + eggs.Clear(); + else + eggs.RemoveAll(egg => deadeggs.Contains(egg)); + return pregnant; + } + + protected void BleedOut() + { + // ~1.5 per hour times acceleration + float bledAmount = Utility.VariationRange(0.03f * Configurations.BleedingAmount * Configurations.CycleAcceleration * HoursBetweenSimulations, 0.5f); + CumIn(Pawn, bledAmount, Translations.Menstrual_Blood, -5.0f, Pawn.RaceProps?.BloodDef ?? ThingDefOf.Filth_Blood); + Cum blood = GetNotCum(Translations.Menstrual_Blood); + if (blood != null) blood.Color = BloodColor; + } + + /// + /// Make filth ignoring absorber + /// + /// + /// + protected void MakeCumFilth(Cum cum, float amount) + { + if (Pawn.MapHeld == null) return; + if (amount >= minmakefilthvalue) FilthMaker.TryMakeFilth(Pawn.PositionHeld, Pawn.MapHeld, cum.FilthDef, cum.pawn?.LabelShort ?? "Unknown"); + } + + /// + /// Absorb cum and return leaked amount + /// + /// + /// + /// + /// + protected float AbsorbCum(float amount, Absorber absorber) + { + + if (absorber == null) + { + //if (amount >= minmakefilthvalue) FilthMaker.TryMakeFilth(Pawn.Position, Pawn.Map, cum.FilthDef, cum.pawn.LabelShort); + return amount; + } + + float absorbable = absorber.GetStatValue(VariousDefOf.MaxAbsorbable); + absorber.SetColor(Colors.CMYKLerp(GetCumMixtureColor, absorber.DrawColor, 1f - amount / absorbable)); + if (absorber.dirty) + { + //if (absorber.LeakAfterDirty) FilthMaker.TryMakeFilth(Pawn.Position, Pawn.Map, cum.FilthDef, cum.pawn.LabelShort); + return amount; + } + absorber.absorbedfluids += amount; + absorber.CheckDirty(); + return 0; + } + + protected float MakeCumFilthMixture(float amount, List cumlabels) + { + if (Pawn.MapHeld == null) return 0; + if (amount >= minmakefilthvalue) + { + FilthMaker_Colored.TryMakeFilth(Pawn.PositionHeld, Pawn.MapHeld, VariousDefOf.FilthMixture, cumlabels, GetCumMixtureColor, false); + } + return amount; + } + + protected void EggDecay() + { + HashSet deadeggs = new HashSet(); + foreach (Egg egg in eggs) + { + egg.ageTicks += TickInterval * Configurations.CycleAcceleration; + if (egg.fertilized) egg.ticksSinceFertilization += TickInterval * Configurations.CycleAcceleration; + else + { + egg.lifeSpanTicks -= TickInterval * Configurations.CycleAcceleration; + if (egg.lifeSpanTicks < 0) deadeggs.Add(egg); + } + } + eggs.RemoveAll(egg => deadeggs.Contains(egg)); + } + + protected void AddCrampPain() + { + Hediff hediff = HediffMaker.MakeHediff(VariousDefOf.Hediff_MenstrualCramp, Pawn); + hediff.Severity = Utility.VariationRange(crampPain, 0.1f); + HediffCompProperties_SeverityPerDay Prop = (HediffCompProperties_SeverityPerDay)hediff.TryGetComp().props; + Prop.severityPerDay = -hediff.Severity / (currentIntervalTicks / GenDate.TicksPerDay) * Configurations.CycleAcceleration; + Pawn.health.AddHediff(hediff, parent.Part); + } + + protected void AdvanceStageTime() + { + curStageTicks += TickInterval * Configurations.CycleAcceleration; + } + + protected virtual void FollicularAction() + { + if (!IsBreedingSeason()) + { + estrusflag = false; + GoNextStage(Stage.Anestrus); + return; + } + else if (curStageTicks >= currentIntervalTicks) + { + GoOvulatoryStage(); + } + else + { + AdvanceStageTime(); + if (!estrusflag && curStageTicks > currentIntervalTicks - Props.estrusDaysBeforeOvulation * GenDate.TicksPerDay) + { + estrusflag = true; + SetEstrus(); + } + } + } + + protected virtual void OvulatoryAction() + { + if (curStageTicks < currentIntervalTicks) + { + AdvanceStageTime(); + return; + } + estrusflag = false; + float eggnum; + try + { + eggnum = Math.Max(Rand.ByCurve(Pawn.RaceProps.litterSizeCurve), 1f); + } + catch (NullReferenceException) + { + eggnum = 1f; + } + catch (ArgumentException e) + { + Log.WarningOnce($"Invalid litterSizeCurve for {Pawn.def}: {e}", 642201874 + Pawn.thingIDNumber); + eggnum = 1f; + } + eggnum *= ovulationFactor; + int toOvulate = Math.Max(1, (int)eggnum + eggstack); + + int ovulated = 0; + for (int i = 0; i < toOvulate; i++) + if (i < eggstack || Rand.Chance(OvulationChance)) // eggstack comes from drugs and are guaranteed ovulated + { + eggs.Add(new Egg((int)(EggLifespanTicks / CycleFactor))); + ++ovulated; + } + ovarypower -= ovulated; + eggstack = 0; + if (Configurations.Debug && ovulated < toOvulate) + Log.Message($"{Pawn} ovulated {ovulated}/{toOvulate} eggs ({OvulationChance.ToStringPercent()} chance)"); + + GoNextStage(Stage.Luteal); + } + + protected virtual void LutealAction() + { + if (curStageTicks >= currentIntervalTicks) + { + eggs.Clear(); + if (EggHealth < 1f / 4f || (EggHealth < 1f / 3f && Rand.Chance(0.3f))) //skips bleeding + { + GoNextStage(Stage.Follicular); + } + else + { + GoFollicularOrBleeding(); + } + } + else if (!eggs.NullOrEmpty()) + { + FertilizationCheck(); + EggDecay(); + if (Implant()) + { + GoNextStage(Stage.Pregnant); + } + else + { + AdvanceStageTime(); + } + } + else + { + AdvanceStageTime(); + } + + } + + protected virtual void BleedingAction() + { + if (curStageTicks >= currentIntervalTicks || noBleeding) + { + Hediff hediff = Pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_MenstrualCramp); + if (hediff != null && !Pawn.GetMenstruationComps().Any(comp => comp != this && comp.curStage == Stage.Bleeding)) Pawn.health.RemoveHediff(hediff); + int totalFollicularTicks = PeriodRandomizer(Stage.Follicular); // The total amount of time for both bleeding and follicular + if (totalFollicularTicks <= currentIntervalTicks) // We've bled for so long that we completely missed the follicular phase + GoOvulatoryStage(); + else + { + GoNextStage(Stage.Follicular, totalFollicularTicks - currentIntervalTicks); // I.e., the remaining follicular time equals the total minus the bleeding time elapsed + } + } + else + { + if (curStageTicks < currentIntervalTicks / 4) BleedOut(); + AdvanceStageTime(); + } + } + + protected virtual void PregnantAction() + { + if (!eggs.NullOrEmpty()) + { + FertilizationCheck(); + EggDecay(); + Implant(); + } + + if (Pregnancy != null) + curStageTicks += TickInterval; + else + GoNextStage(Stage.Recover); + } + + protected virtual void RecoverAction() + { + if (curStageTicks >= currentIntervalTicks) + { + if (ShouldBeInfertile()) + { + GoNextStage(Stage.Infertile); + } + else if (!IsBreedingSeason()) + { + GoNextStage(Stage.Anestrus); + } + else + { + GoNextStage(Stage.Follicular); + } + } + else + { + AdvanceStageTime(); + } + } + + protected virtual void InfertileAction() + { + if (ShouldBeInfertile()) + return; + else if (IsBreedingSeason()) + GoNextStage(Stage.Follicular); + else + GoNextStage(Stage.Anestrus); + } + + protected virtual void AnestrusAction() + { + if (IsBreedingSeason()) + { + GoFollicularOrBleeding(); + } + } + + protected virtual void ThoughtCumInside(Pawn cummer) + { + if (!xxx.is_human(Pawn) || !xxx.is_human(cummer)) return; + + MemoryThoughtHandler cummerMemories = cummer.needs.mood.thoughts.memories; + MemoryThoughtHandler pawnMemories = Pawn.needs.mood.thoughts.memories; + + if (cummer.IsProPregnancy(out Precept preceptm) || (cummer.IsTeratophile() != (Pawn.GetStatValue(StatDefOf.PawnBeauty) >= 0))) + { + if (cummer.relations.OpinionOf(Pawn) <= -5) + cummerMemories.TryGainMemory(VariousDefOf.HaterCameInsideM, Pawn); + else if (preceptm != null) + cummerMemories.TryGainMemory(VariousDefOf.CameInsideMIdeo, Pawn, preceptm); + else + cummerMemories.TryGainMemory(VariousDefOf.CameInsideM, Pawn); + } + + if (IsDangerDay) + { + if (Pawn.IsProPregnancy(out Precept preceptf)) + { + if (preceptf != null) + { + if (Pawn.relations.OpinionOf(cummer) <= -5) + pawnMemories.TryGainMemory(VariousDefOf.HaterCameInsideFIdeo, cummer, preceptf); + else + pawnMemories.TryGainMemory(VariousDefOf.CameInsideFIdeo, cummer, preceptf); + } + else pawnMemories.TryGainMemory(VariousDefOf.CameInsideFFetish, cummer); + } + else if (Pawn.relations.OpinionOf(cummer) <= -5) + pawnMemories.TryGainMemory(VariousDefOf.HaterCameInsideF, cummer); + else if (Pawn.IsInEstrus() && Pawn.relations.OpinionOf(cummer) < RJWHookupSettings.MinimumRelationshipToHookup) + pawnMemories.TryGainMemory(VariousDefOf.HaterCameInsideFEstrus, cummer); + else if (!Pawn.relations.DirectRelationExists(PawnRelationDefOf.Spouse, cummer) && !Pawn.relations.DirectRelationExists(PawnRelationDefOf.Fiance, cummer)) + { + if (Pawn.health.capacities.GetLevel(xxx.reproduction) < 0.50f) pawnMemories.TryGainMemory(VariousDefOf.CameInsideFLowFert, cummer); + else pawnMemories.TryGainMemory(VariousDefOf.CameInsideF, cummer); + } + } + else + { + if (Pawn.IsProPregnancy(out Precept _)) + pawnMemories.TryGainMemory(VariousDefOf.CameInsideFFetishSafe, cummer); + else if (Pawn.relations.OpinionOf(cummer) <= -5) + pawnMemories.TryGainMemory(VariousDefOf.HaterCameInsideFSafe, cummer); + } + } + + protected virtual void TaleCumInside(Pawn cummer) + { + // Only make the tale for human-on-human, consentual sex. Otherwise the art just gets too hard to phrase properly + if (!xxx.is_human(Pawn) || !xxx.is_human(cummer) || Pawn == cummer) return; + if (Pawn.CurJobDef != xxx.casual_sex && Pawn.CurJobDef != xxx.gettin_loved) return; + if (!(Pawn.IsColonist || Pawn.IsPrisonerOfColony) && !(cummer.IsColonist || cummer.IsPrisonerOfColony)) return; + if (!IsDangerDay) return; + TaleRecorder.RecordTale(VariousDefOf.TaleCameInside, new object[] { cummer, Pawn }); + } + + public void GoNextStage(Stage nextstage, int? stageTicks = null) + { + curStageTicks = 0; + currentIntervalTicks = stageTicks ?? PeriodRandomizer(nextstage); + curStage = nextstage; + } + + protected virtual void GoOvulatoryStage() + { + GoNextStage(Stage.Ovulatory); + } + + protected void GoFollicularOrBleeding() + { + if (Props.bleedingIntervalDays == 0 || noBleeding) + { + GoNextStage(Stage.Follicular); + } + else + { + GoNextStage(Stage.Bleeding); + if (crampPain >= 0.05f) + { + AddCrampPain(); + } + } + } + + protected int PeriodRandomizer(Stage stage) + { + float variabilityFactor = (EggHealth < 1.0f) ? 6.0f : 1.0f; + // Most cycle lengthening or shortening occurs in the follicular phase, so weight towards that + switch (stage) + { + case Stage.Follicular: + return (int)(Utility.VariationRange(Props.follicularIntervalDays * GenDate.TicksPerDay, cycleVariability * 1.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 1.5f)); + case Stage.Ovulatory: + return Props.ovulationIntervalHours * GenDate.TicksPerHour; // No variability for now + case Stage.Luteal: + return (int)(Utility.VariationRange(Props.lutealIntervalDays * GenDate.TicksPerDay, cycleVariability * 0.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 0.5f)); + case Stage.Bleeding: + return (int)(Utility.VariationRange(Props.bleedingIntervalDays * GenDate.TicksPerDay, cycleVariability * 0.5f * variabilityFactor) / (1 + (cycleSpeed - 1) * 0.5f)); + case Stage.Recover: + return (int)Utility.VariationRange(Props.recoveryIntervalDays * GenDate.TicksPerDay, 0.05f); + case Stage.Pregnant: + return (int)(MenstruationUtility.GestationHours(pregnancy) * GenDate.TicksPerHour); + default: + return 1; + } + } + + protected float InterspeciesImplantFactor(Pawn fertilizer) + { + if (fertilizer.def.defName == Pawn.def.defName) return 1.0f; + else + { + if (RJWPregnancySettings.complex_interspecies) return SexUtility.BodySimilarity(Pawn, fertilizer); + else return RJWPregnancySettings.interspecies_impregnation_modifier; + } + } + + protected float PainRandomizer() + { + float rand = Rand.Range(0.0f, 1.0f); + if (rand < 0.01f) return Rand.Range(0.0f, 0.2f); + else if (rand < 0.2f) return Rand.Range(0.1f, 0.2f); + else if (rand < 0.8f) return Rand.Range(0.2f, 0.4f); + else if (rand < 0.95f) return Rand.Range(0.4f, 0.6f); + else return Rand.Range(0.6f, 1.0f); + } + + protected virtual float RandomOvulationChance => (float)Props.ovulationIntervalHours / GenDate.HoursPerDay; + + protected Stage RandomStage() + { + Stage stage = Rand.ElementByWeight( + Stage.Follicular, Props.follicularIntervalDays - Props.bleedingIntervalDays, + Stage.Ovulatory, RandomOvulationChance, + Stage.Luteal, Props.lutealIntervalDays, + Stage.Bleeding, Props.bleedingIntervalDays); + + switch (stage) + { + case Stage.Follicular: + curStageTicks = Rand.Range(0, (Props.follicularIntervalDays - Props.bleedingIntervalDays) * GenDate.TicksPerDay); + break; + case Stage.Ovulatory: + curStageTicks = Rand.Range(0, Props.ovulationIntervalHours * GenDate.TicksPerHour); + break; + case Stage.Luteal: + curStageTicks = Rand.Range(0, Props.lutealIntervalDays * GenDate.TicksPerDay); + break; + case Stage.Bleeding: + curStageTicks = Rand.Range(0, Props.bleedingIntervalDays * GenDate.TicksPerDay); + break; + } + return stage; + } + + // Searches for a pregnancy unclaimed by any womb and put it in this one + public void TakeLoosePregnancy() + { + if (pregnancy != null) return; + + IEnumerable pregnancies = Pawn.health.hediffSet.hediffs.Where(hediff => + hediff is Hediff_BasePregnancy || + hediff is Hediff_Pregnant || + hediff is Hediff_Labor || + hediff is Hediff_LaborPushing); + + pregnancy = + pregnancies.Except( + Pawn.GetMenstruationComps().Select(comp => comp.pregnancy).Where(preg => preg != null) + ).FirstOrDefault(); + if (pregnancy != null) + GoNextStage(Stage.Pregnant); + } + + public virtual void CopyCycleProperties(HediffComp_Menstruation original) + { + cycleSpeed = original.cycleSpeed; + cycleVariability = original.cycleVariability; + ovarypower = original.ovarypower; + crampPain = original.crampPain; + } + + public int EggsRestoredPerBiosculptor(float yearsWorth) + { + return Math.Max(1, (int)(RaceCyclesPerYear() * yearsWorth * AverageLitterSize())); + } + + public void RestoreEggs(float yearsWorth) + { + ovarypower += EggsRestoredPerBiosculptor(yearsWorth); + } + + public class Egg : IExposable + { + public bool fertilized; + public int lifeSpanTicks; // Actual ticks scaled by cycleAcceleration + public Pawn fertilizer; + public int ageTicks; + public int ticksSinceFertilization = 0; + + public Egg() + { + fertilized = false; + lifeSpanTicks = (int)(VariousDefOf.HumanVaginaCompProperties.eggLifespanDays * GenDate.TicksPerDay * Configurations.EggLifespanMultiplier); + fertilizer = null; + ageTicks = 0; + } + + public Egg(int lifespanticks) + { + fertilized = false; + lifeSpanTicks = (int)(lifespanticks * Configurations.EggLifespanMultiplier); + fertilizer = null; + ageTicks = 0; + } + + public void ExposeData() + { + if (Scribe.mode == LoadSaveMode.LoadingVars) + { + int lifespanhrs = -1; + int position = -1; + Scribe_Values.Look(ref lifespanhrs, "lifespanhrs", lifespanhrs, true); + Scribe_Values.Look(ref position, "position", position, true); + if (lifespanhrs >= 0) lifeSpanTicks = lifespanhrs * GenDate.TicksPerHour; + if (position >= 0) ageTicks = position * GenDate.TicksPerHour; + } + Scribe_References.Look(ref fertilizer, "fertilizer", true); + Scribe_Values.Look(ref fertilized, "fertilized", false); + Scribe_Values.Look(ref lifeSpanTicks, "lifeSpanTicks", lifeSpanTicks, true); + Scribe_Values.Look(ref ageTicks, "ageTicks", ageTicks, true); + Scribe_Values.Look(ref ticksSinceFertilization, "ticksSinceFertilization", 0); + if (ticksSinceFertilization == 0 && Scribe.mode == LoadSaveMode.LoadingVars) + { + // A bit awkward to do this twice, but it prevents ticksSinceFertilization from getting overwritten on a fertstage load + int fertstage = -1; + Scribe_Values.Look(ref fertstage, "fertstage", fertstage, true); + if (fertstage >= 0) ticksSinceFertilization = fertstage * GenDate.TicksPerHour; + } + } + } + } + + public class HediffComp_Anus : HediffComp + { + public CompProperties_Anus Props => (CompProperties_Anus)props; + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PeriodicOvulator.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PeriodicOvulator.cs new file mode 100644 index 0000000..cfb9a16 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PeriodicOvulator.cs @@ -0,0 +1,120 @@ +using RimWorld; +using Verse; + +namespace RJW_Menstruation +{ + public class CompProperties_PeriodicOvulator : CompProperties_Menstruation + { + public FloatRange cycleIntervalDays; // From the start of one cycle to the start of the next + + public CompProperties_PeriodicOvulator() + { + compClass = typeof(HediffComp_PeriodicOvulator); + } + } + + public class HediffComp_PeriodicOvulator : HediffComp_Menstruation + { + public int ticksToNextCycle = -100000; + public int averageCycleIntervalTicks = -1; + + public new CompProperties_PeriodicOvulator Props; + + protected override void PreInitialize() + { + base.PreInitialize(); + Props = (CompProperties_PeriodicOvulator)props; + } + + protected override void InitializeExtraValues() + { + base.InitializeExtraValues(); + if (averageCycleIntervalTicks < 0) + { + averageCycleIntervalTicks = (int)(Props.cycleIntervalDays.RandomInRange * GenDate.TicksPerDay / cycleSpeed); + if (ticksToNextCycle < -50000) + ticksToNextCycle = Rand.Range(0, averageCycleIntervalTicks); + // Make the cutoff halfway into cycle, just to be sure there isn't a double-cycle the first time + if ((curStage == Stage.Follicular || curStage == Stage.Ovulatory || curStage == Stage.Luteal || curStage == Stage.Bleeding) + && (averageCycleIntervalTicks - ticksToNextCycle) / 2 >= GenDate.TicksPerDay * (Props.follicularIntervalDays + Props.lutealIntervalDays) / cycleSpeed) + GoNextStage(Stage.Anestrus); + } + } + + protected override float RaceCyclesPerYear() + { + // Don't bother trying to work seasonal breeding into the math + // Base it off of the shortest cycle interval of the vagina + return GenDate.DaysPerYear / (Props.cycleIntervalDays.TrueMin / Configurations.CycleAccelerationDefault); + } + + protected override void BeforeSimulator() + { + base.BeforeSimulator(); + if (ticksToNextCycle > 0) ticksToNextCycle -= TickInterval * Configurations.CycleAcceleration; + } + + public override void CompExposeData() + { + base.CompExposeData(); + if (Scribe.mode == LoadSaveMode.LoadingVars) + { + int hoursToNextCycle = -1; + int averageCycleIntervalHours = -1; + Scribe_Values.Look(ref hoursToNextCycle, "hoursToNextCycle", hoursToNextCycle, true); + Scribe_Values.Look(ref averageCycleIntervalHours, "averageCycleIntervalHours", averageCycleIntervalHours, true); + if (hoursToNextCycle >= 0) ticksToNextCycle = hoursToNextCycle * GenDate.TicksPerHour; + if (averageCycleIntervalHours >= 0) averageCycleIntervalTicks = averageCycleIntervalHours * GenDate.TicksPerHour; + } + Scribe_Values.Look(ref ticksToNextCycle, "ticksToNextCycle", ticksToNextCycle, true); + Scribe_Values.Look(ref averageCycleIntervalTicks, "averageCycleIntervalTicks", averageCycleIntervalTicks, true); + } + + protected override int TicksToNextStage() + { + if (curStage == Stage.Anestrus && ticksToNextCycle > 0) return ticksToNextCycle / Configurations.CycleAcceleration; + else return base.TicksToNextStage(); + } + + protected override void LutealAction() + { + base.LutealAction(); + if (curStage == Stage.Follicular) + GoNextStage(Stage.Anestrus); + } + + protected override void BleedingAction() + { + base.BleedingAction(); + if (curStage != Stage.Bleeding) + { + estrusflag = false; + GoNextStage(Stage.Anestrus); + } + } + + protected override void PregnantAction() + { + base.PregnantAction(); + if (curStage != Stage.Pregnant) + // Go halfway into the cycle + ticksToNextCycle = (int)Utility.VariationRange(averageCycleIntervalTicks, cycleVariability) / 2; + } + + protected override void AnestrusAction() + { + if (ticksToNextCycle <= 0 && IsBreedingSeason()) + { + ticksToNextCycle = (int)Utility.VariationRange(averageCycleIntervalTicks, cycleVariability); + GoNextStage(Stage.Follicular); + } + } + + public override void CopyCycleProperties(HediffComp_Menstruation original) + { + base.CopyCycleProperties(original); + if (original is HediffComp_PeriodicOvulator comp) + averageCycleIntervalTicks = comp.averageCycleIntervalTicks; + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Pheromones.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Pheromones.cs new file mode 100644 index 0000000..130edcc --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_Pheromones.cs @@ -0,0 +1,106 @@ + + +using RimWorld; +using RimWorld.Planet; +using rjw; +using System; +using System.Collections.Generic; +using System.Linq; +using Verse; + +namespace RJW_Menstruation +{ + public class CompProperties_Pheromones : HediffCompProperties + { + public float daysToMaxSeverity; + public float range; + + public CompProperties_Pheromones() + { + compClass = typeof(HediffComp_Pheromones); + } + } + + public class HediffComp_Pheromones : HediffComp + { + public CompProperties_Pheromones Props => (CompProperties_Pheromones)props; + public const int emitInterval = GenTicks.TickRareInterval; + public const float emitRatio = (float)emitInterval / GenDate.TicksPerDay; + + public override void CompPostTick(ref float severityAdjustment) + { + try + { + if (!Configurations.EnablePheromones) return; + if (!Pawn.RaceProps.Humanlike && (!Configurations.EnableAnimalCycle || Configurations.AnimalPheromoneEffect <= 0.0f)) return; + if (!Pawn.IsHashIntervalTick(emitInterval)) return; + if (!Pawn.SpawnedOrAnyParentSpawned) return; + + foreach (Pawn pawn in AffectedPawns()) + ApplyEffectToPawn(pawn); + } + catch (Exception ex) + { + Log.Error($"Error when trying to emit pheromones from pawn {Pawn}: {ex}"); + } + } + + protected IEnumerable AffectedPawns() + { + if(Pawn.GetCaravan() is Caravan caravan) + foreach (Pawn p in caravan.PawnsListForReading.Where(p => p != Pawn)) yield return p; + Map mapHeld = Pawn.MapHeld; + if (mapHeld == null) yield break; + foreach (Pawn pawn in mapHeld.mapPawns.AllPawnsSpawned) + { + if (pawn == Pawn) continue; + if (!pawn.RaceProps.Humanlike) continue; + if (Pawn.PositionHeld.InHorDistOf(pawn.PositionHeld, Props.range) && Pawn.GetRoom() == pawn.GetRoom()) + yield return pawn; + } + } + + protected float GetEffectOnPawn(Pawn target) + { + if (target.Suspended || target.Dead) return 0.0f; + if (target.needs?.TryGetNeed(VariousDefOf.SexNeed) == null) return 0.0f; + if (!xxx.can_do_loving(target)) return 0.0f; + if (target.story?.traits.HasTrait(TraitDefOf.Asexual) ?? true) return 0.0f; + float penisEffect; + if (Genital_Helper.has_penis_fertile(target)) penisEffect = 1.0f; + else if (target.gender == Gender.Male) penisEffect = 0.25f; + else return 0.0f; + + BodyDef body = target.RaceProps.body; + if (!PawnCapacityUtility.BodyCanEverDoCapacity(body, PawnCapacityDefOf.Breathing)) return 0.0f; + HediffSet hediffs = target.health.hediffSet; + float breathingEffect = PawnCapacityUtility.CalculateCapacityLevel(hediffs, PawnCapacityDefOf.Breathing); + float noseEffect = 1.0f; + List noses = body.GetPartsWithDef(BodyPartDefOf.Nose); + if (noses.Any()) // if the body doesn't have a nose but still breathes, then let it be affected + noseEffect = noses.Average(nose => PawnCapacityUtility.CalculatePartEfficiency(hediffs, nose)); + + return penisEffect * breathingEffect * noseEffect; + } + + protected void ApplyEffectToPawn(Pawn target) + { + float intensity = GetEffectOnPawn(target); + if (intensity <= 0.0f) return; + Hediff pheromones = target.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.Hediff_AffectedByPheromones); + float decay = VariousDefOf.Hediff_AffectedByPheromones.CompProps().severityPerDay; + float raiseSeverityPerDay = intensity / Props.daysToMaxSeverity - decay; // Desired increase plus enough to overcome pheromone decay + if (!Pawn.RaceProps.Humanlike) raiseSeverityPerDay *= Configurations.AnimalPheromoneEffect; + float amountToApply = emitRatio * raiseSeverityPerDay; + if (pheromones != null) + pheromones.Severity += amountToApply; + else + { + pheromones = HediffMaker.MakeHediff(VariousDefOf.Hediff_AffectedByPheromones, target); + pheromones.Severity = amountToApply; + target.health.AddHediff(pheromones); + } + return; + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PregeneratedBabies.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PregeneratedBabies.cs new file mode 100644 index 0000000..0a919c4 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/HediffComp_PregeneratedBabies.cs @@ -0,0 +1,306 @@ +using HarmonyLib; +using RimWorld; +using rjw; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using Verse; + +namespace RJW_Menstruation +{ + public class HediffComp_PregeneratedBabies : HediffComp + { + public List babies; + // Unused, but can't hurt to track + protected Dictionary enzygoticSiblings; + + protected static readonly MethodInfo RandomLastName = typeof(PregnancyUtility).GetMethod("RandomLastName", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(Pawn), typeof(Pawn), typeof(Pawn) }, null); + + public bool HasBaby + { + get => !babies.NullOrEmpty(); + } + + public Pawn PopBaby() + { + if (babies.NullOrEmpty()) return null; + + Pawn firstBaby = babies.First(); + babies.Remove(firstBaby); + return firstBaby; + } + + public override void CompPostPostRemoved() + { + // At this point in the hediff removal process, the new hediff is already on the pawn + // But it is possible that there is no new hediff (be it a birth, miscarrage, or dev edit) + base.CompPostPostRemoved(); + + // Send the babies from this comp to the new one + switch (parent) + { + case Hediff_Pregnant hediff_Pregnant: + Hediff_Labor labor = (Hediff_Labor)Pawn.health.hediffSet.hediffs.Where(hediff => hediff is Hediff_Labor).MaxByWithFallback(hediff => hediff.loadID); + HediffComp_PregeneratedBabies laborcomp = labor?.TryGetComp(); + if (laborcomp == null) return; + laborcomp.babies = this.babies; + laborcomp.enzygoticSiblings = this.enzygoticSiblings; + break; + case Hediff_Labor hediff_Labor: + Hediff_LaborPushing pushing = (Hediff_LaborPushing)Pawn.health.hediffSet.hediffs.Where(hediff => hediff is Hediff_LaborPushing).MaxByWithFallback(hediff => hediff.loadID); + HediffComp_PregeneratedBabies pushingcomp = pushing?.TryGetComp(); + if (pushingcomp == null) return; + pushingcomp.babies = this.babies; + pushingcomp.enzygoticSiblings = this.enzygoticSiblings; + break; + case Hediff_LaborPushing hediff_LaborPushing: + // Nothing to do, the laborpushing transpiler will pick it up + break; + } + } + + public override void CompExposeData() + { + base.CompExposeData(); + Scribe_Collections.Look(ref babies, "babies", LookMode.Deep); + Scribe_Collections.Look(ref enzygoticSiblings, "enzygoticSiblings", keyLookMode: LookMode.Reference, valueLookMode: LookMode.Reference); + } + + + public void AddNewBaby(Pawn mother, Pawn father) + { + if (babies == null) babies = new List(); + PawnKindDef babyPawnKind = PregnancyCommon.BabyPawnKindDecider(mother, father, true); + PawnGenerationRequest request = new PawnGenerationRequest + ( + kind: babyPawnKind, + faction: mother.Faction, + allowDowned: true, + // fixedLastName seems not to actually do anything, as we eventually end up in PawnBioAndNameGenerator.NameResolvedFrom, which ignores its forcedLastName argument + fixedLastName: (string)RandomLastName.Invoke(null, new object[] { mother, mother, xxx.is_human(father) ? father : null }), + forceNoIdeo: true, + forcedEndogenes: PregnancyUtility.GetInheritedGenes(father, mother), + forcedXenotype: XenotypeDefOf.Baseliner, + developmentalStages: DevelopmentalStage.Newborn + ); + int division = 1; + Pawn firstbaby = null; + while (Rand.Chance(Configurations.EnzygoticTwinsChance) && division < Configurations.MaxEnzygoticTwins) division++; + if (division > 1 && enzygoticSiblings == null) enzygoticSiblings = new Dictionary(); + for (int i = 0; i < division; i++) + { + Pawn baby = PawnGenerator.GeneratePawn(request); + if (baby == null) break; + PregnancyCommon.SetupBabyXenotype(mother, father, baby); // Probably redundant with Biotech post-birth xenotyping + baby.Drawer.renderer.graphics.ResolveAllGraphics(); + if (division > 1) + { + if (i == 0) + { + firstbaby = baby; + request.FixedGender = baby.gender; + request.ForcedEndogenes = baby.genes?.Endogenes.Select(gene => gene.def).ToList(); + } + else + { + enzygoticSiblings.Add(baby, firstbaby); + + if (baby.story != null) + { + baby.story.headType = firstbaby.story.headType; + baby.story.hairDef = firstbaby.story.hairDef; + baby.story.HairColor = firstbaby.story.HairColor; + baby.story.bodyType = firstbaby.story.bodyType; + baby.story.furDef = firstbaby.story.furDef; + baby.story.skinColorOverride = firstbaby.story.skinColorOverride; + } + + if (baby.genes != null) + { + baby.genes.SetXenotypeDirect(firstbaby.genes.Xenotype); + baby.genes.xenotypeName = firstbaby.genes.xenotypeName; + baby.genes.iconDef = firstbaby.genes.iconDef; + baby.genes.hybrid = firstbaby.genes.hybrid; + } + + if (baby.IsHAR()) + HARCompatibility.CopyHARProperties(baby, firstbaby); + + // MultiplePregnancy calls this post-birth because RJW resets private parts + // So xenotype things shouldn't be shared + PregnancyCommon.ProcessIdenticalSibling(baby, firstbaby); + } + } + babies.Add(baby); + // These get cleared out later, but setting the relations now will help keep track of things. + baby.SetMother(mother); + if (mother != father) + { + if (father.gender != Gender.Female) baby.SetFather(father); + else baby.relations.AddDirectRelation(PawnRelationDefOf.Parent, father); + } + } + } + } + + [HarmonyPatch(typeof(PregnancyUtility), nameof(PregnancyUtility.ApplyBirthOutcome))] + public static class ApplyBirthOutcome_PregeneratedBabies_Patch + { + private static Pawn GetPregeneratedBaby(PawnGenerationRequest request, Thing birtherThing) + { + // Don't test for the config set here. We can do it at the functions that call ApplyBirthOutcome + // Easier to work out twins that way + + // From e.g. a vat + if (!(birtherThing is Pawn mother) || !xxx.is_human(mother)) + return PawnGenerator.GeneratePawn(request); + + // No babies found. Could be an unmodified pregnancy + HediffComp_PregeneratedBabies comp = mother.health.hediffSet.GetFirstHediff()?.TryGetComp(); + if (comp == null || !comp.HasBaby) + return PawnGenerator.GeneratePawn(request); + + Pawn baby = comp.PopBaby(); + if (baby == null) return PawnGenerator.GeneratePawn(request); // Shouldn't happen + baby.ageTracker.AgeBiologicalTicks = 0; + baby.ageTracker.AgeChronologicalTicks = 0; + baby.babyNamingDeadline = Find.TickManager.TicksGame + GenDate.TicksPerDay; + if (request.ForceDead) baby.Kill(null, null); + return baby; + } + + private static readonly MethodInfo ApplyBirthOutcome = typeof(PregnancyUtility).GetMethod(nameof(PregnancyUtility.ApplyBirthOutcome)); + private static readonly int birtherThing = ApplyBirthOutcome.GetParameters().FirstIndexOf(parameter => parameter.Name == "birtherThing" && parameter.ParameterType == typeof(Thing)); + private static readonly MethodInfo GeneratePawn = typeof(PawnGenerator).GetMethod(nameof(PawnGenerator.GeneratePawn), new Type[] {typeof (PawnGenerationRequest)}); + + public static IEnumerable Transpiler(IEnumerable instructions) + { + if (birtherThing < 0) throw new InvalidOperationException("Could not locate index of birtherThing"); + if (GeneratePawn?.ReturnType != typeof(Pawn)) throw new InvalidOperationException("GeneratePawn not found"); + foreach (CodeInstruction instruction in instructions) + { + if (instruction.Calls(GeneratePawn)) + { + yield return new CodeInstruction(OpCodes.Ldarg, birtherThing); + yield return CodeInstruction.Call(typeof(ApplyBirthOutcome_PregeneratedBabies_Patch), nameof(GetPregeneratedBaby)); + } + else yield return instruction; + } + } + } + + [HarmonyPatch(typeof(Hediff_LaborPushing), nameof(Hediff_LaborPushing.PreRemoved))] + public static class Hediff_LaborPushing_PreRemoved_Patch + { + private static Thing ApplyBirthLoop(OutcomeChance outcome, float quality, Precept_Ritual ritual, List genes, Pawn geneticMother, Thing birtherThing, Pawn father, Pawn doctor, LordJob_Ritual lordJobRitual, RitualRoleAssignments assignments) + { + if (birtherThing is Pawn mother) + { + HediffComp_PregeneratedBabies comp = mother.health.hediffSet.GetFirstHediff().TryGetComp(); + if (comp?.HasBaby ?? false) + { + OutcomeChance thisOutcome = outcome; + Precept_Ritual precept_Ritual = (Precept_Ritual)comp.Pawn.Ideo.GetPrecept(PreceptDefOf.ChildBirth); + float birthQuality = PregnancyUtility.GetBirthQualityFor(mother); + do + { + Pawn baby = comp.babies[0]; + Pawn thisFather = baby.GetFather() ?? father; + baby.relations.ClearAllRelations(); // To keep ApplyBirthOutcome from erroring when it tries to set up relations + + PregnancyUtility.ApplyBirthOutcome(thisOutcome, quality, ritual, genes, geneticMother, birtherThing, thisFather, doctor, lordJobRitual, assignments); + // No more babies if mom dies halfway through. Unrealistic maybe, but saves a lot of headache in ApplyBirthOutcome + if (mother.Dead) break; + if (xxx.is_human(baby)) + mother.records.Increment(xxx.CountOfBirthHuman); + else if (xxx.is_animal(baby)) + mother.records.Increment(xxx.CountOfBirthAnimal); + thisOutcome = ((RitualOutcomeEffectWorker_ChildBirth)precept_Ritual.outcomeEffect).GetOutcome(birthQuality, null); + } while (comp.HasBaby); + + // PreRemoved doesn't use the return value + return null; + } + } + + return PregnancyUtility.ApplyBirthOutcome(outcome, quality, ritual, genes, geneticMother, birtherThing, father, doctor, lordJobRitual, assignments); + } + + private static readonly MethodInfo ApplyBirthOutcome = typeof(PregnancyUtility).GetMethod(nameof(PregnancyUtility.ApplyBirthOutcome), + new Type[] {typeof(OutcomeChance), typeof(float), typeof(Precept_Ritual), typeof(List), typeof(Pawn), typeof(Thing), typeof(Pawn), typeof(Pawn), typeof(LordJob_Ritual), typeof(RitualRoleAssignments)}); + public static IEnumerable Transpiler(IEnumerable instructions) + { + if (ApplyBirthOutcome?.ReturnType != typeof(Thing)) throw new InvalidOperationException("ApplyBirthOutcome not found"); + foreach (CodeInstruction instruction in instructions) + { + if (instruction.Calls(ApplyBirthOutcome)) + yield return CodeInstruction.Call(typeof(Hediff_LaborPushing_PreRemoved_Patch), nameof(Hediff_LaborPushing_PreRemoved_Patch.ApplyBirthLoop)); + else yield return instruction; + } + } + } + + [HarmonyPatch(typeof(RitualOutcomeEffectWorker_ChildBirth), nameof (RitualOutcomeEffectWorker_ChildBirth.Apply))] + public static class Ritual_ChildBirth_Apply_Patch + { + private static Thing ApplyBirthLoop(OutcomeChance outcome, float quality, Precept_Ritual ritual, List genes, Pawn geneticMother, Thing birtherThing, Pawn father, Pawn doctor, LordJob_Ritual lordJobRitual, RitualRoleAssignments assignments) + { + if (birtherThing is Pawn mother) + { + HediffComp_PregeneratedBabies comp = mother.health.hediffSet.GetFirstHediff().TryGetComp(); + if (comp?.HasBaby ?? false) + { + // Much the same as the other one + + // Don't reroll the outcome every time, I think + // This is all one ritual, so every baby has the same ritual outcome + // I don't think this will add the ritual memory every time? + // Though even if it does, that's probably okay. More babies more memories after all + do + { + Pawn baby = comp.babies[0]; + Pawn thisFather = baby.GetFather() ?? father; + baby.relations.ClearAllRelations(); + + PregnancyUtility.ApplyBirthOutcome(outcome, quality, ritual, genes, geneticMother, birtherThing, thisFather, doctor, lordJobRitual, assignments); + if (mother.Dead) break; + if (xxx.is_human(baby)) + mother.records.Increment(xxx.CountOfBirthHuman); + else if (xxx.is_animal(baby)) + mother.records.Increment(xxx.CountOfBirthAnimal); + } while (comp.HasBaby); + + // The ritual version doesn't use the return value, either + return null; + } + } + return PregnancyUtility.ApplyBirthOutcome(outcome, quality, ritual, genes, geneticMother, birtherThing, father, doctor, lordJobRitual, assignments); + } + private static readonly MethodInfo ApplyBirthOutcome = typeof(PregnancyUtility).GetMethod(nameof(PregnancyUtility.ApplyBirthOutcome), + new Type[] { typeof(OutcomeChance), typeof(float), typeof(Precept_Ritual), typeof(List), typeof(Pawn), typeof(Thing), typeof(Pawn), typeof(Pawn), typeof(LordJob_Ritual), typeof(RitualRoleAssignments) }); + public static IEnumerable Transpiler(IEnumerable instructions) + { + if (ApplyBirthOutcome?.ReturnType != typeof(Thing)) throw new InvalidOperationException("ApplyBirthOutcome not found"); + foreach (CodeInstruction instruction in instructions) + { + if (instruction.Calls(ApplyBirthOutcome)) + yield return CodeInstruction.Call(typeof(Ritual_ChildBirth_Apply_Patch), nameof(Ritual_ChildBirth_Apply_Patch.ApplyBirthLoop)); + else yield return instruction; + } + } + } + + // HAR patches ApplyBirthOutcome to produce multiple babies based on the mother's littersize. But the pregenerated babies system already makes multiple babies + // So make it always consider the mother to have one baby + public static class HAR_LitterSize_Undo + { + public static void Postfix(ref int __result, Pawn mother) + { + if (Configurations.PregnancySource != Configurations.PregnancyType.Biotech || !Configurations.EnableBiotechTwins) return; + __result = 0; + return; + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/MenstruationUtility.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/MenstruationUtility.cs new file mode 100644 index 0000000..394c376 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/HediffComps/MenstruationUtility.cs @@ -0,0 +1,470 @@ +using RimWorld; +using rjw; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Verse; + +namespace RJW_Menstruation +{ + public static class MenstruationUtility + { + [Obsolete("This method is obsolete. Use GetMenstruationComps or a related function instead", false)] + public static HediffComp_Menstruation GetMenstruationComp(this Pawn pawn) + { + return pawn.GetFirstMenstruationComp(); + } + + public static IEnumerable GetMenstruationComps(this Pawn pawn) + { + List hedifflist = pawn.health.hediffSet.hediffs.FindAll(h => VariousDefOf.AllVaginas.Contains(h.def)); + if (hedifflist == null) yield break; + foreach (Hediff hediff in hedifflist) + { + HediffComp_Menstruation result = hediff.TryGetComp(); + if (result != null) yield return result; + } + } + + public static HediffComp_Menstruation GetFirstMenstruationComp(this Pawn pawn) + { + return pawn.GetMenstruationComps().FirstOrDefault(); + } + + public static HediffComp_Menstruation GetRandomMenstruationComp(this Pawn pawn) + { + return pawn.GetMenstruationComps().RandomElementWithFallback(); + } + + public static HediffComp_Menstruation GetFertileMenstruationComp(this Pawn pawn) + { + List comps = pawn.GetMenstruationComps().ToList(); + return comps.Where(c => c.IsDangerDay).RandomElementWithFallback() ?? comps.RandomElementWithFallback(); + } + + public static HediffComp_Menstruation GetMenstruationCompFromVagina(this Hediff vagina) + { + if (VariousDefOf.AllVaginas.Contains(vagina?.def)) + { + return vagina.TryGetComp(); + } + return null; + } + + public static HediffComp_Menstruation GetMenstruationCompFromPregnancy(this Hediff pregnancy) + { + return pregnancy?.pawn.GetMenstruationComps().FirstOrDefault(comp => comp.Pregnancy == pregnancy); + } + + public static HediffComp_Anus GetAnusComp(this Pawn pawn) + { + return pawn.health.hediffSet.hediffs.FirstOrDefault((Hediff h) => VariousDefOf.AllAnuses.Contains(h.def))?.TryGetComp(); + } + + [Obsolete("This method is obsolete and can cause ambiguity. Use GetMenstruationCompFromVagina or GetMenstruationCompFromPregnancy instead.", true)] + public static HediffComp_Menstruation GetMenstruationComp(Hediff hediff) + { + switch (hediff) + { + case Hediff_BasePregnancy rjwPreg: + return rjwPreg.GetMenstruationCompFromPregnancy(); + case Hediff_Pregnant vanillaPreg: + return vanillaPreg.GetMenstruationCompFromPregnancy(); + case Hediff_Labor vanillaLabor: + return vanillaLabor.GetMenstruationCompFromPregnancy(); + case Hediff_LaborPushing vanillaLaborPushing: + return vanillaLaborPushing.GetMenstruationCompFromPregnancy(); + case Hediff_PartBaseNatural rjwNatrual: + return rjwNatrual.GetMenstruationCompFromVagina(); + case Hediff_PartBaseArtifical rjwArtificial: + return rjwArtificial.GetMenstruationCompFromVagina(); + default: + Log.Warning("Obsolete GetMenstruationComp called with unknown hediff. Ensure your submods are up to date."); + return null; + } + } + + public static HediffComp_Anus GetAnusComp(this Hediff hediff) + { + if (hediff is Hediff_PartBaseNatural || hediff is Hediff_PartBaseArtifical) + { + return hediff.TryGetComp(); + } + return null; + } + + public static float GetFertilityChance(this HediffComp_Menstruation comp) + { + return 1.0f - Mathf.Pow(1.0f - Configurations.FertilizeChance, comp.TotalFertCum * comp.Props.basefertilizationChanceFactor); + } + + public static Texture2D GetPregnancyIcon(this HediffComp_Menstruation comp, Hediff hediff) + { + float gestationProgress = comp.StageProgress; + + ThingDef babydef; + int babycount; + HediffComp_PregeneratedBabies babiescomp = hediff?.TryGetComp(); + if (hediff is Hediff_MechanoidPregnancy) + { + babydef = VariousDefOf.Scyther; + babycount = 1; + } + else if (hediff is Hediff_BasePregnancy preg) + { + babydef = preg.babies?.FirstOrDefault()?.def ?? ThingDefOf.Human; + babycount = preg.babies?.Count ?? 1; + } + else if (babiescomp?.HasBaby ?? false) + { + babydef = babiescomp.babies.First().def; + babycount = babiescomp.babies.Count; + } + else + { + babydef = comp.Pawn.def; + babycount = 1; + } + + string fetustex = babydef.GetModExtension()?.fetusTexPath ?? "Fetus/Fetus_Default"; + string icon; + if (gestationProgress < 0.2f) icon = comp.WombTex + "_Implanted"; + else if (gestationProgress < 0.4f) icon = fetustex + "00"; + else if (gestationProgress < 0.5f) icon = fetustex + "01"; + else if (gestationProgress < 0.6f) icon = fetustex + "02"; + else if (gestationProgress < 0.7f) icon = fetustex + "03"; + else if (gestationProgress < 0.8f) icon = fetustex + "04"; + else icon = fetustex + "05"; + + return TryGetTwinsIcon(icon, babycount) ?? ContentFinder.Get(icon, true); + } + + public static Texture2D TryGetTwinsIcon(string path, int babycount) + { + for (int i = babycount; i > 1; i--) + { + Texture2D result = ContentFinder.Get(path + "_Multiplet_" + i, false); + if (result != null) return result; + } + return null; + } + + public static Texture2D GetCumIcon(this HediffComp_Menstruation comp) + { + Pawn pawn = comp.Pawn; + + List insectEggs = new List(); + comp.Pawn.health.hediffSet.GetHediffs(ref insectEggs); + if (insectEggs?.Sum(hediff => hediff.eggssize) > 1.0f) return null; // same logic as "Stuffed" in GetInsectEggedIcon + + string icon = comp.WombTex; + float cumpercent = comp.TotalCumPercent; + if (cumpercent < 0.001f) return ContentFinder.Get("Womb/Empty", true); + else if (cumpercent < 0.01f) icon += "_Cum_00"; + else if (cumpercent < 0.05f) icon += "_Cum_01"; + else if (cumpercent < 0.11f) icon += "_Cum_02"; + else if (cumpercent < 0.17f) icon += "_Cum_03"; + else if (cumpercent < 0.23f) icon += "_Cum_04"; + else if (cumpercent < 0.29f) icon += "_Cum_05"; + else if (cumpercent < 0.35f) icon += "_Cum_06"; + else if (cumpercent < 0.41f) icon += "_Cum_07"; + else if (cumpercent < 0.47f) icon += "_Cum_08"; + else if (cumpercent < 0.53f) icon += "_Cum_09"; + else if (cumpercent < 0.59f) icon += "_Cum_10"; + else if (cumpercent < 0.65f) icon += "_Cum_11"; + else if (cumpercent < 0.71f) icon += "_Cum_12"; + else if (cumpercent < 0.77f) icon += "_Cum_13"; + else if (cumpercent < 0.83f) icon += "_Cum_14"; + else if (cumpercent < 0.89f) icon += "_Cum_15"; + else if (cumpercent < 0.95f) icon += "_Cum_16"; + else icon += "_Cum_17"; + Texture2D cumtex = ContentFinder.Get(icon, true); + return cumtex; + } + public static Texture2D GetInsectEggedIcon(this HediffComp_Menstruation comp) + { + List hediffs = new List(); + comp.Pawn.health.hediffSet.GetHediffs(ref hediffs); + + if (hediffs.NullOrEmpty()) return null; + string path = "Womb/Insect_Egged/Womb_Egged_"; + + float sumSize = hediffs.Sum(hediff => hediff.eggssize); + if (sumSize > 1.0f) + { + path += "Stuffed_"; + if (sumSize < 1.0f) path += "00"; + else if (sumSize < 2.0f) path += "01"; + else if (sumSize < 2.5f) path += "02"; + else if (sumSize < 3.0f) path += "03"; + else path += "04"; + } + else + { + if(hediffs.Max(hediff => hediff.eggssize) > 0.3f) // The threshold for "large egg" in the debug + { + path += "L"; + if (hediffs.Count == 1) path += "00"; + else if (hediffs.Count == 2) path += "01"; + else path += "02"; + } + else + { + path += "S"; + if (hediffs.Count == 1) path += "00"; + else if (hediffs.Count == 2) path += "01"; + else if (hediffs.Count == 3) path += "02"; + else if (hediffs.Count == 4) path += "03"; + else path += "04"; + } + } + + return ContentFinder.Get(path); + } + public static Texture2D GetWombIcon(this HediffComp_Menstruation comp) + { + Texture2D wombtex = comp.GetInsectEggedIcon(); + if (wombtex != null) return wombtex; + string icon = comp.WombTex; + HediffComp_Menstruation.Stage stage = comp.curStage; + if (stage == HediffComp_Menstruation.Stage.Bleeding) icon += "_Bleeding"; + + wombtex = ContentFinder.Get(icon, true); + + return wombtex; + } + public static Texture2D GetOvaryIcon(this HediffComp_Menstruation comp) + { + const float ovaryChanceToShow_01 = 0.2f; + const float ovaryChanceToShow_02 = 0.8f; + float ovulatoryProgress; + bool isInduced = comp is HediffComp_InducedOvulator; + if (comp.curStage == HediffComp_Menstruation.Stage.Follicular && + isInduced && + comp.Pawn.jobs.curDriver is JobDriver_Sex job && + job.Sexprops != null && + !job.Sexprops.usedCondom && + (job.Sexprops.sexType == xxx.rjwSextype.Vaginal || job.Sexprops.sexType == xxx.rjwSextype.DoublePenetration)) + ovulatoryProgress = 0.0f; + else if (comp.curStage == HediffComp_Menstruation.Stage.Ovulatory) ovulatoryProgress = isInduced ? Mathf.Max(ovaryChanceToShow_01, comp.StageProgessNextUpdate) : comp.StageProgessNextUpdate; +// else if (comp.curStage == HediffComp_Menstruation.Stage.Luteal && comp.IsEggExist) return ContentFinder.Get("Ovaries/Ovary_02", true); + else return ContentFinder.Get("Womb/Empty", true); + + float combinedAppearance = ovulatoryProgress * comp.OvulationChance; + if (combinedAppearance >= ovaryChanceToShow_02 && comp.OvulationChance >= 1.0f) return ContentFinder.Get("Ovaries/Ovary_02", true); + else if (combinedAppearance >= ovaryChanceToShow_01) return ContentFinder.Get("Ovaries/Ovary_01", true); + else return ContentFinder.Get("Ovaries/Ovary_00", true); + } + public static Texture2D GetEggIcon(this HediffComp_Menstruation comp, bool includeOvary) + { + switch (comp.CurrentVisibleStage) + { + case HediffComp_Menstruation.Stage.Follicular: + case HediffComp_Menstruation.Stage.Ovulatory: + if (!includeOvary) break; + else return GetOvaryIcon(comp); + case HediffComp_Menstruation.Stage.Luteal: + if (!comp.IsEggExist) break; + int fertTime = comp.EggFertilizedTime; + if (fertTime >= 0) + { + if (fertTime <= GenDate.TicksPerHour * Configurations.CycleAcceleration) return ContentFinder.Get("Eggs/Egg_Fertilizing02", true); + else if (fertTime <= 18 * GenDate.TicksPerHour) return ContentFinder.Get("Eggs/Egg_Fertilized00", true); + else if (fertTime <= 54 * GenDate.TicksPerHour) return ContentFinder.Get("Eggs/Egg_Fertilized01", true); + else return ContentFinder.Get("Eggs/Egg_Fertilized02", true); + } + else if (includeOvary && comp.curStageTicks <= comp.Props.ovulationIntervalHours * 0.4f * GenDate.TicksPerHour) // Total about as long as it spent in Ovary_01 + { + return ContentFinder.Get("Ovaries/Ovary_02", true); + } + else if (comp.IsEggFertilizing) + { + if (comp.GetFertilityChance() < 0.5f) + return ContentFinder.Get("Eggs/Egg_Fertilizing00", true); + else + return ContentFinder.Get("Eggs/Egg_Fertilizing01", true); + } + else return ContentFinder.Get("Eggs/Egg", true); + case HediffComp_Menstruation.Stage.Pregnant: + if (comp.Pregnancy is Hediff_MechanoidPregnancy) break; + else if (comp.GetPregnancyProgress() < 0.2f) return ContentFinder.Get("Eggs/Egg_Implanted00", true); + else break; + } + return ContentFinder.Get("Womb/Empty", true); + } + + public static void DrawEggOverlay(this HediffComp_Menstruation comp, Rect wombRect, bool includeOvary) + { + Rect rect = new Rect(wombRect.xMax - wombRect.width / 3, wombRect.y, wombRect.width / 3, wombRect.width / 3); + GUI.color = Color.white; + GUI.DrawTexture(rect, comp.GetEggIcon(includeOvary), ScaleMode.ScaleToFit); + } + + + public static Texture2D GetGenitalIcon(this Pawn pawn, HediffComp_Menstruation comp) + { + Hediff hediff = comp?.parent; + if (hediff == null) return ContentFinder.Get("Genitals/Vagina00", true); + //HediffComp_Menstruation comp = hediff.GetMenstruationComp(); + string icon; + float severity = hediff.Severity; + if (comp != null) icon = comp.VagTex; + else icon = "Genitals/Vagina"; + + if (severity < 0.20f) icon += "00"; //micro + else if (severity < 0.30f) icon += "01"; //tight + else if (severity < 0.40f) icon += "02"; //tight + else if (severity < 0.47f) icon += "03"; //average + else if (severity < 0.53f) icon += "04"; //average + else if (severity < 0.60f) icon += "05"; //average + else if (severity < 0.70f) icon += "06"; //accomodating + else if (severity < 0.80f) icon += "07"; //accomodating + else if (severity < 0.87f) icon += "08"; //cavernous + else if (severity < 0.94f) icon += "09"; //cavernous + else if (severity < 1.01f) icon += "10"; //cavernous + else icon += "11"; //abyssal + + return ContentFinder.Get(icon, true); + } + + public static Texture2D GetAnalIcon(this Pawn pawn) + { + Hediff hediff = pawn.health.hediffSet.hediffs.FirstOrDefault(h => VariousDefOf.AllAnuses.Contains(h.def)) ?? + pawn.health.hediffSet.hediffs.FirstOrDefault(h => h.def.defName.ToLower().Contains("anus")); + if (hediff == null) return ContentFinder.Get("Genitals/Anal00", true); + + string icon = ((CompProperties_Anus)hediff.GetAnusComp()?.props)?.analTex ?? "Genitals/Anal"; + float severity = hediff.Severity; + + if (severity < 0.20f) icon += "00"; //micro + else if (severity < 0.40f) icon += "01"; //tight + else if (severity < 0.60f) icon += "02"; //average + else if (severity < 0.80f) icon += "03"; //accomodating + else if (severity < 1.01f) icon += "04"; //cavernous + else icon += "05"; //abyssal + + return ContentFinder.Get(icon, true); + } + + public static float GestationHours(this Hediff hediff) + { + if (hediff == null) + { + Log.Error("Tried to get gestation length without a pregnancy."); + return 1f; + } + else if (hediff is Hediff_BasePregnancy rjw_preg) + return (rjw_preg.p_end_tick - rjw_preg.p_start_tick) / GenDate.TicksPerHour; + // TODO: Biotech pregnancy + else return hediff.pawn.RaceProps.gestationPeriodDays * GenDate.HoursPerDay; + } + + public static float RandomVariabilityPercent(int recursion = 0) + { + // Humans, in days + const float mean = 1.635f; + const float stddev = 0.9138f; + const float lambda = 0.234f; + if (recursion >= 10) return mean / (28 * 2); + + float variability = Rand.Gaussian(mean, stddev) - Mathf.Log(Rand.Value) / lambda; + variability /= 28 * 2; // Convert to percentage + + if (variability < 0 || variability > 0.35f) return RandomVariabilityPercent(recursion + 1); // ~2% chance, about the limit on how far variability can go before things start to break + else return variability; + } + + public static bool ShouldCycle(this Pawn pawn) + { + if (!Configurations.EnableAnimalCycle && pawn.IsAnimal()) return false; + if (pawn.GetComp() != null) return false; + if (pawn.RaceHasOviPregnancy()) return false; + + if (ModsConfig.BiotechActive && pawn.genes != null && + pawn.genes.GenesListForReading.Select(gene => gene.def).Intersect(VariousDefOf.EggLayerGenes).Any()) return false; + + return true; + } + + public static bool IsInEstrus(this Pawn pawn, bool visible = true) + { + if (pawn.Dead) return false; + return pawn.health?.hediffSet?.HasHediff(visible ? VariousDefOf.Hediff_Estrus : VariousDefOf.Hediff_Estrus_Concealed) ?? false; + } + + public static HediffComp_Menstruation.EstrusLevel HighestEstrus(this Pawn pawn) + { + HediffComp_Menstruation.EstrusLevel res = HediffComp_Menstruation.EstrusLevel.None; + + foreach(HediffComp_Menstruation comp in pawn.GetMenstruationComps()) + { + switch (comp.GetEstrusLevel()) + { + case HediffComp_Menstruation.EstrusLevel.None: + break; + case HediffComp_Menstruation.EstrusLevel.Concealed: + res = HediffComp_Menstruation.EstrusLevel.Concealed; + break; + case HediffComp_Menstruation.EstrusLevel.Visible: + return HediffComp_Menstruation.EstrusLevel.Visible; + } + } + + return res; + } + + public static bool HasIUD(this Pawn pawn) + { + if (pawn.health.hediffSet.HasHediff(VariousDefOf.RJW_IUD)) return true; + if (ModsConfig.BiotechActive && pawn.health.hediffSet.HasHediff(HediffDefOf.ImplantedIUD)) return true; + return false; + } + + public static bool IsProPregnancy(this Pawn pawn, out Precept precept) + { + precept = null; + + Ideo ideo = pawn.Ideo; + if (ideo != null) + { + precept = ideo.GetPrecept(VariousDefOf.Pregnancy_Required) ?? + ideo.GetPrecept(VariousDefOf.Pregnancy_Holy) ?? + ideo.GetPrecept(VariousDefOf.Pregnancy_Elevated); + } + if (precept != null) return true; + + else return pawn.IsBreeder() || + pawn.HasImpregnationFetish(); + } + + public static float DamagePants(this Pawn pawn, float fluidAmount) + { + if (pawn.apparel == null) return 0; + Apparel pants = null; + foreach(Apparel apparel in pawn.apparel.WornApparel.Where(app => app.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Legs))) + { + if (apparel.def.apparel.LastLayer == ApparelLayerDefOf.OnSkin) + { + pants = apparel; + break; + } + else if (pants == null || apparel.def.apparel.LastLayer == ApparelLayerDefOf.Middle) + // Either grab whatever's available or reassign the pants from shell to a middle + pants = apparel; + // Pants are middle and this is a shell + else continue; + } + if (pants == null) return 0; + + const float HPPerMl = 0.5f; + + DamageWorker.DamageResult damage = pants.TakeDamage(new DamageInfo(DamageDefOf.Deterioration, fluidAmount * HPPerMl, spawnFilth: false)); + + if (pants.Destroyed && PawnUtility.ShouldSendNotificationAbout(pawn) && !pawn.Dead) + Messages.Message("MessageWornApparelDeterioratedAway".Translate(GenLabel.ThingLabel(pants.def, pants.Stuff), pawn).CapitalizeFirst(), pawn, MessageTypeDefOf.NegativeEvent); + + return damage.totalDamageDealt; + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Hediff_Estrus.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Hediff_Estrus.cs new file mode 100644 index 0000000..26fa191 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Hediff_Estrus.cs @@ -0,0 +1,78 @@ +using System.Collections.Generic; +using System.Linq; +using Verse; + +namespace RJW_Menstruation +{ + public class Hediff_Estrus : HediffWithComps + { + const int checkInterval = GenTicks.TickRareInterval; + private bool shouldRemove = false; + + public override bool ShouldRemove + { + get + { + return shouldRemove || base.ShouldRemove; + } + } + + protected bool IsVisible + { + get + { + return def == VariousDefOf.Hediff_Estrus; + } + } + + public override void PostAdd(DamageInfo? dinfo) + { + base.PostAdd(dinfo); + if (IsVisible) + { + List removals = pawn.health.hediffSet.hediffs.Where(hediff => hediff.def == VariousDefOf.Hediff_Estrus_Concealed).ToList(); + foreach (Hediff concealedEstrus in removals) + { + pawn.health.RemoveHediff(concealedEstrus); + } + } + } + + public override void PostTick() + { + base.PostTick(); + if (!pawn.IsHashIntervalTick(checkInterval)) return; + + if (IsVisible) + { + switch (pawn.HighestEstrus()) + { + case HediffComp_Menstruation.EstrusLevel.None: + shouldRemove = true; + break; + case HediffComp_Menstruation.EstrusLevel.Concealed: + shouldRemove = true; + pawn.health.AddHediff(VariousDefOf.Hediff_Estrus_Concealed); + break; + case HediffComp_Menstruation.EstrusLevel.Visible: + break; + } + } + else + { + // Adding a visible will remove this one, so we don't have to check it here + if (pawn.HighestEstrus() == HediffComp_Menstruation.EstrusLevel.None) shouldRemove = true; + } + } + + public override bool TryMergeWith(Hediff other) + { + if (!(other is Hediff_Estrus otherEstrus)) return false; + + if (this.def == otherEstrus.def) return true; + else if (!this.IsVisible && otherEstrus.IsVisible && !otherEstrus.shouldRemove) return true; // A concealed estrus won't be added if there's a visible + // This is a visible estrus overwriting a concealed. + else return false; // Since this is being added while hediffs are being looped through, it's not safe to remove the concealed yet. Do it in PostAdd. + } + } +} \ No newline at end of file diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs new file mode 100644 index 0000000..b7877d2 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Hediff_MultiplePregnancy.cs @@ -0,0 +1,540 @@ +using RimWorld; +using rjw; +using System.Collections.Generic; +using System.Linq; +using Verse; + +namespace RJW_Menstruation +{ + public class Hediff_MultiplePregnancy : Hediff_BasePregnancy + { + protected Dictionary enzygoticSiblings = new Dictionary(); // Each pawn and who they split from + + public override void DiscoverPregnancy() + { + PregnancyThought(); + base.DiscoverPregnancy(); + } + + protected void PregnancyThought() + { + if (is_discovered || + !xxx.is_human(pawn) || + pawn.IsBreeder() || (pawn.Ideo?.HasPrecept(VariousDefOf.Pregnancy_Required) ?? false) || + (pawn.relations?.DirectRelations?.Find(x => x.def.Equals(PawnRelationDefOf.Spouse) || + x.def.Equals(PawnRelationDefOf.Fiance))) != null) + return; + if (pawn.IsProPregnancy(out Precept precept) || pawn.relations?.DirectRelations?.Find(x => x.def.Equals(PawnRelationDefOf.Lover)) != null) + { + if (precept != null) + pawn.needs.mood.thoughts.memories.TryGainMemory(VariousDefOf.UnwantedPregnancyMild); + } + else + { + pawn.needs.mood.thoughts.memories.TryGainMemory(VariousDefOf.UnwantedPregnancy); + } + } + + public override void Miscarry() + { + this.GetMenstruationCompFromPregnancy().Pregnancy = null; + base.Miscarry(); + } + + public override void GiveBirth() + { + + if (babies.NullOrEmpty()) + { + ModLog.Warning(" no babies (debug?) " + this.GetType().Name); + if (father == null) + { + father = Trytogetfather(ref pawn); + } + Initialize(pawn, father, SelectDnaGivingParent(pawn, father)); + } + + foreach (Pawn baby in babies) + { + if (xxx.is_animal(baby)) + { + BestialBirth(baby); + } + else + { + HumanlikeBirth(baby); + } + + baby.ageTracker.AgeChronologicalTicks = 0; + } + + pawn.health.RemoveHediff(this); + HediffComp_Menstruation comp = this.GetMenstruationCompFromPregnancy(); + if(comp != null) comp.Pregnancy = null; + HediffComp_Breast breastcomp = pawn.GetBreastComp(); + if (ModsConfig.BiotechActive && xxx.is_human(pawn) && breastcomp != null) + pawn.health.AddHediff(HediffDefOf.Lactating); + breastcomp?.GaveBirth(); + } + + private void HumanlikeBirth(Pawn baby) + { + Pawn mother = pawn; Pawn father = Utility.GetFather(baby, pawn); + //backup melanin, LastName for when baby reset by other mod on spawn/backstorychange + //var skin_whiteness = baby.story.melanin; + //var last_name = baby.story.birthLastName; + + PawnUtility.TrySpawnHatchedOrBornPawn(baby, mother); + + Need_Sex sex_need = mother.needs?.TryGetNeed(); + if (mother.Faction != null && !(mother.Faction?.IsPlayer ?? false) && sex_need != null) + { + sex_need.CurLevel = 1.0f; + } + if (mother.Faction != null) + { + if (mother.Faction != baby.Faction) + baby.SetFaction(mother.Faction); + } + if (mother.IsSlaveOfColony) + { + if (mother.SlaveFaction != null) + baby.SetFaction(mother.SlaveFaction); + else if (mother.HomeFaction != null) + baby.SetFaction(mother.HomeFaction); + else if (mother.Faction != null) + baby.SetFaction(mother.Faction); + else + baby.SetFaction(Faction.OfPlayer); + baby.guest.SetGuestStatus(Faction.OfPlayer, GuestStatus.Slave); + } + else if (mother.IsPrisonerOfColony) + { + if (mother.HomeFaction != null) + baby.SetFaction(mother.HomeFaction); + baby.guest.SetGuestStatus(Faction.OfPlayer, GuestStatus.Prisoner); + } + + if (xxx.is_human(mother)) TaleRecorder.RecordTale(TaleDefOf.GaveBirth, new object[] { mother, baby }); + + if (ModsConfig.BiotechActive) + { + // Ugly, but it'll have to do + OutcomeChance bestOutcome = RitualOutcomeEffectDefOf.ChildBirth.BestOutcome; + + string label = bestOutcome.label; + string description = bestOutcome.description.Formatted(mother.Named("MOTHER")); + + baby.babyNamingDeadline = Find.TickManager.TicksGame + GenDate.TicksPerDay; + ChoiceLetter_BabyBirth choiceLetter_BabyBirth = (ChoiceLetter_BabyBirth)LetterMaker.MakeLetter( + label, description, LetterDefOf.BabyBirth, baby + ); + choiceLetter_BabyBirth.Start(); + Find.LetterStack.ReceiveLetter(choiceLetter_BabyBirth); + } + + PostBirth(mother, father, baby); + } + + + private void BestialBirth(Pawn baby) + { + Pawn mother = pawn; Pawn father = Utility.GetFather(baby, pawn); + //backup melanin, LastName for when baby reset by other mod on spawn/backstorychange + //var skin_whiteness = baby.story.melanin; + //var last_name = baby.story.birthLastName; + + PawnUtility.TrySpawnHatchedOrBornPawn(baby, mother); + + Need_Sex sex_need = mother.needs?.TryGetNeed(); + if (mother.Faction != null && !(mother.Faction?.IsPlayer ?? false) && sex_need != null) + { + sex_need.CurLevel = 1.0f; + } + if (mother.Faction != null) + { + if (mother.Faction != baby.Faction) + baby.SetFaction(mother.Faction); + } + + Train(baby, mother); + + PostBirth(mother, father, baby); + + //restore melanin, LastName for when baby reset by other mod on spawn/backstorychange + //baby.story.melanin = skin_whiteness; + //baby.story.birthLastName = last_name; + } + + public override void PostBirth(Pawn mother, Pawn father, Pawn baby) + { + base.PostBirth(mother, father, baby); + // Has to happen on birth since RJW redoes the genitals at birth + if (!enzygoticSiblings.NullOrEmpty() && enzygoticSiblings.TryGetValue(baby, out Pawn original) && baby != original) + PregnancyCommon.ProcessIdenticalSibling(baby, original); + } + + // From RJW's trait code + protected List GetInheritableTraits(Pawn mother, Pawn father) + { + List traitpool = new List(); + List momtraits = new List(); + List poptraits = new List(); + List traits_to_inherit = new List(); + float max_num_momtraits_inherited = RJWPregnancySettings.max_num_momtraits_inherited; + float max_num_poptraits_inherited = RJWPregnancySettings.max_num_poptraits_inherited; + float max_num_traits_inherited = max_num_momtraits_inherited + max_num_poptraits_inherited; + int i = 1; + int j = 1; + if (xxx.has_traits(mother) && mother.RaceProps.Humanlike) + { + foreach (Trait momtrait in mother.story.traits.allTraits) + { + if (!non_genetic_traits.Contains(momtrait.def.defName) && !momtrait.ScenForced) + momtraits.Add(momtrait); + } + } + if (father != null && xxx.has_traits(father) && father.RaceProps.Humanlike) + { + foreach (Trait poptrait in father.story.traits.allTraits) + { + if (!non_genetic_traits.Contains(poptrait.def.defName) && !poptrait.ScenForced) + poptraits.Add(poptrait); + } + } + int rand_trait_index; + if (!momtraits.NullOrEmpty()) + { + i = 1; + while (momtraits.Count > 0 && i <= max_num_momtraits_inherited) + { + rand_trait_index = Rand.Range(0, momtraits.Count); + traits_to_inherit.Add(momtraits[rand_trait_index]); + momtraits.RemoveAt(rand_trait_index); + } + } + if (!poptraits.NullOrEmpty()) + { + j = 1; + while (poptraits.Count > 0 && j <= max_num_poptraits_inherited) + { + rand_trait_index = Rand.Range(0, poptraits.Count); + traits_to_inherit.Add(poptraits[rand_trait_index]); + poptraits.RemoveAt(rand_trait_index); + } + } + + if (poptraits.NullOrEmpty() || momtraits.NullOrEmpty()) + { + foreach (Trait traits in traits_to_inherit) + { + traitpool.Add(traits); + } + } + else + { + if (traits_to_inherit.Count() != max_num_traits_inherited) + { + if (momtraits.Count != 0 && i != max_num_momtraits_inherited) + { + while (poptraits != null && momtraits.Count() > 0 && i <= max_num_momtraits_inherited) + { + rand_trait_index = Rand.Range(0, momtraits.Count); + if (!traits_to_inherit.Contains(momtraits[rand_trait_index])) + { + traits_to_inherit.Add(momtraits[rand_trait_index]); + } + momtraits.RemoveAt(rand_trait_index); + } + } + if (poptraits != null && poptraits.Count != 0 && j != max_num_poptraits_inherited) + { + while (poptraits.Count > 0 && i < max_num_poptraits_inherited) + { + rand_trait_index = Rand.Range(0, poptraits.Count); + if (!traits_to_inherit.Contains(poptraits[rand_trait_index])) + { + traits_to_inherit.Add(poptraits[rand_trait_index]); + } + poptraits.RemoveAt(rand_trait_index); + } + } + } + foreach (Trait traits in traits_to_inherit) + { + traitpool.Add(traits); + } + } + return traitpool; + } + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Collections.Look(ref enzygoticSiblings, "enzygoticSiblings", keyLookMode: LookMode.Reference, valueLookMode: LookMode.Reference); + } + + protected override void GenerateBabies(DnaGivingParent _) + { + AddNewBaby(pawn, father); + } + + protected void Train(Pawn baby, Pawn mother) + { + if (xxx.is_human(baby) || baby.Faction != Faction.OfPlayer) return; + + if (xxx.is_human(mother) && baby.Faction == Faction.OfPlayer && baby.training.CanAssignToTrain(TrainableDefOf.Obedience, out _).Accepted) + { + baby.training.Train(TrainableDefOf.Obedience, mother); + } + if (xxx.is_human(mother) && baby.Faction == Faction.OfPlayer && baby.training.CanAssignToTrain(TrainableDefOf.Tameness, out _).Accepted) + { + baby.training.Train(TrainableDefOf.Tameness, mother); + } + } + + + public bool AddNewBaby(Pawn mother, Pawn father) + { + string lastname; + if (xxx.is_human(mother)) lastname = NameTriple.FromString(mother.Name.ToStringFull).Last; + else if (xxx.is_human(father)) lastname = NameTriple.FromString(father.Name.ToStringFull).Last; + else lastname = ""; + + PawnGenerationRequest request = new PawnGenerationRequest( + developmentalStages: DevelopmentalStage.Newborn, + allowDowned: true, + faction: mother.Faction, + canGeneratePawnRelations: false, + forceGenerateNewPawn: true, + colonistRelationChanceFactor: 0, + allowFood: false, + allowAddictions: false, + relationWithExtraPawnChanceFactor: 0, + fixedLastName: lastname, + kind: PregnancyCommon.BabyPawnKindDecider(mother, father, false), + //fixedIdeo: mother.Ideo, + forbidAnyTitle: true, + forceNoBackstory: true, + forcedEndogenes: PregnancyUtility.GetInheritedGenes(father, mother), + forcedXenotype: ModsConfig.BiotechActive ? XenotypeDefOf.Baseliner : null + ); + + int division = 1; + Pawn firstbaby = null; + int traitSeed = Rand.Int; + List parentTraits = GetInheritableTraits(mother, father); + while (Rand.Chance(Configurations.EnzygoticTwinsChance) && division < Configurations.MaxEnzygoticTwins) division++; + for (int i = 0; i < division; i++) + { + Pawn baby = GenerateBaby(request, mother, father, parentTraits, traitSeed); + if (baby == null) break; + PregnancyCommon.SetupBabyXenotype(mother, father, baby); + // HAR and some xenotype mods don't randomize graphics until it's rendered + // So poke it early + baby.Drawer.renderer.graphics.ResolveAllGraphics(); + if (division > 1) + { + if (i == 0) + { + + firstbaby = baby; + request.FixedGender = baby.gender; + request.ForcedEndogenes = baby.genes?.Endogenes.Select(gene => gene.def).ToList(); + } + else + { + enzygoticSiblings.Add(baby, firstbaby); + + if (baby.story != null) + { + baby.story.headType = firstbaby.story.headType; + baby.story.hairDef = firstbaby.story.hairDef; + baby.story.HairColor = firstbaby.story.HairColor; + baby.story.bodyType = firstbaby.story.bodyType; + baby.story.furDef = firstbaby.story.furDef; + baby.story.skinColorOverride = firstbaby.story.skinColorOverride; + } + + if (baby.genes != null && ModsConfig.BiotechActive) + { + baby.genes.SetXenotypeDirect(firstbaby.genes.Xenotype); + baby.genes.xenotypeName = firstbaby.genes.xenotypeName; + baby.genes.iconDef = firstbaby.genes.iconDef; + baby.genes.hybrid = firstbaby.genes.hybrid; + } + + if (baby.IsHAR()) + HARCompatibility.CopyHARProperties(baby, firstbaby); + if (Configurations.AnimalGeneticsActivated) + AnimalGeneticsCompatibility.CopyGenes(baby, firstbaby); + } + } + babies.Add(baby); + } + + return true; + + } + + public Pawn GenerateBaby(PawnGenerationRequest request, Pawn mother, Pawn father, List parentTraits, int traitSeed) + { + if (Configurations.AnimalGeneticsActivated) AnimalGeneticsCompatibility.PreConception(mother, father); + Pawn baby = PawnGenerator.GeneratePawn(request); + if (Configurations.AnimalGeneticsActivated) AnimalGeneticsCompatibility.PostConception(); + if (baby == null) + { + Log.Error("Baby not generated. Request: " + request.ToString()); + return null; + } + if (xxx.is_human(baby) || (baby.relations != null && !RJWSettings.Disable_bestiality_pregnancy_relations)) + { + baby.SetMother(mother); + if (mother != father) + { + if (father.gender != Gender.Female) baby.SetFather(father); + else baby.relations.AddDirectRelation(PawnRelationDefOf.Parent, father); + } + } + if (xxx.is_human(baby)) + { + // Ensure the same inherited traits are chosen each run + // Has to happen right here so GeneratePawn up there still gets unique results + Rand.PushState(traitSeed); // With a seed just to make sure that fraternal twins *don't* get trait-duped + UpdateTraits(baby, parentTraits); + Rand.PopState(); + } + return baby; + } + + /// + /// Copy from RJW + /// + /// + /// + /// + public void UpdateTraits(Pawn pawn, List parentTraits) + { + if (pawn?.story?.traits == null) + { + return; + } + + int traitLimit = pawn.story.traits.allTraits.Count; + + //Personal pool + List personalTraitPool = new List(pawn.story.traits.allTraits); + //Parents + List parentTraitPool = new List(parentTraits); + parentTraitPool.RemoveAll(x => x.ScenForced); + int numberInherited; + if (parentTraitPool != null) + numberInherited = System.Math.Min(parentTraitPool.Count(), Rand.RangeInclusive(0, 2)); // Not 3; give a better chance for a natural trait to appear + else + numberInherited = 0; + + //Game suggested traits. + IEnumerable forcedTraits = personalTraitPool + .Where(x => x.ScenForced) + .Distinct(new TraitComparer(ignoreDegree: true)); // result can be a mess, because game allows this mess to be created in scenario editor + + List selectedTraits = new List(); + TraitComparer comparer = new TraitComparer(); // trait comparision implementation, because without game compares traits *by reference*, makeing them all unique. + selectedTraits.AddRange(forcedTraits); // enforcing scenario forced traits + for (int i = 0; i < numberInherited; i++) // add parent traits first + { + int index = Rand.Range(0, parentTraitPool.Count); + Trait trait = parentTraitPool[index]; + parentTraitPool.RemoveAt(index); + if (!selectedTraits.Any(x => comparer.Equals(x, trait) || + x.def.ConflictsWith(trait))) + selectedTraits.Add(new Trait(trait.def, trait.Degree, false)); + } + + while (selectedTraits.Count < traitLimit && personalTraitPool.Count > 0) + { + int index = Rand.Range(0, personalTraitPool.Count); // getting trait and removing from the pull + Trait trait = personalTraitPool[index]; + personalTraitPool.RemoveAt(index); + + if (!selectedTraits.Any(x => comparer.Equals(x, trait) || // skipping traits conflicting with already added + x.def.ConflictsWith(trait))) + selectedTraits.Add(new Trait(trait.def, trait.Degree, false)); + + } + + pawn.story.traits.allTraits = selectedTraits; + } + + public override bool TryMergeWith(Hediff other) + { + return false; + } + } + + /// + /// Copy from RJW + /// + public class TraitComparer : IEqualityComparer + { + readonly bool ignoreForced; + readonly bool ignoreDegree; + + public TraitComparer(bool ignoreDegree = false, bool ignoreForced = true) + { + this.ignoreDegree = ignoreDegree; + this.ignoreForced = ignoreForced; + } + + public bool Equals(Trait x, Trait y) + { + return + x.def == y.def && + (ignoreDegree || (x.Degree == y.Degree)) && + (ignoreForced || (x.ScenForced == y.ScenForced)); + } + + public int GetHashCode(Trait obj) + { + return + (obj.def.GetHashCode() << 5) + + (ignoreDegree ? 0 : obj.Degree) + + ((ignoreForced || obj.ScenForced) ? 0 : 0x10); + } + } + + public class RaceComparer : IEqualityComparer + { + public bool Equals(Pawn x, Pawn y) + { + return x.def.Equals(y.def); + } + + public int GetHashCode(Pawn obj) + { + return obj.def.GetHashCode(); + } + } + + public class FatherComparer : IEqualityComparer + { + readonly Pawn mother; + + public FatherComparer(Pawn mother) + { + this.mother = mother; + } + + public bool Equals(Pawn x, Pawn y) + { + if (Utility.GetFather(x, mother) == null && Utility.GetFather(y, mother) == null) return true; + return Utility.GetFather(x, mother)?.Label.Equals(Utility.GetFather(y, mother)?.Label) ?? false; + } + + public int GetHashCode(Pawn obj) + { + return obj.def.GetHashCode(); + } + } + +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/IngestionOutcomeDoers.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/IngestionOutcomeDoers.cs new file mode 100644 index 0000000..a413f42 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/IngestionOutcomeDoers.cs @@ -0,0 +1,17 @@ +using RimWorld; +using Verse; + +namespace RJW_Menstruation +{ + public class IngestionOutcomeDoer_GiveHediff_StackCount : IngestionOutcomeDoer_GiveHediff + { + protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) + { + Hediff hediff = HediffMaker.MakeHediff(hediffDef, pawn); + float effect = ((!(severity > 0f)) ? hediffDef.initialSeverity : severity) * ingested.stackCount; + AddictionUtility.ModifyChemicalEffectForToleranceAndBodySize_NewTemp(pawn, toleranceChemical, ref effect, multiplyByGeneToleranceFactors); + hediff.Severity = effect; + pawn.health.AddHediff(hediff); + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/JobDrivers.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/JobDrivers.cs new file mode 100644 index 0000000..99cae05 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/JobDrivers.cs @@ -0,0 +1,125 @@ +using RimWorld; +using System.Collections.Generic; +using System.Linq; +using Verse; +using Verse.AI; + +namespace RJW_Menstruation +{ + public class JobDriver_VaginaWashing : JobDriver + { + const int excretingTime = 300;//ticks - 120 = 2 real seconds, 3 in-game minutes + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + return pawn.Reserve(pawn, job, 1, -1, null, errorOnFailed); + } + + protected override IEnumerable MakeNewToils() + { + List comps = pawn.GetMenstruationComps().ToList(); + this.FailOn(delegate + { + return comps.All(comp => comp.TotalCumPercent < 0.001); + }); + Toil excreting = Toils_General.Wait(excretingTime, TargetIndex.None);//duration of + + excreting.WithProgressBarToilDelay(TargetIndex.A); + yield return excreting; + yield return new Toil() + { + initAction = delegate () + { + foreach (HediffComp_Menstruation comp in comps) + comp.CumOut(null, 0.5f); + if (comps.Any(comp => comp.TotalCumPercent > 0.001)) JumpToToil(excreting); + } + }; + //yield return excreting; + yield break; + } + } + + public class JobDriver_MilkSelf : JobDriver + { + protected float progress = 0; + protected float MilkingTime + { + get + { + return 250f * Fullness + 50f; + } + } + protected virtual float Fullness + { + get + { + return comp?.Fullness ?? 0; + } + } + + private CompMilkable comp; + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + return pawn.Reserve(pawn, job, 1, -1, null, errorOnFailed); + } + + protected virtual void PreMakeNewToils() + { + comp = pawn.GetComp(); + } + + protected override IEnumerable MakeNewToils() + { + PreMakeNewToils(); + this.FailOnDespawnedNullOrForbidden(TargetIndex.A); + this.FailOnNotCasualInterruptible(TargetIndex.A); + Toil milking = new Toil + { + initAction = delegate () + { + pawn.pather.StopDead(); + }, + tickAction = MilkingTick + }; + milking.AddFinishAction(Finish); + milking.defaultCompleteMode = ToilCompleteMode.Never; + milking.WithProgressBar(TargetIndex.A, () => progress / MilkingTime); + yield return milking; + yield break; + } + + protected void MilkingTick() + { + progress += pawn.GetStatValue(StatDefOf.AnimalGatherSpeed); + if (progress > MilkingTime) + { + Gathered(); + pawn.jobs.EndCurrentJob(JobCondition.Succeeded); + } + PostTickAction(); + } + + protected virtual void Gathered() + { + pawn.GetComp().Gathered(pawn); + } + + protected virtual void Finish() + { + if (pawn.CurJobDef == JobDefOf.Wait_MaintainPosture) + { + pawn.jobs.EndCurrentJob(JobCondition.InterruptForced); + } + } + + protected virtual void PostTickAction() + { + } + + + } + + +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/MenstruationModExtension.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/MenstruationModExtension.cs new file mode 100644 index 0000000..c3a8fbe --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/MenstruationModExtension.cs @@ -0,0 +1,15 @@ +using Verse; + +namespace RJW_Menstruation +{ + public class MenstruationModExtension : DefModExtension + { + public float eggLifeTimeFactor = 1.0f; + public bool neverEstrus = false; + public bool alwaysEstrus = false; + public float ovulationFactor = 1.0f; + public bool noBleeding = false; + + public bool disableCycle = false; + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/Biotech_Patch.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/Biotech_Patch.cs new file mode 100644 index 0000000..0125f26 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/Biotech_Patch.cs @@ -0,0 +1,240 @@ +using HarmonyLib; +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using Verse; + +namespace RJW_Menstruation +{ + [HarmonyPatch(typeof(Hediff_Pregnant), "Miscarry")] + public class Miscarry_Patch + { + public static void Postfix(Hediff_Pregnant __instance) + { + HediffComp_Menstruation comp = __instance.GetMenstruationCompFromPregnancy(); + if (comp == null) return; + comp.Pregnancy = null; + } + } + + [HarmonyPatch(typeof(Hediff_Pregnant), nameof(Hediff_Pregnant.StartLabor))] + public class StartLabor_Patch + { + public static void Postfix(Hediff_Pregnant __instance) + { + HediffComp_Menstruation comp = __instance.GetMenstruationCompFromPregnancy(); + if (comp == null) return; + comp.Pregnancy = __instance.pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.PregnancyLabor); + } + } + + [HarmonyPatch(typeof(Hediff_Labor), nameof(Hediff_Labor.PreRemoved))] + public class Labor_PreRemoved_Patch + { + public static void Postfix(Hediff_Labor __instance) + { + HediffComp_Menstruation comp = __instance.GetMenstruationCompFromPregnancy(); + if (comp == null) return; + comp.Pregnancy = __instance.pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.PregnancyLaborPushing); + } + } + + [HarmonyPatch(typeof(Hediff_LaborPushing), nameof(Hediff_LaborPushing.PreRemoved))] + public class LaborPushing_PreRemoved_Patch + { + public static void Postfix(Hediff_LaborPushing __instance) + { + HediffComp_Menstruation comp = __instance.GetMenstruationCompFromPregnancy(); + if (comp == null) return; + comp.Pregnancy = null; + } + } + + // Prevents a pregnancy from going into labor if another pregnancy already is + [HarmonyPatch(typeof(Hediff_Pregnant), nameof(Hediff_Pregnant.GestationProgress), MethodType.Getter)] + public class Hediff_Pregnant_GestationProgess_Patch + { + public static void Postfix(Hediff_Pregnant __instance, ref float __result) + { + if (__result < 1f) return; + Pawn pawn = __instance.pawn; + if (pawn.health.hediffSet.hediffs.Any(hediff => hediff.def == HediffDefOf.PregnancyLabor || hediff.def == HediffDefOf.PregnancyLaborPushing)) + __result = 0.999f; + } + } + + [HarmonyPatch(typeof(Recipe_ExtractOvum), nameof(Recipe_ExtractOvum.AvailableReport))] + public class ExtractOvum_AvailableReport_Patch + { + public static void Postfix(Thing thing, ref AcceptanceReport __result) + { + if (!__result.Accepted) return; + Pawn pawn = (Pawn)thing; + if (pawn.IsRJWPregnant()) + { + __result = "CannotPregnant".Translate(); + return; + } + List comps = pawn.GetMenstruationComps().ToList(); + if (!comps.Any()) return; + if (comps.All(comp => comp.ovarypower <= 0)) + { + __result = Translations.CannotNoEggs; + return; + } + return; + } + } + + [HarmonyPatch(typeof(Recipe_ExtractOvum), "OnSurgerySuccess")] + public class ExtractOvum_OnSurgerySuccess_Patch + { + public static void Postfix(Pawn pawn) + { + List comps = pawn.GetMenstruationComps().ToList(); + if (!comps.Any()) return; + HediffComp_Menstruation mostEggs = comps.MaxBy(comp => comp.ovarypower); + if (mostEggs.ovarypower <= 0) return; // Shouldn't happen + mostEggs.ovarypower--; + } + } + + [HarmonyPatch(typeof(Recipe_ImplantEmbryo), nameof(Recipe_ImplantEmbryo.ApplyOnPawn))] + public class ImplantEmbryo_ApplyOnPawn_Patch + { + public static void Postfix(Pawn pawn) + { + foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps()) + comp.TakeLoosePregnancy(); + } + } + + [HarmonyPatch(typeof(PregnancyUtility), nameof(PregnancyUtility.ApplyBirthOutcome))] + public class ApplyBirthOutcome_Breast_Patch + { + public static void Postfix(Thing birtherThing) + { + if (birtherThing is Pawn pawn && !pawn.Dead) + pawn.GetBreastComp()?.GaveBirth(); + } + } + + [HarmonyPatch] + public class TerminatePregnancy_Patch + { + public static IEnumerable TargetMethods() + { + yield return AccessTools.Method(typeof(PregnancyUtility), nameof(PregnancyUtility.TryTerminatePregnancy)); + yield return AccessTools.Method(typeof(Recipe_TerminatePregnancy), nameof(Recipe_TerminatePregnancy.ApplyOnPawn)); + } + + private static PregnancyAttitude? GetAttitude(Hediff pregnancy) + { + if (pregnancy is Hediff_Pregnant preg) return preg.Attitude; + else return null; + } + + private static Hediff GetEarliestPregnancy(Pawn pawn) + { + Hediff Earliest_Pregnancy = PregnancyUtility.GetPregnancyHediff(pawn); + foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps()) + { + Hediff pregnancy = comp.Pregnancy; + if (pregnancy == null) continue; + if (Earliest_Pregnancy == null || Earliest_Pregnancy.Severity > pregnancy.Severity) Earliest_Pregnancy = pregnancy; + } + + return Earliest_Pregnancy; + } + + private static readonly MethodInfo GetPregnancyHediff = AccessTools.Method(typeof(PregnancyUtility), nameof(PregnancyUtility.GetPregnancyHediff), new Type[] { typeof(Pawn) }); + private static readonly MethodInfo Get_Attitude = AccessTools.DeclaredPropertyGetter(typeof(Hediff_Pregnant), nameof(Hediff_Pregnant.Attitude)); + + public static IEnumerable Transpiler(IEnumerable instructions) + { + if (GetPregnancyHediff?.ReturnType != typeof(Hediff)) throw new InvalidOperationException("GetPregnancyHediff not found"); + if (Get_Attitude == null || Nullable.GetUnderlyingType(Get_Attitude.ReturnType) != typeof(PregnancyAttitude)) throw new InvalidOperationException("get_Attitude not found"); + foreach (CodeInstruction instruction in instructions) + { + if (instruction.Calls(GetPregnancyHediff)) + yield return CodeInstruction.Call(typeof(TerminatePregnancy_Patch), nameof(TerminatePregnancy_Patch.GetEarliestPregnancy)); + // Menstruation pregnancies don't have an attitude, so skip the cast to Hediff_Pregnant and call a version that handles it + else if (instruction.opcode == OpCodes.Castclass && (Type)instruction.operand == typeof(Hediff_Pregnant)) + yield return new CodeInstruction(OpCodes.Nop); + else if (instruction.Calls(Get_Attitude)) + yield return CodeInstruction.Call(typeof(TerminatePregnancy_Patch), nameof(TerminatePregnancy_Patch.GetAttitude)); + else yield return instruction; + } + } + } + + [HarmonyPatch(typeof(PregnancyUtility), nameof(PregnancyUtility.TryTerminatePregnancy))] + public class PregnancyUtility_TryTerminatePregnancy_Patch + { + public static void Postfix(bool __result, Pawn pawn) + { + if (__result) + foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps()) + _ = comp.Pregnancy; // get_Pregnancy will remove the hediff attached to the comp that doesn't have it anymore + } + } + + [HarmonyPatch(typeof(Recipe_TerminatePregnancy), nameof(Recipe_TerminatePregnancy.AvailableOnNow))] + public class TerminatePregnancy_AvailableOnNow_Patch + { + public static void Postfix(ref bool __result, Thing thing) + { + if (!ModsConfig.BiotechActive || !(thing is Pawn pawn)) return; + __result |= pawn.GetMenstruationComps().Any(comp => comp.Pregnancy != null); + } + } + + [HarmonyPatch(typeof(Pawn_GeneTracker), "Notify_GenesChanged")] + public class Notify_GenesChanged_Patch + { + public static void Postfix(Pawn_GeneTracker __instance, GeneDef addedOrRemovedGene) + { + if (!addedOrRemovedGene.HasModExtension()) return; + foreach (HediffComp_Menstruation comp in __instance.pawn.GetMenstruationComps()) + comp.Notify_UpdatedGenes(); + } + } + + [HarmonyPatch(typeof(StatPart_FertilityByGenderAge), "AgeFactor")] + public class AgeFactor_Patch + { + public static void Postfix(ref float __result, Pawn pawn) + { + if (__result <= 0.0f) return; + if (pawn.GetMenstruationComps().Any(comp => comp.CalculatingOvulationChance)) + __result = 1.0f; + } + } + + //[HarmonyPatch(typeof(ChildcareUtility), nameof(ChildcareUtility.SuckleFromLactatingPawn))] + //public class GreedyConsume_Patch + //{ + // private static float ConsumeAndAdjustNipples(HediffComp_Chargeable instance, float desiredCharge) + // { + // // Pulling breast comp every tick might be too much for performance. + // const float averageNippleChangePerTick = 0.0025f / 50000f; + // instance.Pawn.GetBreastComp()?.AdjustNippleProgress(Rand.Range(0.0f, averageNippleChangePerTick * 2) * Configurations.MaxBreastIncrementFactor); + // return instance.GreedyConsume(desiredCharge); + // } + + // private static readonly MethodInfo GreedyConsume = AccessTools.Method(typeof(HediffComp_Chargeable), nameof(HediffComp_Chargeable.GreedyConsume), new Type[] { typeof(HediffComp_Chargeable), typeof(float) }); + // public static IEnumerable Transpiler(IEnumerable instructions) + // { + // if(GreedyConsume == null) throw new InvalidOperationException("GreedyConsume not found"); + // foreach (var instruction in instructions) + // { + // if (instruction.Calls(GreedyConsume)) + // yield return CodeInstruction.Call(typeof(GreedyConsume_Patch), nameof(GreedyConsume_Patch.ConsumeAndAdjustNipples)); + // yield return instruction; + // } + // } + //} +} \ No newline at end of file diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/GC_Patch.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/GC_Patch.cs new file mode 100644 index 0000000..37eda3e --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/GC_Patch.cs @@ -0,0 +1,37 @@ +using HarmonyLib; +using RimWorld; +using RimWorld.Planet; +using System.Collections.Generic; +using System.Linq; +using Verse; + +namespace RJW_Menstruation.Patch +{ + [HarmonyPatch(typeof(WorldPawnGC), "GetCriticalPawnReason")] + public static class GetCriticalPawnReason_Patch + { + readonly public static HashSet cummedPawns = new HashSet(); + + public static void Postfix(ref string __result, Pawn pawn) + { + if (!__result.NullOrEmpty()) return; + if (cummedPawns.Contains(pawn)) + __result = "EggFertOrCumInWomb"; + } + } + + [HarmonyPatch(typeof(WorldPawnGC), "AccumulatePawnGCData")] + public static class AccumulatePawnGCData_Patch + { + public static void Prefix() + { + GetCriticalPawnReason_Patch.cummedPawns.Clear(); + // foreach(Pawn p in PawnsFinder.All_AliveOrDead) + foreach (Pawn p in PawnsFinder.AllMapsCaravansAndTravelingTransportPods_Alive_OfPlayerFaction.Union(PawnsFinder.AllMapsCaravansAndTravelingTransportPods_Alive_PrisonersOfColony)) + { + foreach (HediffComp_Menstruation comp in p.GetMenstruationComps()) + GetCriticalPawnReason_Patch.cummedPawns.UnionWith(comp.GetCummersAndFertilizers()); + } + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/Gizmo_Patch.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/Gizmo_Patch.cs new file mode 100644 index 0000000..92b8b16 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/Gizmo_Patch.cs @@ -0,0 +1,127 @@ +using HarmonyLib; +using RimWorld; +using rjw; +using System.Collections.Generic; +using System.Text; +using UnityEngine; +using Verse; + +namespace RJW_Menstruation +{ + [HarmonyPatch(typeof(Pawn), nameof(Pawn.GetGizmos))] + public class Pawn_GetGizmos + { + public static void Postfix(ref IEnumerable __result, Pawn __instance) + { + if (!__instance.ShowStatus()) + { + return; + } + + if (__instance.ShouldShowWombGizmo()) + { + __result = AddWombGizmos(__instance, __result); + } + } + + private static IEnumerable AddWombGizmos(Pawn __instance, IEnumerable gizmos) + { + foreach (Gizmo gizmo in gizmos) + yield return gizmo; + + foreach (HediffComp_Menstruation comp in __instance.GetMenstruationComps()) + foreach (Gizmo gizmo in GetMenstruationGizmos(__instance, comp)) + yield return gizmo; + } + + public static List GetMenstruationGizmos(Pawn pawn, HediffComp_Menstruation comp) + { + return new List() { CreateGizmo_WombStatus(pawn, comp) }; + } + + + private static Gizmo CreateGizmo_WombStatus(Pawn pawn, HediffComp_Menstruation comp) + { + if (!comp.loaded) + comp.Initialize(); + Texture2D icon, icon_overlay; + StringBuilder description = new StringBuilder(); + if (Configurations.Debug) + { + description + .AppendFormat("{0}: {1}\n", comp.curStage, comp.curStageTicks / GenDate.TicksPerHour); + if (comp.Pregnancy is Hediff_BasePregnancy rjwpreg) description + .AppendFormat("due: {0}\n", rjwpreg.DueDate()); + else if (comp.Pregnancy is Hediff_Pregnant biopreg) description + .AppendFormat("due: {0}\n", biopreg.DueDate()); + description + .AppendFormat("fertcums: {0}\n" + + "ovarypower: {1}\n" + + "eggs: {2}\n", + comp.TotalFertCum, comp.ovarypower, comp.GetNumOfEggs); + } + else description.AppendFormat("{0}\n", comp.GetCurStageLabel); + if (pawn.IsRJWPregnant() || pawn.IsBiotechPregnant()) + { + Hediff hediff = comp.Pregnancy; + if (hediff != null && Utility.ShowFetusImage(hediff)) + { + icon = comp.GetPregnancyIcon(hediff); + float gestationProgress = comp.StageProgress; + if (hediff is Hediff_BasePregnancy || hediff is HediffWithParents) + { + if (gestationProgress < 0.2f) icon_overlay = comp.GetCumIcon(); + else icon_overlay = ContentFinder.Get(("Womb/Empty"), true); + } + else icon_overlay = ContentFinder.Get(("Womb/Empty"), true); + } + else + { + icon = comp.GetWombIcon(); + icon_overlay = comp.GetCumIcon(); + } + } + else + { + Hediff hediff = pawn.health.hediffSet.GetFirstHediff(); + if (hediff != null) + { + icon = MenstruationUtility.GetInsectEggedIcon(comp); + } + else + { + icon = comp.GetWombIcon(); + } + icon_overlay = comp.GetCumIcon(); + + } + foreach (string s in comp.GetCumsInfo) description.AppendFormat("{0}\n", s); + + Color c = comp.GetCumMixtureColor; + + return new Gizmo_Womb + { + defaultLabel = pawn.LabelShort, + defaultDesc = description.ToString(), + icon = icon, + icon_overlay = icon_overlay, + shrinkable = Configurations.AllowShrinkIcon, + cumcolor = c, + comp = comp, + //order = 100, + hotKey = comp == pawn.GetFirstMenstruationComp() ? VariousDefOf.OpenStatusWindowKey : null, + groupKey = 0, + action = delegate + { + Dialog_WombStatus.ToggleWindow(pawn, comp); + } + }; + } + } + + + + + + +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/Harmony.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/Harmony.cs new file mode 100644 index 0000000..6e86da5 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/Harmony.cs @@ -0,0 +1,36 @@ +using HarmonyLib; +using rjw; +using rjw.Modules.Interactions.Internals.Implementation; +using rjw.Modules.Interactions.Rules.PartKindUsageRules; +using rjw.Modules.Shared.Logs; +using System.Collections.Generic; +using System.Reflection; +using Verse; + +namespace RJW_Menstruation +{ + [StaticConstructorOnStartup] + internal static class First + { + static First() + { + Harmony har = new Harmony("RJW_Menstruation"); + har.PatchAll(Assembly.GetExecutingAssembly()); + if (ModsConfig.IsActive("erdelf.HumanoidAlienRaces")) // Don't use the cached in Configurations, it isn't initialized yet + { + har.Patch(GenTypes.GetTypeInAnyAssembly("AlienRace.HarmonyPatches").GetMethod(nameof(AlienRace.HarmonyPatches.BirthOutcomeMultiplier)), + postfix: new HarmonyMethod(typeof(HAR_LitterSize_Undo).GetMethod(nameof(HAR_LitterSize_Undo.Postfix)))); + } + + InjectIntoRjwInteractionServices(); + } + private static void InjectIntoRjwInteractionServices() + { + ILog log = LogManager.GetLogger("StaticConstructorOnStartup"); + + List partKindUsageRules = Unprivater.GetProtectedValue>("_partKindUsageRules", typeof(PartPreferenceDetectorService)); + partKindUsageRules.Add(new Interactions.EstrusPartKindUsageRule()); + log.Message("Added 1 rule to PartPreferenceDetectorService._partKindUsageRules"); + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/Pawn_Patch.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/Pawn_Patch.cs new file mode 100644 index 0000000..c2f1176 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/Pawn_Patch.cs @@ -0,0 +1,111 @@ +using HarmonyLib; +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Verse; + +namespace RJW_Menstruation +{ + + [HarmonyPatch(typeof(Pawn), nameof(Pawn.SpawnSetup))] + public class Pawn_Patch + { + public static void Postfix(Pawn __instance) + { + //Log.Message("Initialize on spawnsetup"); + foreach (HediffComp_Menstruation comp in __instance.GetMenstruationComps()) + { + comp.Initialize(); + } + + __instance.GetBreastComp()?.Initialize(); + } + } + + [HarmonyPatch(typeof(FloatMenuMakerMap), "AddHumanlikeOrders")] + public class HumanlikeOrder_Patch + { + public static void Postfix(Vector3 clickPos, Pawn pawn, List opts) + { + IEnumerable selftargets = GenUI.TargetsAt(clickPos, TargetingParameters.ForSelf(pawn)); + + foreach (LocalTargetInfo t in selftargets) + { + if (t.Pawn == pawn && pawn.HasMenstruationComp()) opts.AddDistinct(MakeSelfMenu(pawn, t)); + break; + } + } + + public static FloatMenuOption MakeSelfMenu(Pawn pawn, LocalTargetInfo target) + { + FloatMenuOption option = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(Translations.FloatMenu_CleanSelf, delegate () + { + pawn.jobs.TryTakeOrderedJob(new Verse.AI.Job(VariousDefOf.VaginaWashing, null, null, target.Cell)); + }, MenuOptionPriority.Low), pawn, target); + + return option; + } + } + + [HarmonyPatch(typeof(HealthCardUtility), "DrawOverviewTab")] + public class DrawOverviewTab_Patch + { + public const float buttonWidth = 50f; + public const float buttonHeight = 20f; + + public static void Prefix(Rect leftRect, Pawn pawn, float curY) + { + if (Configurations.EnableButtonInHT && pawn.ShowStatus() && pawn.ShouldCycle()) + { + HediffComp_Menstruation comp = pawn.GetFirstMenstruationComp(); + if (comp != null) + { + Text.Font = GameFont.Tiny; + Rect buttonRect = new Rect(leftRect.xMax - buttonWidth - 8f, curY + 4f, buttonWidth, buttonHeight); + if (Widgets.ButtonText(buttonRect, Translations.Button_HealthTab)) + { + Dialog_WombStatus.ToggleWindow(pawn, comp); + } + } + } + } + } + + [HarmonyPatch(typeof(CompBiosculpterPod), nameof(CompBiosculpterPod.CannotUseNowPawnCycleReason), new Type[] { typeof(Pawn), typeof(Pawn), typeof(CompBiosculpterPod_Cycle), typeof(bool) })] + public class CannotUseNowPawnCycleReason_Patch + { + private const string eggRestorationKey = "eggRestoration"; + public static void Postfix(ref string __result, Pawn biosculptee, CompBiosculpterPod_Cycle cycle) + { + if (__result != null) return; + if (cycle.Props.key == eggRestorationKey && !biosculptee.GetMenstruationComps().Any()) + __result = Translations.CannotNoWomb; + } + } + + // Doesn't cover everything, but at least it'll get the auto equip + [HarmonyPatch(typeof(Apparel), nameof(Apparel.PawnCanWear))] + public class PawnCanWear_Patch + { + public static void Postfix(ref bool __result, Apparel __instance, Pawn pawn) + { + if (__result && __instance is Absorber) + { + __result = pawn.ShouldCycle() && pawn.GetMenstruationComps().Any(); + } + } + } + + // Might cause issues when it comes to caravans + //[HarmonyPatch(typeof(JobGiver_OptimizeApparel), nameof(JobGiver_OptimizeApparel.ApparelScoreRaw))] + //public class ApparelScoreRaw_Patch + //{ + // public static void Postfix(ref float __result, Pawn pawn, Apparel ap) + // { + // if (__result > 0f && ap is Absorber && !pawn.GetMenstruationComps().Any(comp => comp.TotalCum > 0)) + // __result = -10f; + // } + //} +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/RJW_Patch.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/RJW_Patch.cs new file mode 100644 index 0000000..eb776e3 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Patch/RJW_Patch.cs @@ -0,0 +1,387 @@ +using HarmonyLib; +using RimWorld; +using rjw; +using rjw.Modules.Interactions.Enums; +using rjw.Modules.Interactions.Objects; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using UnityEngine; +using Verse; + +namespace RJW_Menstruation +{ + + [HarmonyPatch(typeof(PregnancyHelper), nameof(PregnancyHelper.impregnate))] + public static class Impregnate_Patch + { + public static bool Prefix(SexProps props) + { + xxx.rjwSextype sextype = props.sexType; + Pawn pawn = props.pawn; + Pawn partner = props.partner; + + if (sextype != xxx.rjwSextype.Vaginal && sextype != xxx.rjwSextype.DoublePenetration) return true; + + if (!partner.ShouldCycle()) return true; + + if (!InteractionCanCausePregnancy(props)) return false; + + List pawnparts = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn)); + + HediffComp_Menstruation comp; + if (pawn.HasImpregnationFetish() || partner.HasImpregnationFetish() || partner.IsInEstrus()) + comp = partner.GetFertileMenstruationComp(); + else comp = partner.GetRandomMenstruationComp(); + if (comp == null) return true; + + if (Genital_Helper.has_penis_fertile(pawn, pawnparts) && PregnancyHelper.CanImpregnate(pawn, partner, sextype)) + { + PregnancyHelper.DoImpregnate(pawn, partner); + return false; + } + else if (Genital_Helper.has_ovipositorM(pawn, pawnparts)) + { + comp.CumIn(pawn, Rand.Range(0.75f, 4.5f) * pawn.BodySize, pawn.SterileGenes() ? 0.0f : 1.0f); + } + else comp.CumIn(pawn, pawn.GetCumVolume(pawnparts), 0); + + return true; + } + + public static void Postfix(SexProps props) + { + Pawn pawn = props.partner; + + if (props.sexType != xxx.rjwSextype.MechImplant && pawn.health.hediffSet.GetFirstHediff() == null) return; + + // The existing pregnancies might have been destroyed, so go through see if any new mech pregnancies need to be picked up + foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps()) + { + _ = comp.Pregnancy; // get_Pregnancy will do any removals + comp.TakeLoosePregnancy(); + } + } + + /// + /// Checks if pregnancy can happen based on the interaction def + /// This is needed for futanari sex, but should work for everyone + /// + /// + /// Interaction can result in pregnancy + public static bool InteractionCanCausePregnancy(SexProps props) + { + InteractionWithExtension interaction = rjw.Modules.Interactions.Helpers.InteractionHelper.GetWithExtension(props.dictionaryKey); + + if (!interaction.HasInteractionTag(InteractionTag.Fertilization)) + return false; + + bool usesPawnsPenis; + bool usesPartnersVagina; + + if (!props.isReceiver) + { + usesPawnsPenis = interaction.DominantHasTag(GenitalTag.CanPenetrate); + usesPartnersVagina = interaction.SubmissiveHasFamily(GenitalFamily.Vagina); + } + else + { + usesPawnsPenis = interaction.SubmissiveHasTag(GenitalTag.CanPenetrate); + usesPartnersVagina = interaction.DominantHasFamily(GenitalFamily.Vagina); + } + + return usesPawnsPenis && usesPartnersVagina; + } + } + + [HarmonyPatch(typeof(PregnancyHelper), nameof(PregnancyHelper.DoImpregnate))] + public static class DoImpregnate_Patch + { + public static bool Prefix(Pawn pawn, Pawn partner) // partner has vagina + { + if (!partner.ShouldCycle()) return true; + HediffComp_Menstruation comp; + if (pawn.HasImpregnationFetish() || partner.HasImpregnationFetish() || partner.IsInEstrus()) + comp = partner.GetFertileMenstruationComp(); + else comp = partner.GetRandomMenstruationComp(); + if (comp == null) + { + if (Configurations.Debug) ModLog.Message("used original rjw method: Comp missing"); + return true; + } + else if (AndroidsCompatibility.IsAndroid(pawn) && !AndroidsCompatibility.AndroidPenisFertility(pawn)) + { + comp.CumIn(pawn, pawn.GetCumVolume(), 0); + return false; + } + else comp.CumIn(pawn, pawn.GetCumVolume(), pawn.SterileGenes() ? 0.0f : pawn.health.capacities.GetLevel(xxx.reproduction)); + return false; + } + } + + [HarmonyPatch(typeof(PregnancyHelper), nameof(PregnancyHelper.CanImpregnate))] + public static class CanImpregnate_Patch + { + private static bool PregnancyBlocksImpregnation(this Pawn pawn, bool _) + { + if (!pawn.ShouldCycle()) return pawn.IsPregnant(); + else if (pawn.GetMenstruationComps().Any()) return false; + else return pawn.IsPregnant(); + } + private static readonly MethodInfo IsPregnant = AccessTools.Method(typeof(PawnExtensions), nameof(PawnExtensions.IsPregnant), new System.Type[] { typeof(Pawn), typeof(bool) }); + public static IEnumerable Transpiler(IEnumerable instructions) + { + if (IsPregnant?.ReturnType != typeof(bool)) throw new System.InvalidOperationException("IsPregnant not found"); + foreach (CodeInstruction instruction in instructions) + { + if (instruction.Calls(IsPregnant)) + yield return CodeInstruction.Call(typeof(CanImpregnate_Patch), nameof(PregnancyBlocksImpregnation)); + else yield return instruction; + } + } + } + + [HarmonyPatch(typeof(Hediff_BasePregnancy), nameof(Hediff_BasePregnancy.PostBirth))] + public static class RJW_Patch_PostBirth + { + public static void Postfix(Hediff_BasePregnancy __instance, Pawn mother, Pawn baby) + { + if (Configurations.EnableBirthVaginaMorph) + { + // The comp still has the pregnancy attached at this point in the process + Hediff vagina = (__instance.GetMenstruationCompFromPregnancy()?.parent) ?? mother.health.hediffSet.hediffs.FirstOrFallback(x => VariousDefOf.AllVaginas.Contains(x.def)); + if (vagina == null) return; + float morph = Mathf.Max(baby.BodySize - Mathf.Pow(vagina.Severity * mother.BodySize, 2), 0f); + vagina.Severity += morph * Configurations.VaginaMorphPower; + } + } + } + + [HarmonyPatch(typeof(Quirk), nameof(Quirk.IsSatisfiedBy))] + public static class IsSatisfiedBy_Patch + { + public static void Postfix(Quirk __instance, ref bool __result, Pawn pawn, Pawn partner) + { + // This is stricter than can_impregnate, so quickly filter out scenarios that are negative anyways. + if (__result == false || __instance != Quirk.ImpregnationFetish) return; + __result = + (PregnancyHelper.CanImpregnate(pawn, partner) && (partner.GetMenstruationComps()?.Any(comp => comp.IsDangerDay) ?? true)) + || + (PregnancyHelper.CanImpregnate(partner, pawn) && (pawn.GetMenstruationComps()?.Any(comp => comp.IsDangerDay) ?? true)); + } + } + + [HarmonyPatch(typeof(Quirk), nameof(Quirk.CountSatisfiedQuirks))] + public static class CountSatisfiedQuirks_Patch + { + public static void Postfix(ref int __result, SexProps props) + { + // Awkward, but it'll have to do + Pawn pawn = props.pawn; + if (__result == 0 || !pawn.HasImpregnationFetish() || !props.hasPartner()) return; + + // Check if the existing code would have added the count + Pawn partner = props.partner; + if (!(PregnancyHelper.CanImpregnate(pawn, partner, props.sexType) || PregnancyHelper.CanImpregnate(partner, pawn, props.sexType))) return; + else __result--; + + if ( + (PregnancyHelper.CanImpregnate(pawn, partner, props.sexType) && (partner.GetMenstruationComps()?.Any(comp => comp.IsDangerDay) ?? true)) + || + (PregnancyHelper.CanImpregnate(partner, pawn, props.sexType) && (pawn.GetMenstruationComps()?.Any(comp => comp.IsDangerDay) ?? true))) + __result++; + } + } + + [HarmonyPatch(typeof(SexAppraiser), "GetBodyFactor")] + public static class GetBodyFactor_Patch + { + private static float GetNetFertility(Pawn fucker, Pawn fucked) + { + float fert = fucked.health.capacities.GetLevel(xxx.reproduction); + if (fucker.def.defName != fucked.def.defName) + { + if (RJWPregnancySettings.complex_interspecies) + fert *= SexUtility.BodySimilarity(fucker, fucked); + else + fert *= RJWPregnancySettings.interspecies_impregnation_modifier; + } + return fert; + } + public static void Postfix(ref float __result, Pawn fucker, Pawn fucked) + { + if (fucker.IsInEstrus(true) && PregnancyHelper.CanImpregnate(fucked, fucker)) + { + __result *= (1f + GetNetFertility(fucker, fucked) / 4); + } + else if (fucker.IsInEstrus(false) && PregnancyHelper.CanImpregnate(fucked, fucker)) + { + __result *= (1f + GetNetFertility(fucker, fucked) / 40); + } + else if (xxx.is_animal(fucker) && fucked.IsInEstrus(true) && PregnancyHelper.CanImpregnate(fucker, fucked)) + { + __result *= 1.25f; + } + } + } + + [HarmonyPatch(typeof(CasualSex_Helper), nameof(CasualSex_Helper.roll_to_skip))] + public static class Roll_To_Skip_Patch + { + private static float FuckabilityThreshold(Pawn pawn, Pawn partner) + { + return (Configurations.EstrusOverridesHookupSettings && pawn.IsInEstrus() && PregnancyHelper.CanImpregnate(partner, pawn)) + ? Configurations.EstrusFuckabilityToHookup : RJWHookupSettings.MinimumFuckabilityToHookup; + } + + private static readonly FieldInfo MinimumFuckabilityToHookup = AccessTools.Field(typeof(RJWHookupSettings), nameof(RJWHookupSettings.MinimumFuckabilityToHookup)); + public static IEnumerable Transpiler(IEnumerable instructions) + { + if (MinimumFuckabilityToHookup?.FieldType != typeof(float)) throw new System.InvalidOperationException("MinimumFuckabilityToHookup not found"); + bool first_fuckability = true; + foreach (CodeInstruction instruction in instructions) + { + if (instruction.LoadsField(MinimumFuckabilityToHookup)) + { + // The first load will be for the estrus-haver considering a partner, the second for a pawn considering the estrus-haver + yield return new CodeInstruction(first_fuckability ? OpCodes.Ldarg_0 : OpCodes.Ldarg_1); + yield return new CodeInstruction(first_fuckability ? OpCodes.Ldarg_1 : OpCodes.Ldarg_0); + + yield return CodeInstruction.Call(typeof(Roll_To_Skip_Patch), nameof(FuckabilityThreshold)); + first_fuckability = false; + } + else yield return instruction; + } + } + } + + [HarmonyPatch(typeof(CasualSex_Helper), nameof(CasualSex_Helper.FindBestPartner))] + public static class FindBestPartner_Patch + { + private static float AttractivenessThreshold(Pawn pawn, Pawn partner) + { + return (Configurations.EstrusOverridesHookupSettings && pawn.IsInEstrus() && PregnancyHelper.CanImpregnate(partner, pawn)) + ? Configurations.EstrusAttractivenessToHookup : RJWHookupSettings.MinimumAttractivenessToHookup; + } + private static float RelationshipThreshold(Pawn pawn, Pawn partner) + { + return (Configurations.EstrusOverridesHookupSettings && pawn.IsInEstrus() && PregnancyHelper.CanImpregnate(partner, pawn)) + ? Configurations.EstrusRelationshipToHookup : RJWHookupSettings.MinimumRelationshipToHookup; + } + + private static readonly FieldInfo MinimumAttractivenessToHookup = AccessTools.Field(typeof(RJWHookupSettings), nameof(RJWHookupSettings.MinimumAttractivenessToHookup)); + private static readonly FieldInfo MinimumRelationshipToHookup = AccessTools.Field(typeof(RJWHookupSettings), nameof(RJWHookupSettings.MinimumRelationshipToHookup)); + public static IEnumerable Transpiler(IEnumerable instructions) + { + if (MinimumAttractivenessToHookup?.FieldType != typeof(float)) throw new System.InvalidOperationException("MinimumAttractivenessToHookup not found"); + if (MinimumRelationshipToHookup?.FieldType != typeof(float)) throw new System.InvalidOperationException("MinimumRelationshipToHookup not found"); + LocalBuilder pawn_index = null; + // Like in the last one, we switch the arguments around for the second load + bool first_attractiveness = true; + bool first_relationship = true; + foreach (CodeInstruction instruction in instructions) + { + // Get where the compiler decided to index the pawn at + if (pawn_index == null && instruction.opcode == OpCodes.Stloc_S) // the first stloc.s in the IL is the pawn being loaded out of the list + { // a future RJW or compiler update might change this, or maybe another mod's patch + pawn_index = (LocalBuilder)instruction.operand; + yield return instruction; + } + else if (instruction.LoadsField(MinimumAttractivenessToHookup)) + { + if (pawn_index?.LocalType != typeof(Pawn)) + throw new System.InvalidOperationException($"pawn_index is not a Pawn ({pawn_index?.LocalType})"); + + yield return first_attractiveness ? new CodeInstruction(OpCodes.Ldarg_0) : new CodeInstruction(OpCodes.Ldloc_S, pawn_index); + yield return first_attractiveness ? new CodeInstruction(OpCodes.Ldloc_S, pawn_index) : new CodeInstruction(OpCodes.Ldarg_0); + + yield return CodeInstruction.Call(typeof(FindBestPartner_Patch), nameof(AttractivenessThreshold)); + first_attractiveness = false; + } + else if (instruction.LoadsField(MinimumRelationshipToHookup)) + { + if (pawn_index?.LocalType != typeof(Pawn)) + throw new System.InvalidOperationException($"pawn_index is not a Pawn ({pawn_index?.LocalType})"); + + yield return first_relationship ? new CodeInstruction(OpCodes.Ldarg_0) : new CodeInstruction(OpCodes.Ldloc_S, pawn_index); + yield return first_relationship ? new CodeInstruction(OpCodes.Ldloc_S, pawn_index) : new CodeInstruction(OpCodes.Ldarg_0); + + yield return CodeInstruction.Call(typeof(FindBestPartner_Patch), nameof(RelationshipThreshold)); + first_relationship = false; + } + else yield return instruction; + } + } + } + + [HarmonyPatch(typeof(JobDriver_Sex), nameof(JobDriver_Sex.PlayCumSound))] + public static class Orgasm_Patch + { + public static void Postfix(JobDriver_Sex __instance) + { +#if false + Pawn pawn = __instance.pawn; + foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps()) + { + comp.CumIn(pawn, (comp.parent.Severity / 10) * Rand.Range(0.75f, 1.25f), pawn.Label, -5.0f, VariousDefOf.GirlCumFilth); + } +#endif + } + } + + [HarmonyPatch(typeof(JobDriver_Sex), nameof(JobDriver_Sex.SexTick))] + public static class SexTick_Patch + { + private const float fertilePrecummersPercentage = 0.33f; + private const float precumRatio = 0.1f; // Relative to ejaculation volume + private const float precumFertility = 0.5f; + private const float expectedDurationTicks = 2000f * (0.9f - 0.5f) / 2; + + public static void Postfix(JobDriver_Sex __instance, Pawn pawn, Thing target) + { + if (!pawn.IsHashIntervalTick(__instance.ticks_between_thrusts)) return; + xxx.rjwSextype sextype = __instance.Sexprops.sexType; + if (!(target is Pawn partner)) return; + if (sextype != xxx.rjwSextype.Vaginal && sextype != xxx.rjwSextype.DoublePenetration) return; + if (__instance.Sexprops.usedCondom) return; + if (AndroidsCompatibility.IsAndroid(pawn)) return; + if (!Impregnate_Patch.InteractionCanCausePregnancy(__instance.Sexprops)) return; + if (!partner.ShouldCycle()) return; + + // Archotech penises have more control. Or something. + CompHediffBodyPart penisComp = pawn.GetGenitalsList()?.Find(genital => (genital as Hediff_PartBaseNatural)?.def.defName.ToLower().Contains("penis") ?? false)?.TryGetComp(); + if (penisComp == null || Rand.ChanceSeeded(1.0f - fertilePrecummersPercentage, Gen.HashOffset(penisComp.parent.loadID))) return; + HediffComp_Menstruation vaginaComp = partner.GetRandomMenstruationComp(); + if (vaginaComp == null) return; + + float precumAmount = pawn.GetCumVolume(penisComp) * precumRatio * __instance.ticks_between_thrusts / expectedDurationTicks; + vaginaComp.CumIn(pawn, precumAmount, pawn.SterileGenes() ? 0.0f : precumFertility * pawn.health.capacities.GetLevel(xxx.reproduction), true); + } + } + + [HarmonyPatch(typeof(CompHediffBodyPart), nameof(CompHediffBodyPart.updatesize))] + public static class Updatesize_Patch + { + public static void Postfix(CompHediffBodyPart __instance) + { + HediffComp_Breast comp = __instance.parent.GetBreastComp(); + if (comp != null) + { + __instance.parent.Severity += comp.BreastSizeIncreased; + } + + } + } + + [HarmonyPatch(typeof(PawnCapacityWorker_Fertility), "CalculateAgeImpact")] + public static class PawnCapacityWorker_Fertility_Age_Patch + { + public static void Postfix(ref float __result, Pawn pawn) + { + if (__result <= 0.0f) return; + if (pawn.GetMenstruationComps().Any(comp => comp.CalculatingOvulationChance)) + __result = 1.0f; + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/PregnancyCommon.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/PregnancyCommon.cs new file mode 100644 index 0000000..9b9bdad --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/PregnancyCommon.cs @@ -0,0 +1,320 @@ +using RimWorld; +using rjw; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using Verse; + +namespace RJW_Menstruation +{ + public static class PregnancyCommon + { + private static readonly MethodInfo TryGetInheritedXenotype = typeof(PregnancyUtility).GetMethod("TryGetInheritedXenotype", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(Pawn), typeof(Pawn), typeof(XenotypeDef).MakeByRefType() }, null); + private static readonly MethodInfo ShouldByHybrid = typeof(PregnancyUtility).GetMethod("ShouldByHybrid", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(Pawn), typeof(Pawn) }, null); + + public static string GetBabyInfo(IEnumerable babies) + { + if (babies == null || !babies.Any()) return "Null"; + + StringBuilder res = new StringBuilder(); + + int iteration = 0; + foreach (Pawn baby in babies.Distinct(new RaceComparer())) + { + int num = babies.Where(x => x.def.Equals(baby.def)).Count(); + if (iteration > 0) res.Append(", "); + res.AppendFormat("{0} {1}", num, baby.def.label); + iteration++; + } + res.AppendFormat(" {0}", Translations.Dialog_WombInfo02); + return res.ToString(); + } + + public static string GetFatherInfo(IEnumerable babies, Pawn mother, bool is_parent_known) + { + if (babies == null || !babies.Any()) return "Null"; + + StringBuilder res = new StringBuilder(); + res.AppendFormat("{0}: ", Translations.Dialog_WombInfo03); + + if (!is_parent_known && Configurations.InfoDetail != Configurations.DetailLevel.All) + return res.Append(Translations.Dialog_FatherUnknown).ToString(); + + int iteration = 0; + foreach (Pawn baby in babies.Distinct(new FatherComparer(mother))) + { + if (iteration > 0) res.Append(", "); + res.Append(Utility.GetFather(baby, mother)?.LabelShort ?? Translations.Dialog_FatherUnknown); + iteration++; + } + return res.ToString(); + } + + /// + /// Decide pawnkind from mother and father + /// Come from RJW + /// + /// + /// + /// + + /// + public static PawnKindDef BabyPawnKindDecider(Pawn mother, Pawn father, bool noAnimalsFromHumanlikes) + { + PawnKindDef motherKindDef = Utility.GetRacesPawnKind(mother); + PawnKindDef fatherKindDef = Utility.GetRacesPawnKind(father); + + PawnKindDef spawn_kind_def = motherKindDef; + + int flag = 0; + if (xxx.is_human(mother)) flag += 2; + if (xxx.is_human(father)) flag += 1; + //Mother - Father = Flag + //Human - Human = 3 + //Human - Animal = 2 + //Animal - Human = 1 + //Animal - Animal = 0 + + switch (flag) + { + case 3: + if (!Rand.Chance(RJWPregnancySettings.humanlike_DNA_from_mother)) spawn_kind_def = fatherKindDef; + break; + case 2: + if (RJWPregnancySettings.bestiality_DNA_inheritance == 0f) spawn_kind_def = fatherKindDef; + else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef; + break; + case 1: + if (RJWPregnancySettings.bestiality_DNA_inheritance == 1f) spawn_kind_def = fatherKindDef; + else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef; + break; + case 0: + if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef; + break; + } + + bool IsAndroidmother = AndroidsCompatibility.IsAndroid(mother); + bool IsAndroidfather = AndroidsCompatibility.IsAndroid(father); + if (IsAndroidmother && !IsAndroidfather) + { + spawn_kind_def = fatherKindDef; + } + else if (!IsAndroidmother && IsAndroidfather) + { + spawn_kind_def = motherKindDef; + } + + string MotherRaceName = ""; + string FatherRaceName = ""; + MotherRaceName = motherKindDef?.race?.defName; + PawnKindDef non_hybrid_kind_def = spawn_kind_def; + if (father != null) + FatherRaceName = fatherKindDef?.race?.defName; + + + if (FatherRaceName != "" && Configurations.UseHybridExtention) + { + spawn_kind_def = GetHybrid(father, mother); + //Log.Message("pawnkind: " + spawn_kind_def?.defName); + } + + if (MotherRaceName != FatherRaceName && FatherRaceName != "") + { + if (!Configurations.UseHybridExtention || spawn_kind_def == null) + { + spawn_kind_def = non_hybrid_kind_def; + IEnumerable groups = DefDatabase.AllDefs.Where(x => !(x.hybridRaceParents.NullOrEmpty() || x.hybridChildKindDef.NullOrEmpty())); + + + //ModLog.Message(" found custom RaceGroupDefs " + groups.Count()); + foreach (RaceGroupDef t in groups) + { + if ((t.hybridRaceParents.Contains(MotherRaceName) && t.hybridRaceParents.Contains(FatherRaceName)) + || (t.hybridRaceParents.Contains("Any") && (t.hybridRaceParents.Contains(MotherRaceName) || t.hybridRaceParents.Contains(FatherRaceName)))) + { + //ModLog.Message(" has hybridRaceParents"); + if (t.hybridChildKindDef.Contains("MotherKindDef")) + spawn_kind_def = motherKindDef; + else if (t.hybridChildKindDef.Contains("FatherKindDef") && father != null) + spawn_kind_def = fatherKindDef; + else + { + //ModLog.Message(" trying hybridChildKindDef " + t.defName); + List child_kind_def_list = new List(); + child_kind_def_list.AddRange(DefDatabase.AllDefs.Where(x => t.hybridChildKindDef.Contains(x.defName))); + + //ModLog.Message(" found custom hybridChildKindDefs " + t.hybridChildKindDef.Count); + if (!child_kind_def_list.NullOrEmpty()) + spawn_kind_def = child_kind_def_list.RandomElement(); + } + } + } + } + + } + else if (!Configurations.UseHybridExtention || spawn_kind_def == null) + { + spawn_kind_def = mother.RaceProps?.AnyPawnKind ?? motherKindDef; + } + + if (spawn_kind_def.defName.Contains("Nymph")) + { + //child is nymph, try to find other PawnKindDef + List spawn_kind_def_list = new List(); + spawn_kind_def_list.AddRange(DefDatabase.AllDefs.Where(x => x.race == spawn_kind_def.race && !x.defName.Contains("Nymph"))); + //no other PawnKindDef found try mother + if (spawn_kind_def_list.NullOrEmpty()) + spawn_kind_def_list.AddRange(DefDatabase.AllDefs.Where(x => x.race == motherKindDef.race && !x.defName.Contains("Nymph"))); + //no other PawnKindDef found try father + if (spawn_kind_def_list.NullOrEmpty() && father != null) + spawn_kind_def_list.AddRange(DefDatabase.AllDefs.Where(x => x.race == fatherKindDef.race && !x.defName.Contains("Nymph"))); + //no other PawnKindDef found fallback to generic colonist + if (spawn_kind_def_list.NullOrEmpty()) + spawn_kind_def = PawnKindDefOf.Colonist; + + if (!spawn_kind_def_list.NullOrEmpty()) spawn_kind_def = spawn_kind_def_list.RandomElement(); + } + + // If both parents are humanlike, Biotech will attempt to assign genes to the child + // Normally not a problem, but with the hybrid system, two humanlikes might produce an animal + // So override it and force the child to be human + if (noAnimalsFromHumanlikes && mother.genes != null && father?.genes != null && !spawn_kind_def.race.race.Humanlike) + spawn_kind_def = Rand.Chance(RJWPregnancySettings.humanlike_DNA_from_mother) ? motherKindDef : fatherKindDef; + + return spawn_kind_def; + + } + + public static void SetupBabyXenotype(Pawn mother, Pawn father, Pawn baby) + { + if (baby.genes == null || !ModsConfig.BiotechActive) return; + + if (GeneUtility.SameHeritableXenotype(mother, father) && mother.genes.UniqueXenotype) + { + baby.genes.xenotypeName = mother.genes.xenotypeName; + baby.genes.iconDef = mother.genes.iconDef; + } + + object[] args = new object[] { mother, father, null }; + if ((bool)TryGetInheritedXenotype.Invoke(null, args)) + { + baby.genes.SetXenotypeDirect((XenotypeDef)args[2]); + } + else if ((bool)ShouldByHybrid.Invoke(null, new object[] { mother, father })) + { + baby.genes.hybrid = true; + baby.genes.xenotypeName = "Hybrid".Translate(); + } + } + + public static PawnKindDef GetHybrid(Pawn first, Pawn second) + { + PawnKindDef res = null; + Pawn opposite = second; + HybridInformations info = null; + + + if (!Configurations.HybridOverride.NullOrEmpty()) + { + info = Configurations.HybridOverride.FirstOrDefault(x => x.DefName == first.def?.defName && (x.hybridExtension?.Exists(y => y.DefName == second.def?.defName) ?? false)); + if (info == null) + { + info = Configurations.HybridOverride.FirstOrDefault(x => x.DefName == second.def?.defName && (x.hybridExtension?.Exists(y => y.DefName == first.def?.defName) ?? false)); + opposite = first; + } + } + + if (info != null) + { + res = info.GetHybridWith(opposite.def.defName) ?? null; + } + if (res != null) return res; + + + PawnDNAModExtension dna; + dna = first.def.GetModExtension(); + if (dna != null) + { + res = dna.GetHybridWith(second.def.defName) ?? null; + } + else + { + dna = second.def.GetModExtension(); + if (dna != null) + { + res = dna.GetHybridWith(first.def.defName) ?? null; + } + } + return res; + } + + private static void CopyBodyPartProperties(Hediff part, Hediff originalPart) + { + CompHediffBodyPart comp = part.TryGetComp(); + CompHediffBodyPart originalComp = originalPart.TryGetComp(); + + if (comp != null && originalComp != null) + { + // the string properties should be the same between both pawns anyways, besides the name of the owner + part.Severity = originalPart.Severity; + comp.SizeBase = originalComp.SizeBase; + comp.SizeOwner = originalComp.SizeOwner; + comp.EffSize = originalComp.EffSize; + comp.FluidAmmount = originalComp.FluidAmmount; + comp.FluidModifier = originalComp.FluidModifier; + } + + HediffComp_Menstruation originalMenstruationComp = originalPart.GetMenstruationCompFromVagina(); + if (originalMenstruationComp != null) + { + part.GetMenstruationCompFromVagina()?.CopyCycleProperties(originalMenstruationComp); + } + HediffComp_Breast originalBreastComp = originalPart.GetBreastComp(); + if (originalBreastComp != null) + { + part.GetBreastComp()?.CopyBreastProperties(originalBreastComp); + } + } + + private static void CopyBodyPartRecord(Pawn baby, Pawn original, BodyPartRecord babyBPR, BodyPartRecord originalBPR) + { + if (babyBPR == null || originalBPR == null) return; + + Hediff_BasePregnancy.RemoveBabyParts(baby, Genital_Helper.get_PartsHediffList(baby, babyBPR)); + foreach (Hediff originalPart in Genital_Helper.get_PartsHediffList(original, originalBPR)) + { + Hediff part = SexPartAdder.MakePart(originalPart.def, baby, babyBPR); + CopyBodyPartProperties(part, originalPart); + baby.health.AddHediff(part, babyBPR); + } + } + + // Baby is the sibling to be changed, original is the first of the set and the one to copy to the rest. + public static void ProcessIdenticalSibling(Pawn baby, Pawn original) + { + // They'll be the same pawnkind, which lets us make a lot of useful assumptions + // However, some RNG might still be involved in genital generation (e.g. futas), so the easiest method is to clear out and re-generate + // A bit wasteful since Hediff_BasePregnancy.PostBirth already redid the genitals + CopyBodyPartRecord(baby, original, Genital_Helper.get_genitalsBPR(baby), Genital_Helper.get_genitalsBPR(original)); + CopyBodyPartRecord(baby, original, Genital_Helper.get_breastsBPR(baby), Genital_Helper.get_breastsBPR(original)); + CopyBodyPartRecord(baby, original, Genital_Helper.get_uddersBPR(baby), Genital_Helper.get_uddersBPR(original)); + CopyBodyPartRecord(baby, original, Genital_Helper.get_anusBPR(baby), Genital_Helper.get_anusBPR(original)); + } + + public static string DueDate(this Hediff_BasePregnancy preg) + { + if (preg.pawn.Tile == -1) return ""; + return GenDate.DateFullStringWithHourAt(GenDate.TickGameToAbs((int)preg.p_end_tick), Find.WorldGrid.LongLatOf(preg.pawn.Tile)); + } + + public static string DueDate(this Hediff_Pregnant preg) + { + if (preg.pawn.Tile == -1) return ""; + int ticksRemaining = (int)((1f - preg.GestationProgress) * preg.pawn.RaceProps.gestationPeriodDays * GenDate.TicksPerDay); + int dueTickAbs = GenTicks.TicksAbs + ticksRemaining; + return GenDate.DateFullStringWithHourAt(dueTickAbs, Find.WorldGrid.LongLatOf(preg.pawn.Tile)); + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/QuirkUtility.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/QuirkUtility.cs new file mode 100644 index 0000000..409d3d7 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/QuirkUtility.cs @@ -0,0 +1,37 @@ +using rjw; +using Verse; + +namespace RJW_Menstruation +{ + public static class QuirkUtility + { + // All quirks used in Menstruation + private enum Quirks + { + Breeder, + ImpregnationFetish, + Messy, + Teratophile, + } + private static bool HasQuirk(Pawn pawn, Quirks quirk) + { + switch (quirk) + { + case Quirks.Breeder: + return pawn.Has(Quirk.Breeder); + case Quirks.ImpregnationFetish: + return pawn.Has(Quirk.ImpregnationFetish); + case Quirks.Messy: + return pawn.Has(Quirk.Messy); + case Quirks.Teratophile: + return pawn.Has(Quirk.Teratophile); + default: + return false; + } + } + public static bool IsBreeder(this Pawn pawn) => HasQuirk(pawn, Quirks.Breeder); + public static bool HasImpregnationFetish(this Pawn pawn) => HasQuirk(pawn, Quirks.ImpregnationFetish); + public static bool IsMessy(this Pawn pawn) => HasQuirk(pawn, Quirks.Messy); + public static bool IsTeratophile(this Pawn pawn) => HasQuirk(pawn, Quirks.Teratophile); + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/RJW_Menstruation.csproj b/1.5/source/RJW_Menstruation/RJW_Menstruation/RJW_Menstruation.csproj new file mode 100644 index 0000000..33cf9ec --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/RJW_Menstruation.csproj @@ -0,0 +1,188 @@ + + + + + Debug + AnyCPU + {EED2F3B9-8C20-4194-919E-8D151B29F70B} + Library + RJW_Menstruation + RJW_Menstruation + v4.8 + 512 + true + true + 게시\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + AnyCPU + true + full + false + ..\..\..\Assemblies\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + ..\..\..\Assemblies\ + TRACE + prompt + 4 + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ..\..\..\..\..\..\..\..\workshop\content\294100\839005762\1.4\Assemblies\AlienRace.dll + False + + + ..\..\..\..\..\..\..\..\workshop\content\294100\2830943477\1.4\Assemblies\AnimalGenetics.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll + False + + + ..\..\..\..\..\rjw\1.4\Assemblies\RJW.dll + False + + + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.IMGUIModule.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.InputLegacyModule.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.InputModule.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.TextCoreModule.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.TextRenderingModule.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.UI.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.UIElementsModule.dll + False + + + ..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.UIModule.dll + False + + + + + False + Microsoft .NET Framework 4.7.2%28x86 및 x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + + 2.2.2 + runtime + compile; build; native; contentfiles; analyzers; buildtransitive + + + + + changelogs.txt + + + + \ No newline at end of file diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Recipe_Surgery.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Recipe_Surgery.cs new file mode 100644 index 0000000..6473ac4 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Recipe_Surgery.cs @@ -0,0 +1,88 @@ +using RimWorld; +using rjw; +using System.Collections.Generic; +using Verse; + + +namespace RJW_Menstruation +{ + public class Recipe_BreastSurgery : Recipe_Surgery + { + public override IEnumerable GetPartsToApplyOn(Pawn pawn, RecipeDef recipe) + { + BodyPartRecord part = Genital_Helper.get_breastsBPR(pawn) ?? Genital_Helper.get_uddersBPR(pawn); + if (part != null) + { + + if (pawn.GetBreastComp() != null) yield return part; + } + } + + public override void ApplyOnPawn(Pawn pawn, BodyPartRecord part, Pawn billDoer, List ingredients, Bill bill) + { + HediffComp_Breast breast = pawn.GetBreastComp(); + if (billDoer != null && breast != null) + { + TaleRecorder.RecordTale(TaleDefOf.DidSurgery, new object[] + { + billDoer, + pawn + }); + SurgeryResult(breast); + } + } + + protected virtual void SurgeryResult(HediffComp_Breast breast) + { + } + } + + + public class Recipe_ExpandAreola : Recipe_BreastSurgery + { + protected override void SurgeryResult(HediffComp_Breast breast) + { + breast.AdjustAreolaSizeImmediately(0.2f); + } + } + + public class Recipe_ContractAreola : Recipe_BreastSurgery + { + protected override void SurgeryResult(HediffComp_Breast breast) + { + breast.AdjustAreolaSizeImmediately(-0.2f); + } + } + + public class Recipe_ExpandNipple : Recipe_BreastSurgery + { + protected override void SurgeryResult(HediffComp_Breast breast) + { + breast.AdjustNippleSizeImmediately(0.2f); + } + } + + public class Recipe_ContractNipple : Recipe_BreastSurgery + { + protected override void SurgeryResult(HediffComp_Breast breast) + { + breast.AdjustNippleSizeImmediately(-0.2f); + } + } + + public class Recipe_DarkenNipple : Recipe_BreastSurgery + { + protected override void SurgeryResult(HediffComp_Breast breast) + { + breast.AdjustNippleColorImmediately(0.2f); + } + } + + public class Recipe_LightenNipple : Recipe_BreastSurgery + { + protected override void SurgeryResult(HediffComp_Breast breast) + { + breast.AdjustNippleColorImmediately(-0.2f); + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Reflect.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Reflect.cs new file mode 100644 index 0000000..8e55de8 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Reflect.cs @@ -0,0 +1,52 @@ +using System; +using System.Reflection; + +namespace RJW_Menstruation +{ + public static class Reflector + { + public static object GetMemberValue(this Type type, string name) + { + BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; + FieldInfo fieldInfo = type?.GetField(name, flags); + return fieldInfo?.GetValue(null); + } + + public static object GetMemberValue(this object obj, string name) + { + BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; + FieldInfo fieldInfo = obj?.GetType().GetField(name, flags); + return fieldInfo?.GetValue(obj); + } + + public static object GetPropertyValue(this Type type, string name) + { + BindingFlags flags = BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; + PropertyInfo propertyInfo = type?.GetProperty(name, flags); + return propertyInfo?.GetValue(null); + } + + public static object GetPropertyValue(this object obj, string name) + { + BindingFlags flags = BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; + PropertyInfo propertyInfo = obj?.GetType().GetProperty(name, flags); + return propertyInfo?.GetValue(obj); + } + + public static void SetMemberValue(this Type type, string name, object value) + { + BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; + FieldInfo fieldInfo = type?.GetField(name, flags); + fieldInfo?.SetValue(null, value); + } + + public static void SetMemberValue(this object obj, string name, object value) + { + BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; + FieldInfo fieldInfo = obj?.GetType().GetField(name, flags); + fieldInfo?.SetValue(obj, value); + } + + + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/StatParts.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/StatParts.cs new file mode 100644 index 0000000..6028377 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/StatParts.cs @@ -0,0 +1,90 @@ +using RimWorld; +using System.Collections.Generic; +using System.Linq; +using Verse; + +namespace RJW_Menstruation +{ + public abstract class StatPart_Menstruation_Effects : StatPart + { + public override void TransformValue(StatRequest req, ref float val) + { + if (req.Thing is Pawn pawn && ApplicableComps(pawn).Any()) + val *= GetFactor(pawn); + } + protected abstract IEnumerable ApplicableComps(Pawn pawn); + + protected IEnumerable AllComps(Pawn pawn) + { + return pawn.GetMenstruationComps(); + } + + protected abstract float GetFactor(Pawn pawn); + } + + public abstract class StatPart_Climacteric_Effects : StatPart_Menstruation_Effects + { + public override string ExplanationPart(StatRequest req) + { + if (req.Thing is Pawn pawn && ApplicableComps(pawn).Any()) + { + return $"{Translations.Stage_Climacteric.CapitalizeFirst()}: x{GetFactor(pawn).ToStringPercent()}"; + } + else return null; + } + + protected override IEnumerable ApplicableComps(Pawn pawn) + { + return pawn.GetMenstruationComps().Where(comp => comp.EggHealth < 1f && comp.EggHealth > 0f); + } + } + + public abstract class StatPart_Menopause_Effects : StatPart_Menstruation_Effects + { + public override string ExplanationPart(StatRequest req) + { + if (req.Thing is Pawn pawn && ApplicableComps(pawn).Any()) + { + return $"{Translations.Stage_Menopause.CapitalizeFirst()}: x{GetFactor(pawn).ToStringPercent()}"; + } + else return null; + } + + protected override IEnumerable ApplicableComps(Pawn pawn) + { + return pawn.GetMenstruationComps().Where(comp => comp.EggHealth <= 0f); + } + } + + public class StatPart_Climacteric_SexFrequency : StatPart_Climacteric_Effects + { + protected override float GetFactor(Pawn pawn) + { + return AllComps(pawn).Average(comp => comp.SexFrequencyModifier); + } + } + + public class StatPart_Climacteric_SexSatisfaction : StatPart_Climacteric_Effects + { + protected override float GetFactor(Pawn pawn) + { + return AllComps(pawn).Average(comp => comp.SexSatisfactionModifier); + } + } + + public class StatPart_Menopause_SexFrequency : StatPart_Menopause_Effects + { + protected override float GetFactor(Pawn pawn) + { + return AllComps(pawn).Average(comp => comp.SexFrequencyModifier); + } + } + + public class StatPart_Menopause_SexSatisfaction : StatPart_Menopause_Effects + { + protected override float GetFactor(Pawn pawn) + { + return AllComps(pawn).Average(comp => comp.SexSatisfactionModifier); + } + } +} \ No newline at end of file diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/TextureCache.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/TextureCache.cs new file mode 100644 index 0000000..2e3d6be --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/TextureCache.cs @@ -0,0 +1,102 @@ +using UnityEngine; +using Verse; + +namespace RJW_Menstruation +{ + [StaticConstructorOnStartup] + public static class TextureCache + { + // Milk bars + public static Texture2D MilkTexture + { + get + { + if (milktexturecache == null) milktexturecache = SolidColorMaterials.NewSolidColorTexture(0.992f, 1.0f, 0.960f, 1.0f); + return milktexturecache; + } + } + // Ovulation, sex drive + public static Texture2D OvulatoryTexture + { + get + { + if (ovulatorytexturecache == null) ovulatorytexturecache = SolidColorMaterials.NewSolidColorTexture(0.686f, 0.062f, 0.698f, 1.0f); + return ovulatorytexturecache; + } + } + // Bleeding, vulnerability + public static Texture2D BleedingTexture + { + get + { + if (bleedingtexturecache == null) bleedingtexturecache = SolidColorMaterials.NewSolidColorTexture(0.415f, 0.0f, 0.003f, 1.0f); + return bleedingtexturecache; + } + } + // Pregnant, default, formerly sex ability + public static Texture2D PregnantTexture + { + get + { + if (pregnanttexturecache == null) pregnanttexturecache = SolidColorMaterials.NewSolidColorTexture(0.082f, 0.453f, 0.6f, 1.0f); + return pregnanttexturecache; + } + } + // Recover, count of egg births + public static Texture2D RecoverTexture + { + get + { + if (recovertexturecache == null) recovertexturecache = SolidColorMaterials.NewSolidColorTexture(0.6f, 0.83f, 0.35f, 1.0f); + return recovertexturecache; + } + } + // Follicular, count of humanlike births + public static Texture2D FollicularTexture + { + get + { + if (folliculartexturecache == null) folliculartexturecache = SolidColorMaterials.NewSolidColorTexture(0.878f, 0.674f, 0.411f, 1.0f); + return folliculartexturecache; + } + } + // Count of animal births + public static Texture2D AnimalTexture + { + get + { + if (animaltexturecache == null) animaltexturecache = SolidColorMaterials.NewSolidColorTexture(0.411f, 0.521f, 0.878f, 1.0f); + return animaltexturecache; + } + } + // Luteal, fertility + public static Texture2D LutealTexture + { + get + { + if (lutealtexturecache == null) lutealtexturecache = SolidColorMaterials.NewSolidColorTexture(0.843f, 0.474f, 0.6f, 1.0f); + return lutealtexturecache; + } + } + // Unused, formerly count of whored + public static Texture2D WhoredTexture + { + get + { + if (whoredtexturecache == null) whoredtexturecache = SolidColorMaterials.NewSolidColorTexture(0.7f, 0.7f, 0.0f, 1.0f); + return whoredtexturecache; + } + } + + public static readonly Texture2D FertChanceTex = SolidColorMaterials.NewSolidColorTexture(new Color(1f, 1f, 1f, 0.4f)); + private static Texture2D milktexturecache = SolidColorMaterials.NewSolidColorTexture(0.992f, 1.0f, 0.960f, 1.0f); + private static Texture2D ovulatorytexturecache = SolidColorMaterials.NewSolidColorTexture(0.686f, 0.062f, 0.698f, 1.0f); + private static Texture2D bleedingtexturecache = SolidColorMaterials.NewSolidColorTexture(0.415f, 0.0f, 0.003f, 1.0f); + private static Texture2D pregnanttexturecache = SolidColorMaterials.NewSolidColorTexture(0.082f, 0.453f, 0.6f, 1.0f); + private static Texture2D recovertexturecache = SolidColorMaterials.NewSolidColorTexture(0.6f, 0.83f, 0.35f, 1.0f); + private static Texture2D folliculartexturecache = SolidColorMaterials.NewSolidColorTexture(0.878f, 0.674f, 0.411f, 1.0f); + private static Texture2D animaltexturecache = SolidColorMaterials.NewSolidColorTexture(0.411f, 0.521f, 0.878f, 1.0f); + private static Texture2D lutealtexturecache = SolidColorMaterials.NewSolidColorTexture(0.843f, 0.474f, 0.6f, 1.0f); + private static Texture2D whoredtexturecache = SolidColorMaterials.NewSolidColorTexture(0.7f, 0.7f, 0.0f, 1.0f); + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Things.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Things.cs new file mode 100644 index 0000000..c95454a --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Things.cs @@ -0,0 +1,319 @@ +using RimWorld; +using rjw; +using System.Collections.Generic; +using System.Text; +using System.Xml; +using UnityEngine; +using Verse; + +namespace RJW_Menstruation +{ + public class PawnDNAModExtension : DefModExtension + { + public string fetusTexPath; + public ColorInt cumColor; + public Color CumColor => cumColor.ToColor; + public float cumThickness = 0f; + public List hybridExtension; + public List ingestionOutcomeDoers; + + public HybridExtension GetHybridExtension(string race) + { + if (hybridExtension.NullOrEmpty()) return null; + else return hybridExtension.Find(x => x.thingDef.defName.Equals(race)); + } + + public PawnKindDef GetHybridWith(string race) + { + return GetHybridExtension(race)?.ChooseOne() ?? null; + } + } + + public class HybridExtension + { + + public Dictionary hybridInfo = new Dictionary(); + public ThingDef thingDef; + + public HybridExtension() { } + + + public PawnKindDef ChooseOne() + { + + if (hybridInfo.EnumerableNullOrEmpty()) return null; + PawnKindDef res = null; + do + { + string key = hybridInfo.RandomElementByWeight(x => x.Value).Key; + res = DefDatabase.GetNamedSilentFail(key); + if (res == null) res = DefDatabase.GetNamedSilentFail(key)?.race?.AnyPawnKind; + + if (res == null) + { + Log.Warning($"Could not find pawnKind or race {key}, removing hybrid definition"); + hybridInfo.Remove(key); + } + } while (res == null && !hybridInfo.EnumerableNullOrEmpty()); + + return res; + } + + + public void LoadDataFromXmlCustom(XmlNode xmlRoot) + { + DirectXmlCrossRefLoader.RegisterObjectWantsCrossRef(this, "thingDef", xmlRoot.Name); + XmlNodeList childNodes = xmlRoot.ChildNodes; + + if (childNodes.Count >= 1) foreach (XmlNode node in childNodes) + { +#if DEBUG + Log.Message(xmlRoot.Name + "HybridInfo: " + node.Name + " " + node.InnerText); +#endif + hybridInfo.Add(node.Name, ParseHelper.FromString(node.InnerText)); + } + } + } + + public class HybridInformations : IExposable + { + public List hybridExtension = new List(); + + private ThingDef thingDef; + private string thingDefName; + + public string DefName + { + get + { + return thingDefName; + } + } + public bool IsNull + { + get + { + return (thingDefName?.Length ?? 0) < 1; + } + } + public ThingDef GetDef + { + get + { + if (thingDef != null) return thingDef; + else + { + thingDef = DefDatabase.GetNamedSilentFail(thingDefName); + return thingDef; + } + } + } + + public HybridInformations() { } + + public HybridInformations(ThingDef def) + { + thingDef = def; + thingDefName = def.defName; + } + + public HybridExtensionExposable GetHybridExtension(string race) + { + if (hybridExtension.NullOrEmpty()) return null; + else + { + return hybridExtension.Find(x => x.GetDef?.defName?.Equals(race) ?? false); + } + } + + public PawnKindDef GetHybridWith(string race) + { + return GetHybridExtension(race)?.ChooseOne() ?? null; + } + + public void ExposeData() + { + Scribe_Values.Look(ref thingDefName, "thingDefName"); + Scribe_Collections.Look(ref hybridExtension, "hybridExtension", LookMode.Deep, new object[0]); + } + } + + public class HybridExtensionExposable : HybridExtension, IExposable + { + private string thingDefName; + + public string DefName + { + get + { + return thingDefName; + } + } + public bool IsNull + { + get + { + return (thingDefName?.Length ?? 0) < 1; + } + } + public ThingDef GetDef + { + get + { + if (thingDef != null) return thingDef; + else + { + thingDef = DefDatabase.GetNamedSilentFail(thingDefName); + return thingDef; + } + } + } + + public HybridExtensionExposable() { } + + public HybridExtensionExposable(ThingDef def) + { + thingDef = def; + thingDefName = def.defName; + hybridInfo = new Dictionary(); + } + + public void ExposeData() + { + Scribe_Values.Look(ref thingDefName, "thingDefName"); + Scribe_Collections.Look(ref hybridInfo, "hybridInfo", LookMode.Value, LookMode.Value); + + } + } + public class AbsorberModExtension : DefModExtension + { + public float passiveAbsorptionPerHour = 0.1f; + public bool leakAfterDirty = false; + public bool effectsAfterDirty = false; + public ThingDef dirtyDef = null; + public int minHourstoDirtyEffect = 0; + } + + public class Absorber : Apparel + { + + public float absorbedfluids = 0; + public bool dirty = false; + public int wearTicks = 0; + public virtual float PassiveAbsorptionPerHour => def.GetModExtension().passiveAbsorptionPerHour; + public virtual bool LeakAfterDirty => def.GetModExtension().leakAfterDirty; + public virtual bool EffectAfterDirty => def.GetModExtension().effectsAfterDirty; + public virtual ThingDef DirtyDef => def.GetModExtension().dirtyDef; + public virtual int MinHrstoDirtyEffect => def.GetModExtension().minHourstoDirtyEffect; + + public Color fluidColor = Color.white; + + public virtual void DirtyEffect(int tickInterval) { } + + public virtual void WearEffect(int tickInterval) + { + absorbedfluids += PassiveAbsorptionPerHour * tickInterval / GenDate.TicksPerHour; + CheckDirty(); + if (dirty) wearTicks += tickInterval; + } + + public void CheckDirty() + { + if (absorbedfluids > this.GetStatValue(VariousDefOf.MaxAbsorbable) && !(Wearer?.apparel?.IsLocked(this) ?? false) && DirtyDef != def && DirtyDef != null) + { + bool oldHasStats = !def.equippedStatOffsets.NullOrEmpty(); + bool newHasStats = !DirtyDef.equippedStatOffsets.NullOrEmpty(); + def = DirtyDef; + dirty = true; + Wearer.outfits?.forcedHandler?.SetForced(this, false); + if (oldHasStats || newHasStats) + Wearer.health.capacities.Notify_CapacityLevelsDirty(); + Wearer.apparel.Notify_ApparelChanged(); + } + } + + public override Color DrawColorTwo => fluidColor; + + public override void ExposeData() + { + base.ExposeData(); + if(Scribe.mode == LoadSaveMode.LoadingVars) + { + int wearhours = -1; + Scribe_Values.Look(ref wearhours, "wearhours", wearhours, true); + if (wearhours >= 0) wearTicks = wearhours * GenDate.TicksPerHour; + } + Scribe_Values.Look(ref absorbedfluids, "absorbedfluids", 0); + Scribe_Values.Look(ref dirty, "dirty", false); + Scribe_Values.Look(ref wearTicks, "wearTicks", 0); + Scribe_Values.Look(ref fluidColor, "fluidColor", Color.white); + } + + public override string DescriptionDetailed + { + get + { + StringBuilder text = new StringBuilder(base.DescriptionDetailed); + text.AppendLine(); + text.Append(Translations.Description_Absorbed); + text.Append(": "); + text.Append(absorbedfluids.ToStringDecimalIfSmall()); + text.Append("/"); + text.Append(this.GetStatValue(VariousDefOf.MaxAbsorbable).ToStringDecimalIfSmall()); + text.Append("ml"); + + return text.ToString(); + } + } + } + + public class Absorber_Tampon : Absorber + { + public override void DirtyEffect(int tickInterval) + { + + if (wearTicks > MinHrstoDirtyEffect * GenDate.TicksPerHour && Rand.MTBEventOccurs(100.0f, GenDate.TicksPerHour, tickInterval) && !(Wearer.apparel?.IsLocked(this) ?? false)) + { + Wearer.health.AddHediff(HediffDefOf.WoundInfection, Genital_Helper.get_genitalsBPR(Wearer)); + } + } + + } + + + public class Filth_Colored : Filth + { + + private Color color = Color.white; + + public override void ExposeData() + { + base.ExposeData(); + Scribe_Values.Look(ref color, "color", Color.white); + } + + public override Color DrawColor + { + get + { + if (color != Color.white) + { + return color; + } + if (Stuff != null) + { + return def.GetColorForStuff(Stuff); + } + if (def.graphicData != null) + { + return def.graphicData.color; + } + return color; + } + set + { + color = value; + } + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Translations.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Translations.cs new file mode 100644 index 0000000..6c511cc --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Translations.cs @@ -0,0 +1,164 @@ +using Verse; + +namespace RJW_Menstruation +{ + public static class Translations + { + public static readonly string Mod_Title = "Mod_Title".Translate(); + public static readonly string Info_noCum = "Info_noCum".Translate(); + public static readonly string Menstrual_Blood = "Menstrual_Blood".Translate(); + public static readonly string Stage_Follicular = "Stage_Follicular".Translate(); + public static readonly string Stage_Ovulatory = "Stage_Ovulatory".Translate(); + public static readonly string Stage_Luteal = "Stage_Luteal".Translate(); + public static readonly string Stage_Bleeding = "Stage_Bleeding".Translate(); + public static readonly string Stage_Pregnant = "Stage_Pregnant".Translate(); + public static readonly string Stage_Recover = "Stage_Recover".Translate(); + public static readonly string Stage_None = "Stage_None".Translate(); + public static readonly string Stage_Climacteric = "Stage_Climacteric".Translate(); + public static readonly string Stage_Menopause = "Stage_Menopause".Translate(); + public static readonly string Stage_Anestrus = "Stage_Anestrus".Translate(); + public static readonly string Stage_Follicular_Desc = "Stage_Follicular_Desc".Translate(); + public static readonly string Stage_Follicular_Induced_Desc = "Stage_Follicular_Induced_Desc".Translate(); + public static readonly string Stage_Ovulatory_Desc = "Stage_Ovulatory_Desc".Translate(); + public static readonly string Stage_Luteal_Desc = "Stage_Luteal_Desc".Translate(); + public static readonly string Stage_Bleeding_Desc = "Stage_Bleeding_Desc".Translate(); + public static readonly string Stage_Pregnant_Desc = "Stage_Pregnant_Desc".Translate(); + public static readonly string Stage_Recover_Desc = "Stage_Recover_Desc".Translate(); + public static readonly string Stage_None_Desc = "Stage_None_Desc".Translate(); + public static readonly string Stage_Menopause_Desc = "Stage_Menopause_Desc".Translate(); + public static readonly string Stage_Climacteric_Desc = "Stage_Climacteric_Desc".Translate(); + public static readonly string Stage_Anestrus_Desc = "Stage_Anestrus_Desc".Translate(); + public static readonly string Button_HealthTab = "Button_HealthTab".Translate(); + public static readonly string Button_MilkTooltip = "Button_MilkTooltip".Translate(); + public static readonly string Dialog_DoCleanWomb_Tooltip = "Dialog_DoCleanWomb_Tooltip".Translate(); + public static readonly string Dialog_DontCleanWomb_Tooltip = "Dialog_DontCleanWomb_Tooltip".Translate(); + public static readonly string Dialog_FatherUnknown = "Dialog_FatherUnknown".Translate(); + + public static readonly string Dialog_WombInfo01 = "Dialog_WombInfo01".Translate(); + public static readonly string Dialog_WombInfo02 = "Dialog_WombInfo02".Translate(); + public static readonly string Dialog_WombInfo03 = "Dialog_WombInfo03".Translate(); + public static readonly string Dialog_WombInfo04 = "Dialog_WombInfo04".Translate(); + public static readonly string Dialog_WombInfo05 = "Dialog_WombInfo05".Translate(); + public static readonly string Dialog_WombInfo06 = "Dialog_WombInfo06".Translate(); + public static readonly string Dialog_WombInfo07 = "Dialog_WombInfo07".Translate(); + public static readonly string Dialog_WombInfo08 = "Dialog_WombInfo08".Translate(); + public static readonly string Dialog_WombInfo09 = "Dialog_WombInfo09".Translate(); + public static readonly string Dialog_WombInfo10 = "Dialog_WombInfo10".Translate(); + public static readonly string Description_Absorbed = "Description_Absorbed".Translate(); + + + public static readonly string Option1_Label_1 = "Option1_Label_1".Translate(); + public static readonly string Option1_Label_2 = "Option1_Label_2".Translate(); + public static readonly string Option2_Label = "Option2_Label".Translate(); + public static readonly string Option2_Desc = "Option2_Desc".Translate(); + public static readonly string Option3_Label = "Option3_Label".Translate(); + public static readonly string Option3_Desc = "Option3_Desc".Translate(); + public static readonly string Option4_Label = "Option4_Label".Translate(); + public static readonly string Option4_Desc = "Option4_Desc".Translate(); + public static readonly string Option5_Label = "Option5_Label".Translate(); + public static readonly string Option5_Desc = "Option5_Desc".Translate(); + public static readonly string Option6_Label = "Option6_Label".Translate(); + public static readonly string Option6_Desc = "Option6_Desc".Translate(); + public static readonly string Option7_Label = "Option7_Label".Translate(); + public static readonly string Option7_Desc = "Option7_Desc".Translate(); + public static readonly string Option_ColonistUpdateInterval_Label = "Option_ColonistUpdateInterval_Label".Translate(); + public static readonly string Option_ColonistUpdateInterval_Desc = "Option_ColonistUpdateInterval_Desc".Translate(); + public static readonly string Option_NonColonistUpdateInterval_Label = "Option_NonColonistUpdateInterval_Label".Translate(); + public static readonly string Option_NonColonistUpdateInterval_Desc = "Option_NonColonistUpdateInterval_Desc".Translate(); + public static readonly string Option_AnimalUpdateInterval_Label = "Option_AnimalUpdateInterval_Label".Translate(); + public static readonly string Option_AnimalUpdateInterval_Desc = "Option_AnimalUpdateInterval_Desc".Translate(); + public static readonly string Option8_Label = "Option8_Label".Translate(); + public static readonly string Option8_Desc = "Option8_Desc".Translate(); + public static readonly string Option9_Label = "Option9_Label".Translate(); + public static readonly string Option9_Desc = "Option9_Desc".Translate(); + public static readonly string Option10_Label = "Option10_Label".Translate(); + public static readonly string Option10_Desc = "Option10_Desc".Translate(); + public static readonly string Option11_Label = "Option11_Label".Translate(); + public static readonly string Option11_Desc_1 = "Option11_Desc_1".Translate(); + public static readonly string Option11_Desc_2 = "Option11_Desc_2".Translate(); + public static readonly string Option11_Desc_3 = "Option11_Desc_3".Translate(); + public static readonly string Option11_Desc_4 = "Option11_Desc_4".Translate(); + public static readonly string Option12_Label = "Option12_Label".Translate(); + public static readonly string Option12_Desc = "Option12_Desc".Translate(); + public static readonly string Option_EnablePheromones_Label = "Option_EnablePheromones_Label".Translate(); + public static readonly string Option_EnablePheromones_Desc = "Option_EnablePheromones_Desc".Translate(); + public static readonly string Option_AnimalPheromoneEffect_Label = "Option_AnimalPheromoneEffect_Label".Translate(); + public static readonly string Option_AnimalPheromoneEffect_Desc = "Option_AnimalPheromoneEffect_Desc".Translate(); + public static readonly string Option13_Label = "Option13_Label".Translate(); + public static readonly string Option13_Desc = "Option13_Desc".Translate(); + public static readonly string Option14_Label = "Option14_Label".Translate(); + public static readonly string Option14_Desc = "Option14_Desc".Translate(); + public static readonly string Option15_Label = "Option15_Label".Translate(); + public static readonly string Option15_Desc = "Option15_Desc".Translate(); + public static readonly string Option16_Label = "Option16_Label".Translate(); + public static readonly string Option16_Desc = "Option16_Desc".Translate(); + public static readonly string Option17_Label = "Option17_Label".Translate(); + public static readonly string Option17_Desc = "Option17_Desc".Translate(); + public static readonly string Option18_Label = "Option18_Label".Translate(); + public static readonly string Option18_Desc = "Option18_Desc".Translate(); + public static readonly string Option19_Label_1 = "Option19_Label_1".Translate(); + public static readonly string Option19_Label_2 = "Option19_Label_2".Translate(); + public static readonly string Option19_Desc = "Option19_Desc".Translate(); + public static readonly string Option20_Label_1 = "Option20_Label_1".Translate(); + public static readonly string Option20_Label_2 = "Option20_Label_2".Translate(); + public static readonly string Option20_Label_3 = "Option20_Label_3".Translate(); + public static readonly string Option20_Label_4 = "Option20_Label_4".Translate(); + public static readonly string Option20_Label_5 = "Option20_Label_5".Translate(); + public static readonly string Option21_Label = "Option21_Label".Translate(); + public static readonly string Option21_Desc = "Option21_Desc".Translate(); + public static readonly string Option22_Label = "Option22_Label".Translate(); + public static readonly string Option22_Desc = "Option22_Desc".Translate(); + public static readonly string Option23_Label = "Option23_Label".Translate(); + public static readonly string Option23_Label_1 = "Option23_Label_1".Translate(); + public static readonly string Option23_Label_2 = "Option23_Label_2".Translate(); + public static readonly string Option28_Label = "Option28_Label".Translate(); + public static readonly string Option28_Tooltip = "Option28_Tooltip".Translate(); + public static readonly string Option29_Label = "Option29_Label".Translate(); + public static readonly string Option29_Desc = "Option29_Desc".Translate(); + public static readonly string Option30_Label = "Option30_Label".Translate(); + public static readonly string Option30_Desc = "Option30_Desc".Translate(); + public static readonly string Option31_Label = "Option31_Label".Translate(); + public static readonly string Option31_Desc = "Option31_Desc".Translate(); + public static readonly string Option32_Label = "Option32_Label".Translate(); + public static readonly string Option32_Desc = "Option32_Desc".Translate(); + public static readonly string Option_MaxBreastIncrementFactor_Label = "Option_MaxBreastIncrementFactor_Label".Translate(); + public static readonly string Option_MaxBreastIncrementFactor_Desc = "Option_MaxBreastIncrementFactor_Desc".Translate(); + public static readonly string Option_MaxNippleIncrementFactor_Label = "Option_MaxNippleIncrementFactor_Label".Translate(); + public static readonly string Option_MaxNippleIncrementFactor_Desc = "Option_MaxNippleIncrementFactor_Desc".Translate(); + public static readonly string Option_PermanentNippleChange_Label = "Option_PermanentNippleChange_Label".Translate(); + public static readonly string Option_PermanentNippleChange_Desc = "Option_PermanentNippleChange_Desc".Translate(); + public static readonly string Option_EnableGatherCumGizmo_Label = "Option_EnableGatherCumGizmo_Label".Translate(); + public static readonly string Option_EstrusOverride_Label = "Option_EstrusOverride_Label".Translate(); + public static readonly string Option_EstrusOverride_Desc = "Option_EstrusOverride_Desc".Translate(); + public static readonly string Option_EstrusFuckability_Label = "Option_EstrusFuckability_Label".Translate(); + public static readonly string Option_EstrusAttractability_Label = "Option_EstrusAttractability_Label".Translate(); + public static readonly string Option_EstrusRelationship_Label = "Option_EstrusRelationship_Label".Translate(); + public static readonly string Option_PregnancyFromBaseRJW_Label = "Option_PregnancyFromBaseRJW_Label".Translate(); + public static readonly string Option_PregnancyFromMultiplePregnancy_Label = "Option_PregnancyFromMultiplePregnancy_Label".Translate(); + public static readonly string Option_PregnancyFromBiotech_Label = "Option_PregnancyFromBiotech_Label".Translate(); + public static readonly string Option_EnableBiotechTwins_Label = "Option_EnableBiotechTwins_Label".Translate(); + public static readonly string Option_EnableBiotechTwins_Desc = "Option_EnableBiotechTwins_Desc".Translate(); + public static readonly string Option_EnableDraftedIcon_Label = "Option_EnableDraftedIcon_Label".Translate(); + public static readonly string Option_EnableDraftedIcon_Desc = "Option_EnableDraftedIcon_Desc".Translate(); + + public static readonly string Button_ResetToDefault = "Button_ResetToDefault".Translate(); + + public static readonly string EstimatedCumLifespan = "EstimatedCumLifespan".Translate(); + public static readonly string EstimatedEggLifespan = "EstimatedEggLifespan".Translate(); + public static string OvulationChanceLabel(string value) => "OvulationChanceLabel".Translate(value); + public static readonly string OvulationChanceDesc = "OvulationChanceDesc".Translate(); + public static string FertilityDesc(string value) => "FertilityDesc".Translate(value); + + public static readonly string Gizmo_GatherCum = "Gizmo_GatherCum".Translate(); + public static readonly string FloatMenu_CleanSelf = "FloatMenu_CleanSelf".Translate(); + + public static readonly string CannotNoEggs = "CannotNoEggs".Translate(); + + public static readonly string CannotNoWomb = "CannotNoWomb".Translate(); + public static string EggRestorationCompleted(NamedArgument name) { return "EggRestorationCompleted".Translate(name); } + + public static readonly string CustomHybrid_List_Title = "CustomHybrid_List_Title".Translate(); + static public string CustomHybrid_Title(string label) { return TranslatorFormattedStringExtensions.Translate("CustomHybrid_Title", label); } + static public string CustomHybrid_Tooltip(string label, string breedee, string baby, string chance) { return TranslatorFormattedStringExtensions.Translate("CustomHybrid_Tooltip", label, breedee, baby, chance); } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_HybridCustom.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_HybridCustom.cs new file mode 100644 index 0000000..e61af20 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_HybridCustom.cs @@ -0,0 +1,474 @@ +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Verse; +using Verse.Sound; + +namespace RJW_Menstruation +{ + public class Dialog_HybridCustom : Window + { + private static Vector2 scroll; + private const float windowMargin = 20f; + private static readonly List raceList = new List(); + private static readonly List removeList = new List(); + + public Dialog_HybridCustom() + { + BuildRaceList(); + } + + public void BuildRaceList() + { + raceList.Clear(); + if (!VariousDefOf.AllRaces.NullOrEmpty()) + foreach (ThingDef def in VariousDefOf.AllRaces) + { + if (def.race == null || Configurations.IsOverrideExist(def)) continue; + raceList.Add(new FloatMenuOption(def.label, delegate { AddHybridOverride(def); }, def.uiIcon, Color.white)); + } + raceList.SortBy(x => x.Label); + } + + public void AddHybridOverride(ThingDef def) + { + FloatMenuOption option = raceList.FirstOrDefault(x => x.Label.Equals(def?.label)); + if (option == null) return; + raceList.Remove(option); + if (Configurations.HybridOverride.NullOrEmpty()) + { + Configurations.HybridOverride = new List(); + } + Configurations.HybridOverride.Add(new HybridInformations(def)); + Configurations.HybridOverride.SortBy(x => x.GetDef?.label ?? "Undefined"); + + } + + public override Vector2 InitialSize + { + get + { + float width = 480f; + float height = 640f; + return new Vector2(width, height); + } + } + + + public override void DoWindowContents(Rect inRect) + { + soundClose = SoundDefOf.CommsWindow_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); + + DoMainContents(mainRect); + + if (Widgets.CloseButtonFor(closeRect)) + { + Close(); + } + } + + public override void PostClose() + { + base.PostClose(); + if (!removeList.NullOrEmpty()) + { + foreach (HybridInformations extension in removeList) + { + Configurations.HybridOverride.Remove(extension); + } + raceList.SortBy(x => x.Label); + } + removeList.Clear(); + } + + protected void DoMainContents(Rect inRect) + { + Rect buttonRect = new Rect(inRect.xMax - 120, 0, 100, 30); + Rect titleRect = new Rect(inRect.x, 0, 200, 30); + Widgets.Label(titleRect, Translations.CustomHybrid_List_Title); + Widgets.DrawLineHorizontal(titleRect.x, titleRect.yMax + 12f, inRect.width); + if (Widgets.ButtonText(buttonRect, "Add")) + { + if (!raceList.NullOrEmpty()) Find.WindowStack.Add(new FloatMenu(raceList)); + } + if (!removeList.NullOrEmpty()) + { + buttonRect.x -= 100; + if (Widgets.ButtonText(buttonRect, "Undo")) + { + HybridInformations element = removeList.Last(); + Configurations.HybridOverride.Add(element); + Configurations.HybridOverride.SortBy(x => x.GetDef?.label ?? "Undefined"); + removeList.Remove(element); + } + + foreach (HybridInformations extension in removeList) + { + Configurations.HybridOverride.Remove(extension); + } + raceList.SortBy(x => x.Label); + } + + + + Rect outRect = new Rect(inRect.x, inRect.y + 30f, inRect.width, inRect.height - 30f); + Rect mainRect = new Rect(inRect.x, inRect.y + 30f, inRect.width - 30f, Math.Max(24f * Configurations.HybridOverride?.Count() ?? 1, 10f)); + Listing_Standard listmain = new Listing_Standard(); + + Widgets.BeginScrollView(outRect, ref scroll, mainRect); + listmain.Begin(mainRect); + if (!Configurations.HybridOverride.NullOrEmpty()) + foreach (HybridInformations extension in Configurations.HybridOverride) + { + if (extension.GetDef != null) DoRow(listmain.GetRect(24f), extension); + } + Widgets.EndScrollView(); + listmain.End(); + + + } + + protected void DoRow(Rect rect, HybridInformations extension) + { + Rect buttonRect = new Rect(rect.xMax - 90f, rect.y, 80f, rect.height); + Widgets.Label(rect, extension.GetDef?.label ?? "Undefined"); + if (Widgets.ButtonText(buttonRect, "Delete")) + { + removeList.Add(extension); + //raceList.Add(new FloatMenuOption(extension.GetDef.label, delegate { AddHybridOverride(extension.GetDef); })); + } + buttonRect.x -= 80f; + if (Widgets.ButtonText(buttonRect, "Edit")) + { + Dialog_EditHybrid.OpenWindow(extension); + } + + + Widgets.DrawHighlightIfMouseover(rect); + } + + + public static void ToggleWindow() + { + Dialog_HybridCustom window = (Dialog_HybridCustom)Find.WindowStack.Windows.FirstOrDefault(x => x.GetType().Equals(typeof(Dialog_HybridCustom))); + if (window != null) + { + Find.WindowStack.TryRemove(typeof(Dialog_HybridCustom), true); + } + else + { + SoundDefOf.CommsWindow_Open.PlayOneShotOnCamera(); + Find.WindowStack.Add(new Dialog_HybridCustom()); + } + + + } + + } + + public class Dialog_EditHybrid : Window + { + private const float windowMargin = 20f; + private const float rowH = 24f; + private HybridInformations info; + private Vector2 scroll; + protected List raceList = new List(); + protected List removeList = new List(); + protected float totalWeight = 0; + + public Dialog_EditHybrid(HybridInformations info) + { + this.info = info; + BuildRaceList(); + } + + + + public override Vector2 InitialSize + { + get + { + float width = 840f; + float height = 640f; + return new Vector2(width, height); + } + } + + + public override void DoWindowContents(Rect inRect) + { + soundClose = SoundDefOf.CommsWindow_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); + + DoMainContents(mainRect); + + if (Widgets.CloseButtonFor(closeRect)) + { + Close(); + } + } + + public static void OpenWindow(HybridInformations info) + { + Dialog_EditHybrid window = (Dialog_EditHybrid)Find.WindowStack.Windows.FirstOrDefault(x => x.GetType().Equals(typeof(Dialog_EditHybrid))); + if (window != null) + { + if (window.info != info) + { + SoundDefOf.TabOpen.PlayOneShotOnCamera(); + window.ChangeExtension(info); + } + } + else + { + SoundDefOf.TabClose.PlayOneShotOnCamera(); + Find.WindowStack.Add(new Dialog_EditHybrid(info)); + } + + + } + + protected void ChangeExtension(HybridInformations info) + { + this.info = info; + BuildRaceList(); + } + + protected void BuildRaceList() + { + raceList.Clear(); + if (VariousDefOf.AllRaces.NullOrEmpty()) return; + + foreach (ThingDef def in VariousDefOf.AllRaces) + { + if (def.race != null) + { + if (info.hybridExtension.Exists(x => x.DefName == def.defName)) continue; + else + { + raceList.Add(new FloatMenuOption(def.label, delegate { AddHybridInfo(def); }, Widgets.GetIconFor(def), Color.white)); + } + } + } + raceList.SortBy(x => x.Label); + } + + protected void AddHybridInfo(ThingDef def) + { + FloatMenuOption option = raceList.FirstOrDefault(x => x.Label == def.label); + if (option != null) + { + raceList.Remove(option); + } + info.hybridExtension.Add(new HybridExtensionExposable(def)); + } + + protected void DoMainContents(Rect inRect) + { + Rect labelRect = new Rect(inRect.xMin, inRect.yMin, 300, 24); + Rect buttonRect = new Rect(inRect.xMax - 120, 0, 100, 30); + + Widgets.Label(labelRect, Translations.CustomHybrid_Title(info.GetDef?.label ?? "Undefined")); + Widgets.DrawLineHorizontal(inRect.x, labelRect.yMax, inRect.width); + if (Widgets.ButtonText(buttonRect, "Add")) + { + if (!raceList.NullOrEmpty()) Find.WindowStack.Add(new FloatMenu(raceList)); + } + if (!removeList.EnumerableNullOrEmpty()) + { + buttonRect.x -= 100; + if (Widgets.ButtonText(buttonRect, "Undo")) + { + HybridExtensionExposable element = removeList.Last(); + info.hybridExtension.Add(element); + removeList.Remove(element); + } + + foreach (HybridExtensionExposable element in removeList) + { + info.hybridExtension.Remove(element); + } + } + + + float additionalHeight = 0f; + if (!info.hybridExtension.NullOrEmpty()) foreach (HybridExtensionExposable e in info.hybridExtension) + { + additionalHeight += (e.hybridInfo?.Count() ?? 1) * rowH; + } + + + Rect outRect = new Rect(inRect.x, inRect.y + 30f, inRect.width, inRect.height - 30f); + Rect mainRect = new Rect(inRect.x, inRect.y + 30f, inRect.width - 30f, rowH * (info.hybridExtension?.Count() ?? 1) + additionalHeight); + Listing_Standard listmain = new Listing_Standard(); + + Widgets.BeginScrollView(outRect, ref scroll, mainRect); + listmain.Begin(mainRect); + + if (!info.hybridExtension.NullOrEmpty()) + { + foreach (HybridExtensionExposable extension in info.hybridExtension) + { + DoRow(listmain.GetRect(rowH + rowH * (extension.hybridInfo?.Count() ?? 1)), extension); + } + + } + + + + Widgets.EndScrollView(); + listmain.End(); + } + + protected void DoRow(Rect rect, HybridExtensionExposable extension) + { + Rect mainRect = new Rect(rect.x, rect.y, rect.width, rowH); + Rect subRect = new Rect(rect.x, rect.y + rowH, rect.width, rect.height - rowH); + Rect buttonRect = new Rect(rect.xMax - 90f, rect.y, 80f, rowH); + Widgets.Label(mainRect, extension.GetDef?.label ?? "Undefined"); + + if (Widgets.ButtonText(buttonRect, "Delete")) + { + removeList.Add(extension); + } + buttonRect.x -= 80f; + if (Widgets.ButtonText(buttonRect, "Add")) + { + List list = new List(); + if (!VariousDefOf.AllRaces.NullOrEmpty()) foreach (ThingDef def in VariousDefOf.AllRaces) + { + if (def.race != null) + { + if (extension.hybridInfo.ContainsKey(def.defName)) continue; + else + { + list.Add(new FloatMenuOption(def.label, delegate { extension.hybridInfo.Add(def.defName, 1.0f); }, Widgets.GetIconFor(def), Color.white)); + } + } + } + if (!list.NullOrEmpty()) + { + list.SortBy(x => x.Label); + Find.WindowStack.Add(new FloatMenu(list)); + } + + } + buttonRect.x -= 80f; + + Listing_Standard sublist = new Listing_Standard(); + sublist.Begin(subRect); + + List removeelements = new List(); + if (!extension.hybridInfo.EnumerableNullOrEmpty()) + { + totalWeight = 0; + foreach (KeyValuePair element in extension.hybridInfo) + { + totalWeight += element.Value; + } + + List keys = new List(extension.hybridInfo.Keys); + foreach (string key in keys) + { + DoSubRow(sublist.GetRect(rowH), key, extension, removeelements); + } + } + foreach (string key in removeelements) + extension.hybridInfo.Remove(key); + + sublist.End(); + Widgets.DrawHighlightIfMouseover(rect); + + + } + + protected void DoSubRow(Rect rect, string key, HybridExtensionExposable extension, List removeelements) + { + bool isPawnKind = false; + int value = (int)extension.hybridInfo.TryGetValue(key); + string valuestr = value.ToString(); + string label = null; + label = DefDatabase.GetNamedSilentFail(key)?.label; + if (label == null) + { + label = DefDatabase.GetNamedSilentFail(key)?.label ?? "Undefined"; + isPawnKind = true; + } + Rect buttonRect = new Rect(rect.xMax - 90f, rect.y, 80f, rect.height); + if (Widgets.ButtonText(buttonRect, "Delete")) + { + removeelements.Add(key); + } + buttonRect.x -= 80f; + if (!isPawnKind) + { + if (Widgets.ButtonText(buttonRect, "PawnKind")) + { + List list = new List(); + if (!VariousDefOf.AllKinds.NullOrEmpty()) foreach (PawnKindDef def in VariousDefOf.AllKinds) + { + if (def.race.defName == key) + { + if (extension.hybridInfo.ContainsKey(def.defName)) continue; + else + { + list.Add(new FloatMenuOption(def.label, delegate { extension.hybridInfo.Add(def.defName, 1.0f); }, Widgets.GetIconFor(def.race), Color.white)); + } + } + } + if (!list.NullOrEmpty()) Find.WindowStack.Add(new FloatMenu(list)); + else SoundDefOf.ClickReject.PlayOneShotOnCamera(); + } + buttonRect.x -= 80f; + } + else + { + Widgets.Label(buttonRect, " PawnKind"); + buttonRect.x -= 80f; + } + label += ": " + key; + Widgets.Label(rect, " - " + label); + Widgets.TextFieldNumeric(buttonRect, ref value, ref valuestr, 0, 9999999); + extension.hybridInfo.SetOrAdd(key, value); + buttonRect.x -= 80f; + Widgets.Label(buttonRect, String.Format("{0,0:P2}", value / totalWeight)); + Widgets.DrawHighlightIfMouseover(rect); + TooltipHandler.TipRegion(rect, Translations.CustomHybrid_Tooltip(info.GetDef?.label ?? "Undefined", extension.GetDef?.label ?? "Undefined", label, String.Format("{0,0:0.########%}", value / totalWeight))); + } + + + } + + +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs new file mode 100644 index 0000000..2820b53 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/UI/Dialog_WombStatus.cs @@ -0,0 +1,479 @@ +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 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.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.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.Get("Womb/Empty", true); + HediffComp_PregeneratedBabies babiescomp = p.TryGetComp(); + 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.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); + } + + + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/UI/Gizmo_Womb.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/UI/Gizmo_Womb.cs new file mode 100644 index 0000000..aaaa96f --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/UI/Gizmo_Womb.cs @@ -0,0 +1,48 @@ +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); + } + + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/Utility.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/Utility.cs new file mode 100644 index 0000000..0020d86 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/Utility.cs @@ -0,0 +1,461 @@ +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 float GetCumVolume(this Pawn pawn) + { + List 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 hediffs) + { + CompHediffBodyPart part = (((hediffs?.FindAll((Hediff hed) => hed.def.defName.ToLower().Contains("penis")).InRandomOrder().FirstOrDefault()?.TryGetComp()) ?? + (hediffs?.FindAll((Hediff hed) => hed.def.defName.ToLower().Contains("ovipositorf")).InRandomOrder().FirstOrDefault()?.TryGetComp())) ?? + (hediffs?.FindAll((Hediff hed) => hed.def.defName.ToLower().Contains("ovipositorm")).InRandomOrder().FirstOrDefault()?.TryGetComp())) ?? + (hediffs?.FindAll((Hediff hed) => hed.def.defName.ToLower().Contains("tentacle")).InRandomOrder().FirstOrDefault()?.TryGetComp()); + return pawn.GetCumVolume(part); + } + + + public static float GetCumVolume(this Pawn pawn, CompHediffBodyPart part) + { + float res; + + try + { + res = VariationRange(part.FluidAmmount * part.FluidModifier * pawn.BodySize / pawn.RaceProps.baseBodySize, 0.2f); + } + catch (NullReferenceException) + { + res = 0.0f; + } + 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(); + } + + public static HediffComp_Breast GetBreastComp(this Hediff hediff) + { + if (hediff is Hediff_PartBaseNatural) + { + return hediff.TryGetComp(); + } + return null; + } + + public static List GetMilkComps(this Pawn pawn) + { + List 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 Hediff_PartBaseNatural || hediff is Hediff_PartBaseArtifical) && hediff.TryGetComp() != null) + return true; + else return false; + } + + public static bool IsRJWPregnant(this Pawn pawn) + { + return pawn.health.hediffSet.GetFirstHediff() != 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 pregnancies = new List(); + 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(); + return babiescomp?.babies?.FirstOrDefault(); + } + + 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(); + string icon; + if (comp != null) icon = comp.Props?.BreastTex ?? "Breasts/Breast_Breast"; + else + { + breast = ContentFinder.Get("Breasts/Breast_Breast00", false); + nipple = ContentFinder.Get("Breasts/Breast_Breast00_Nipple00", false); + areola = ContentFinder.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.Get(icon, false); + areola = ContentFinder.Get(areolaicon, false); + nipple = ContentFinder.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.Get("Breasts/Breast_Breast00", false); + nipple = ContentFinder.Get("Breasts/Breast_Breast00_Nipple00", false); + areola = ContentFinder.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 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(); + } + + 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.Get("Milk/Milkbottle_Small", false); + else if (fullness < 0.7f) texture = ContentFinder.Get("Milk/Milkbottle_Medium", false); + else texture = ContentFinder.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; + } + } + } +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/VariousDefOf.cs b/1.5/source/RJW_Menstruation/RJW_Menstruation/VariousDefOf.cs new file mode 100644 index 0000000..16903b2 --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/VariousDefOf.cs @@ -0,0 +1,174 @@ +using RimWorld; +using rjw; +using System.Collections.Generic; +using System.Linq; +using Verse; + +namespace RJW_Menstruation +{ + public static class VariousDefOf + { + + public static readonly ThingDef CumFilth = DefDatabase.GetNamed("FilthCum"); + public static readonly ThingDef GirlCumFilth = DefDatabase.GetNamed("FilthGirlCum"); + public static readonly ThingDef Tampon = DefDatabase.GetNamed("Absorber_Tampon"); + public static readonly ThingDef Tampon_Dirty = DefDatabase.GetNamed("Absorber_Tampon_Dirty"); + public static readonly ThingDef FilthMixture = DefDatabase.GetNamed("FilthMixture"); + public static readonly ThingDef Scyther = DefDatabase.GetNamed("Mech_Scyther"); + public static readonly HediffDef RJW_IUD = DefDatabase.GetNamed("RJW_IUD"); + public static readonly HediffDef Hediff_MenstrualCramp = DefDatabase.GetNamed("Hediff_MenstrualCramp"); + public static readonly HediffDef Hediff_Estrus = DefDatabase.GetNamed("Hediff_Estrus"); + public static readonly HediffDef Hediff_Estrus_Concealed = DefDatabase.GetNamed("Hediff_Estrus_Concealed"); + public static readonly HediffDef Hediff_AffectedByPheromones = DefDatabase.GetNamed("Hediff_AffectedByPheromones"); + public static readonly HediffDef Hediff_ASA = DefDatabase.GetNamed("Hediff_ASA"); + public static readonly StatDef MaxAbsorbable = DefDatabase.GetNamed("MaxAbsorbable"); + public static readonly NeedDef SexNeed = DefDatabase.GetNamed("Sex"); + public static readonly JobDef VaginaWashing = DefDatabase.GetNamed("VaginaWashing"); + public static readonly JobDef Job_LactateSelf = DefDatabase.GetNamed("LactateSelf"); + public static readonly ThoughtDef LeakingFluids = DefDatabase.GetNamed("LeakingFluids"); + public static readonly ThoughtDef CameInsideF = DefDatabase.GetNamed("CameInsideF"); + public static readonly ThoughtDef CameInsideFLowFert = DefDatabase.GetNamed("CameInsideFLowFert"); + public static readonly ThoughtDef CameInsideFFetish = DefDatabase.GetNamed("CameInsideFFetish"); + public static readonly ThoughtDef CameInsideFFetishSafe = DefDatabase.GetNamed("CameInsideFFetishSafe"); + public static readonly ThoughtDef HaterCameInsideFSafe = DefDatabase.GetNamed("HaterCameInsideFSafe"); + public static readonly ThoughtDef HaterCameInsideF = DefDatabase.GetNamed("HaterCameInsideF"); + public static readonly ThoughtDef HaterCameInsideFEstrus = DefDatabase.GetNamed("HaterCameInsideFEstrus"); + public static readonly ThoughtDef CameInsideM = DefDatabase.GetNamed("CameInsideM"); + public static readonly ThoughtDef HaterCameInsideM = DefDatabase.GetNamed("HaterCameInsideM"); + public static readonly ThoughtDef UnwantedPregnancy = DefDatabase.GetNamed("UnwantedPregnancy"); + public static readonly ThoughtDef UnwantedPregnancyMild = DefDatabase.GetNamed("UnwantedPregnancyMild"); + public static readonly ThoughtDef TookContraceptivePill = DefDatabase.GetNamed("TookContraceptivePill"); + public static readonly ThoughtDef HateTookContraceptivePill = DefDatabase.GetNamed("HateTookContraceptivePill"); + public static readonly ThoughtDef EggRestorationReceived = DefDatabase.GetNamed("EggRestorationReceived"); + public static readonly CompProperties_Menstruation HumanVaginaCompProperties = Genital_Helper.average_vagina.CompProps(); + public static readonly KeyBindingDef OpenStatusWindowKey = DefDatabase.GetNamed("OpenStatusWindow"); + public static readonly RecordDef AmountofCreampied = DefDatabase.GetNamed("AmountofCreampied"); + public static readonly RecordDef AmountofFertilizedEggs = DefDatabase.GetNamed("AmountofFertilizedEggs"); + public static readonly TaleDef TaleCameInside = DefDatabase.GetNamed("CameInside"); + + private static List allraces = null; + private static List allkinds = null; + private static HashSet allvaginas = null; + private static HashSet allanuses = null; + private static HashSet allbreasts = null; + private static HashSet egglayergenes = null; + + public static List AllRaces + { + get + { + if (allraces != null) return allraces; + allraces = DefDatabase.AllDefsListForReading.Where(thingdef => thingdef.race?.IsFlesh ?? false).ToList(); + + return allraces; + } + } + public static List AllKinds + { + get + { + if (allkinds != null) return allkinds; + allkinds = DefDatabase.AllDefsListForReading.Where(pawnkinddef => pawnkinddef.race != null).ToList(); + + return allkinds; + } + } + public static HashSet AllVaginas + { + get + { + if (allvaginas != null) return allvaginas; + allvaginas = new HashSet(); + + foreach(HediffDef hediffDef in DefDatabase.AllDefsListForReading) + { + if (hediffDef.comps.NullOrEmpty()) continue; + foreach (HediffCompProperties comp in hediffDef.comps) + { + if (comp.compClass == typeof(HediffComp_Menstruation) || (comp.compClass?.IsSubclassOf(typeof(HediffComp_Menstruation)) ?? false)) + { + allvaginas.Add(hediffDef); + break; + } + } + } + + return allvaginas; + } + } + public static HashSet AllAnuses + { + get + { + if (allanuses != null) return allanuses; + allanuses = new HashSet(); + + foreach (HediffDef hediffDef in DefDatabase.AllDefsListForReading) + { + if (hediffDef.comps.NullOrEmpty()) continue; + foreach (HediffCompProperties comp in hediffDef.comps) + { + if (comp.compClass == typeof(HediffComp_Anus) || (comp.compClass?.IsSubclassOf(typeof(HediffComp_Anus)) ?? false)) + { + allanuses.Add(hediffDef); + break; + } + } + } + + return allanuses; + } + } + public static HashSet AllBreasts + { + get + { + if (allbreasts != null) return allbreasts; + allbreasts = new HashSet(); + + foreach(HediffDef hediffDef in DefDatabase.AllDefsListForReading) + { + if (hediffDef.comps.NullOrEmpty()) continue; + foreach(HediffCompProperties comp in hediffDef.comps) + { + if (comp.compClass == typeof(HediffComp_Breast) || (comp.compClass?.IsSubclassOf(typeof(HediffComp_Breast)) ?? false)) + { + allbreasts.Add(hediffDef); + break; + } + } + } + + return allbreasts; + } + } + public static HashSet EggLayerGenes + { + get + { + if (egglayergenes != null) return egglayergenes; + egglayergenes = DefDatabase.AllDefsListForReading.Where(geneDef => geneDef.GetModExtension()?.disableCycle ?? false).ToHashSet(); + + return egglayergenes; + } + } + + // Defs from Milkable Colonists + public static readonly HediffDef Hediff_Lactating_Drug = DefDatabase.GetNamedSilentFail("Lactating_Drug"); + public static readonly HediffDef Hediff_Lactating_Natural = DefDatabase.GetNamedSilentFail("Lactating_Natural"); + public static readonly HediffDef Hediff_Lactating_Permanent = DefDatabase.GetNamedSilentFail("Lactating_Permanent"); + public static readonly HediffDef Hediff_Heavy_Lactating_Permanent = DefDatabase.GetNamedSilentFail("Heavy_Lactating_Permanent"); + public static readonly JobDef Job_LactateSelf_MC = DefDatabase.GetNamedSilentFail("LactateSelf_MC"); + + // Defs from Sexperience Ideology + public static readonly PreceptDef Pregnancy_Elevated = DefDatabase.GetNamedSilentFail("Pregnancy_Elevated"); + public static readonly PreceptDef Pregnancy_Holy = DefDatabase.GetNamedSilentFail("Pregnancy_Holy"); + public static readonly PreceptDef Pregnancy_Required = DefDatabase.GetNamedSilentFail("Pregnancy_Required"); + // Related thoughts + public static readonly ThoughtDef CameInsideMIdeo = DefDatabase.GetNamed("CameInsideMIdeo"); + public static readonly ThoughtDef CameInsideFIdeo = DefDatabase.GetNamed("CameInsideFIdeo"); + public static readonly ThoughtDef HaterCameInsideFIdeo = DefDatabase.GetNamed("HaterCameInsideFIdeo"); + public static readonly ThoughtDef HateTookContraceptivePillIdeo = DefDatabase.GetNamed("HateTookContraceptivePillIdeo"); + } + +} diff --git a/1.5/source/RJW_Menstruation/RJW_Menstruation/packages.config b/1.5/source/RJW_Menstruation/RJW_Menstruation/packages.config new file mode 100644 index 0000000..3299dfc --- /dev/null +++ b/1.5/source/RJW_Menstruation/RJW_Menstruation/packages.config @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/About/About.xml b/About/About.xml index c4c11a0..7813e42 100644 --- a/About/About.xml +++ b/About/About.xml @@ -8,6 +8,7 @@
  • 1.2
  • 1.3
  • 1.4
  • +
  • 1.5
  • @@ -34,6 +35,9 @@
  • conit.thebirdsandthebees
  • + +
  • conit.thebirdsandthebees
  • +
    Adds menstruation mechanics to vaginas: