Merge 1.0.7.0

This commit is contained in:
lutepickle 2022-07-26 07:41:42 -07:00
commit 3b0dade1bc
55 changed files with 1307 additions and 1540 deletions

Binary file not shown.

View file

@ -0,0 +1,31 @@
<Defs>
<TaleDef>
<defName>CameInside</defName>
<label>came inside</label>
<taleClass>Tale_DoublePawn</taleClass>
<type>Volatile</type>
<firstPawnSymbol>FUCKER</firstPawnSymbol>
<secondPawnSymbol>FUCKED</secondPawnSymbol>
<baseInterest>1.5</baseInterest>
<rulePack>
<rulesStrings>
<li>tale_noun->[FUCKER_nameDef] coming inside of [FUCKED_nameDef]</li>
<li>image->[FUCKER_nameFull]'s penis deep inside of [FUCKED_nameFull]'s vagina [circumstance_group]</li>
<li>image->[FUCKER_nameFull]'s penis vanishing into [FUCKED_nameFull]'s vagina [circumstance_group]</li>
<li>image->[FUCKED_nameFull]'s vagina being filled by [FUCKER_nameFull]'s penis [circumstance_group]</li>
<li>image->[FUCKED_nameFull]'s vagina gripping [FUCKER_nameFull]'s penis tight [cirsumstance_group]</li>
<li>circumstance_phrase->while [FUCKER_nameDef] grits [FUCKER_possessive] teeth</li>
<li>circumstance_phrase->while [FUCKER_nameDef] wears a triumphant smirk</li>
<li>circumstance_phrase->as [FUCKED_nameDef] shudders in ecstasy</li>
<li>circumstance_phrase->as [FUCKER_nameDef] shoots [FUCKER_possessive] load into [FUCKED_nameDef]</li>
<li>circumstance_phrase->while [FUCKED_nameDef] looks into [FUCKER_nameDef]'s eyes with a smile</li>
<li>desc_sentence->[FUCKER_nameDef]'s cum oozes out of [FUCKED_nameDef]'s vagina and drips onto the floor.</li>
<li>desc_sentence->[FUCKER_nameDef]'s sperm races into [FUCKED_nameDef]'s womb and enters [FUCKED_possessive] egg.</li>
<li>desc_sentence->[FUCKER_nameDef]'s cum shoots into [FUCKED_nameDef]'s womb.</li>
<li>desc_sentence->[FUCKED_nameDef]'s womb is filled with cum.</li>
<li>desc_sentence->Sweat runs down [FUCKER_nameDef]'s face.</li>
<li>desc_sentence->[FUCKED_nameDef] is panting heavily.</li>
</rulesStrings>
</rulePack>
</TaleDef>
</Defs>

View file

@ -8,7 +8,6 @@
<Stage_Ovulatory>排卵</Stage_Ovulatory>
<Stage_Luteal>黄体期</Stage_Luteal>
<Stage_Bleeding>月经来潮</Stage_Bleeding>
<Stage_Fertilized>已受精</Stage_Fertilized>
<Stage_Pregnant>怀孕</Stage_Pregnant>
<Stage_Recover>产后恢复</Stage_Recover>
<Stage_None></Stage_None>

View file

@ -8,7 +8,6 @@
<Stage_Ovulatory>排卵</Stage_Ovulatory>
<Stage_Luteal>黃體期</Stage_Luteal>
<Stage_Bleeding>月經來潮</Stage_Bleeding>
<Stage_Fertilized>已受精</Stage_Fertilized>
<Stage_Pregnant>懷孕</Stage_Pregnant>
<Stage_Recover>從出生中恢復</Stage_Recover>
<Stage_None></Stage_None>

View file

@ -8,7 +8,6 @@
<Stage_Ovulatory>Ovulation</Stage_Ovulatory>
<Stage_Luteal>Luteal</Stage_Luteal>
<Stage_Bleeding>In period</Stage_Bleeding>
<Stage_Fertilized>Luteal</Stage_Fertilized>
<Stage_Pregnant>Pregnant</Stage_Pregnant>
<Stage_Recover>Recovering from birth</Stage_Recover>
<Stage_None>None</Stage_None>

View file

@ -8,7 +8,6 @@
<Stage_Ovulatory>배란</Stage_Ovulatory>
<Stage_Luteal>황체기</Stage_Luteal>
<Stage_Bleeding>생리중</Stage_Bleeding>
<Stage_Fertilized>황체기</Stage_Fertilized>
<Stage_Pregnant>임신</Stage_Pregnant>
<Stage_Recover>회복기</Stage_Recover>
<Stage_None>없음</Stage_None>

View file

@ -8,7 +8,6 @@
<Stage_Ovulatory>Ovulación</Stage_Ovulatory>
<Stage_Luteal>Luteal</Stage_Luteal>
<Stage_Bleeding>En periodo</Stage_Bleeding>
<Stage_Fertilized>Luteal</Stage_Fertilized>
<Stage_Pregnant>Embarazada</Stage_Pregnant>
<Stage_Recover>Recuperándose del nacimiento</Stage_Recover>
<Stage_None>Ninguna</Stage_None>

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- one cycle = folicularIntervalDays + lutealIntervalDays -->
<!-- folicularIntervalDays includes bleedingIntervalDays. -->
<!-- bleedingIntervalDays must be smaller than folicularIntervalDays -->
<!-- one cycle = follicularIntervalDays + lutealIntervalDays -->
<!-- follicularIntervalDays includes bleedingIntervalDays. -->
<!-- bleedingIntervalDays must be smaller than follicularIntervalDays -->
<!-- unit of maxCumCapacity is ml -->
<!-- actual max cum capacity is 500times of maxCumCapacity -->
<!-- one egg = 1 ovaryPower-->
@ -16,15 +16,13 @@
<maxCumCapacity>10</maxCumCapacity>
<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>1.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>14</folicularIntervalDays>
<follicularIntervalDays>14</follicularIntervalDays>
<lutealIntervalDays>14</lutealIntervalDays>
<bleedingIntervalDays>6</bleedingIntervalDays>
<recoveryIntervalDays>30</recoveryIntervalDays>
<eggLifespanDays>1</eggLifespanDays>
<wombTex>Womb/Womb</wombTex>
<vagTex>Genitals/Vagina</vagTex>
<ovaryPower>420</ovaryPower>
<concealedEstrus>true</concealedEstrus>
</li>
</comps>
@ -40,8 +38,7 @@
<maxCumCapacity>10</maxCumCapacity>
<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>1.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>14</folicularIntervalDays>
<follicularIntervalDays>14</follicularIntervalDays>
<lutealIntervalDays>14</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>30</recoveryIntervalDays>
@ -89,8 +86,7 @@
<maxCumCapacity>10</maxCumCapacity>
<baseImplantationChanceFactor>2.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>2.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>14</folicularIntervalDays>
<follicularIntervalDays>14</follicularIntervalDays>
<lutealIntervalDays>14</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>0</recoveryIntervalDays>

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- one cycle = folicularIntervalDays + lutealIntervalDays -->
<!-- folicularIntervalDays includes bleedingIntervalDays. -->
<!-- bleedingIntervalDays must be smaller than folicularIntervalDays -->
<!-- one cycle = follicularIntervalDays + lutealIntervalDays -->
<!-- follicularIntervalDays includes bleedingIntervalDays. -->
<!-- bleedingIntervalDays must be smaller than follicularIntervalDays -->
<!-- unit of maxCumCapacity is ml -->
<!-- actual max cum capacity is 500times of maxCumCapacity -->
<!-- one egg = 1 ovaryPower-->
@ -18,8 +18,7 @@
<maxCumCapacity>8</maxCumCapacity>
<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>1.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>14</folicularIntervalDays>
<follicularIntervalDays>14</follicularIntervalDays>
<lutealIntervalDays>166</lutealIntervalDays>
<bleedingIntervalDays>8</bleedingIntervalDays>
<recoveryIntervalDays>15</recoveryIntervalDays>
@ -40,8 +39,7 @@
<maxCumCapacity>6</maxCumCapacity>
<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>2.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>9</folicularIntervalDays>
<follicularIntervalDays>9</follicularIntervalDays>
<lutealIntervalDays>10</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>15</recoveryIntervalDays>
@ -63,8 +61,7 @@
<maxCumCapacity>25</maxCumCapacity>
<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>1.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>7</folicularIntervalDays>
<follicularIntervalDays>7</follicularIntervalDays>
<lutealIntervalDays>14</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>30</recoveryIntervalDays>
@ -87,8 +84,7 @@
<maxCumCapacity>50</maxCumCapacity>
<baseImplantationChanceFactor>0.5</baseImplantationChanceFactor>
<basefertilizationChanceFactor>0.2</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>270</folicularIntervalDays>
<follicularIntervalDays>270</follicularIntervalDays>
<lutealIntervalDays>30</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>300</recoveryIntervalDays>
@ -109,8 +105,7 @@
<maxCumCapacity>10</maxCumCapacity>
<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>1.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>5</folicularIntervalDays>
<follicularIntervalDays>5</follicularIntervalDays>
<lutealIntervalDays>16</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>15</recoveryIntervalDays>
@ -131,8 +126,7 @@
<maxCumCapacity>5</maxCumCapacity>
<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>2.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>6</folicularIntervalDays>
<follicularIntervalDays>6</follicularIntervalDays>
<lutealIntervalDays>9</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>3</recoveryIntervalDays>
@ -153,8 +147,7 @@
<maxCumCapacity>5</maxCumCapacity>
<baseImplantationChanceFactor>2.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>2.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>12</folicularIntervalDays>
<follicularIntervalDays>12</follicularIntervalDays>
<lutealIntervalDays>9</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>3</recoveryIntervalDays>
@ -175,8 +168,7 @@
<maxCumCapacity>10</maxCumCapacity>
<baseImplantationChanceFactor>2.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>2.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>14</folicularIntervalDays>
<follicularIntervalDays>14</follicularIntervalDays>
<lutealIntervalDays>14</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>3</recoveryIntervalDays>

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- one cycle = folicularIntervalDays + lutealIntervalDays -->
<!-- folicularIntervalDays includes bleedingIntervalDays. -->
<!-- bleedingIntervalDays must be smaller than folicularIntervalDays -->
<!-- one cycle = follicularIntervalDays + lutealIntervalDays -->
<!-- follicularIntervalDays includes bleedingIntervalDays. -->
<!-- bleedingIntervalDays must be smaller than follicularIntervalDays -->
<!-- unit of maxCumCapacity is ml -->
<!-- actual max cum capacity is 500times of maxCumCapacity -->
<!-- one egg = 1 ovaryPower-->
@ -18,8 +18,7 @@
<maxCumCapacity>18</maxCumCapacity>
<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>1.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>10</folicularIntervalDays>
<follicularIntervalDays>10</follicularIntervalDays>
<lutealIntervalDays>10</lutealIntervalDays>
<bleedingIntervalDays>4</bleedingIntervalDays>
<recoveryIntervalDays>30</recoveryIntervalDays>
@ -40,8 +39,7 @@
<maxCumCapacity>8</maxCumCapacity>
<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>1.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>8</folicularIntervalDays>
<follicularIntervalDays>8</follicularIntervalDays>
<lutealIntervalDays>12</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>0</recoveryIntervalDays>
@ -62,8 +60,7 @@
<maxCumCapacity>15</maxCumCapacity>
<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>1.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>10</folicularIntervalDays>
<follicularIntervalDays>10</follicularIntervalDays>
<lutealIntervalDays>12</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>30</recoveryIntervalDays>
@ -84,8 +81,7 @@
<maxCumCapacity>8</maxCumCapacity>
<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>1.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>6</folicularIntervalDays>
<follicularIntervalDays>6</follicularIntervalDays>
<lutealIntervalDays>12</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>30</recoveryIntervalDays>
@ -106,8 +102,7 @@
<maxCumCapacity>12</maxCumCapacity>
<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>1.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>14</folicularIntervalDays>
<follicularIntervalDays>14</follicularIntervalDays>
<lutealIntervalDays>20</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>30</recoveryIntervalDays>
@ -128,8 +123,7 @@
<maxCumCapacity>2</maxCumCapacity>
<baseImplantationChanceFactor>0.1</baseImplantationChanceFactor>
<basefertilizationChanceFactor>0.1</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>14</folicularIntervalDays>
<follicularIntervalDays>14</follicularIntervalDays>
<lutealIntervalDays>14</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>0</recoveryIntervalDays>
@ -150,8 +144,7 @@
<maxCumCapacity>10</maxCumCapacity>
<baseImplantationChanceFactor>0.1</baseImplantationChanceFactor>
<basefertilizationChanceFactor>0.1</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>14</folicularIntervalDays>
<follicularIntervalDays>14</follicularIntervalDays>
<lutealIntervalDays>14</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>0</recoveryIntervalDays>

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- one cycle = folicularIntervalDays + lutealIntervalDays -->
<!-- folicularIntervalDays includes bleedingIntervalDays. -->
<!-- bleedingIntervalDays must be smaller than folicularIntervalDays -->
<!-- one cycle = follicularIntervalDays + lutealIntervalDays -->
<!-- follicularIntervalDays includes bleedingIntervalDays. -->
<!-- bleedingIntervalDays must be smaller than follicularIntervalDays -->
<!-- unit of maxCumCapacity is ml -->
<!-- actual max cum capacity is 500times of maxCumCapacity -->
<!-- one egg = 1 ovaryPower-->
@ -16,15 +16,13 @@
<maxCumCapacity>10</maxCumCapacity>
<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>1.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>1800</folicularIntervalDays>
<follicularIntervalDays>1800</follicularIntervalDays>
<lutealIntervalDays>1800</lutealIntervalDays>
<bleedingIntervalDays>6</bleedingIntervalDays>
<recoveryIntervalDays>30</recoveryIntervalDays>
<eggLifespanDays>1</eggLifespanDays>
<wombTex>Womb/Womb</wombTex>
<vagTex>Genitals/Vagina</vagTex>
<ovaryPower>620</ovaryPower>
<concealedEstrus>true</concealedEstrus>
</li>
</comps>
@ -50,15 +48,13 @@
<maxCumCapacity>10</maxCumCapacity>
<baseImplantationChanceFactor>1.0</baseImplantationChanceFactor>
<basefertilizationChanceFactor>1.0</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>7</folicularIntervalDays>
<follicularIntervalDays>7</follicularIntervalDays>
<lutealIntervalDays>10</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>10</recoveryIntervalDays>
<eggLifespanDays>1</eggLifespanDays>
<wombTex>Womb/Womb</wombTex>
<vagTex>Genitals/Vagina</vagTex>
<ovaryPower>620</ovaryPower>
<concealedEstrus>true</concealedEstrus>
</li>
</comps>
@ -86,15 +82,13 @@
<maxCumCapacity>10</maxCumCapacity>
<baseImplantationChanceFactor>0.2</baseImplantationChanceFactor>
<basefertilizationChanceFactor>0.2</basefertilizationChanceFactor>
<deviationFactor>0.05</deviationFactor>
<folicularIntervalDays>14</folicularIntervalDays>
<follicularIntervalDays>14</follicularIntervalDays>
<lutealIntervalDays>14</lutealIntervalDays>
<bleedingIntervalDays>0</bleedingIntervalDays>
<recoveryIntervalDays>10</recoveryIntervalDays>
<eggLifespanDays>1</eggLifespanDays>
<wombTex>Womb/Womb</wombTex>
<vagTex>Genitals/Vagina</vagTex>
<ovaryPower>420</ovaryPower>
<concealedEstrus>true</concealedEstrus>
</li>
</comps>

View file

@ -1,13 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using Verse.AI;
using RimWorld;
using Milk;
using Milk;
using RJW_Menstruation;
using Verse;
namespace MilkModule
{
@ -51,7 +44,7 @@ namespace MilkModule
if (pawn.health.hediffSet.HasHediff(VariousDefOf.Hediff_Heavy_Lactating_Permanent))
{
result = pawn.TryGetComp<CompHyperMilkableHuman>();
}
else
{
@ -125,6 +118,6 @@ namespace MilkModule
//
//
//}
}

View file

@ -1,14 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using HarmonyLib;
using Verse;
using RimWorld;
using HarmonyLib;
using Milk;
using RJW_Menstruation;
using System.Reflection;
using Verse;
namespace MilkModule
{
@ -16,7 +10,7 @@ namespace MilkModule
{
static First()
{
var har = new Harmony("RJW_Menstruation_MilkModule");
Harmony har = new Harmony("RJW_Menstruation_MilkModule");
har.PatchAll(Assembly.GetExecutingAssembly());
}
}

View file

@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해

View file

@ -10,12 +10,12 @@ namespace RJW_Menstruation
{
public const float ImplantationChanceDefault = 0.65f;
public const int ImplantationChanceAdjustDefault = 65;
public const float FertilizeChanceDefault = 0.10f;
public const int FertilizeChanceAdjustDefault = 100;
public const float CumDecayRatioDefault = 0.30f;
public const int CumDecayRatioAdjustDefault = 300;
public const float CumFertilityDecayRatioDefault = 0.2f;
public const int CumFertilityDecayRatioAdjustDefault = 200;
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 float EnzygoticTwinsChanceDefault = 0.002f;
public const int EnzygoticTwinsChanceAdjustDefault = 2;
@ -79,7 +79,7 @@ namespace RJW_Menstruation
return NippleTransitionVariance * NippleTransitionSpeed;
}
}
public static void SettoDefault()
{
ImplantationChanceAdjust = ImplantationChanceAdjustDefault;
@ -152,14 +152,14 @@ namespace RJW_Menstruation
{
List<HybridInformations> removeList = new List<HybridInformations>();
if (!HybridOverride.NullOrEmpty())
foreach(HybridInformations o in HybridOverride)
foreach (HybridInformations o in HybridOverride)
{
if (o.IsNull) removeList.Add(o);
if (o.DefName == def.defName) return true;
}
if (!removeList.NullOrEmpty())
{
foreach(HybridInformations o in removeList)
foreach (HybridInformations o in removeList)
{
HybridOverride.Remove(o);
}
@ -226,7 +226,7 @@ namespace RJW_Menstruation
base.ExposeData();
}
}
@ -242,7 +242,7 @@ namespace RJW_Menstruation
{
get
{
int days = VariousDefOf.VaginaCompProperties.bleedingIntervalDays;
int days = VariousDefOf.HumanVaginaCompProperties.bleedingIntervalDays;
return days * 0.03f * Configurations.BleedingAmount * 6;
}
}
@ -300,7 +300,7 @@ namespace RJW_Menstruation
{
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);
if (wombsection.ButtonText(Translations.Option11_Label + ": " + Configurations.LevelString(Configurations.infoDetail)))
@ -353,17 +353,17 @@ namespace RJW_Menstruation
}
Adjust = (int)(Configurations.NippleTransitionVariance * 1000);
wombsection.Label(Translations.Option24_Label + " " + Configurations.NippleTransitionVariance* 100 + " / 100", -1,Translations.Option24_Desc);
Adjust = (int)wombsection.Slider(Adjust,0,1000);
wombsection.Label(Translations.Option24_Label + " " + Configurations.NippleTransitionVariance * 100 + " / 100", -1, Translations.Option24_Desc);
Adjust = (int)wombsection.Slider(Adjust, 0, 1000);
Configurations.NippleTransitionVariance = (float)Adjust / 1000;
Adjust = (int)(Configurations.NipplePermanentTransitionVariance * 1000);
wombsection.Label(Translations.Option25_Label + " " + Configurations.NipplePermanentTransitionVariance*100 + " / 100", -1, Translations.Option25_Desc);
wombsection.Label(Translations.Option25_Label + " " + Configurations.NipplePermanentTransitionVariance * 100 + " / 100", -1, Translations.Option25_Desc);
Adjust = (int)wombsection.Slider(Adjust, 0, 1000);
Configurations.NipplePermanentTransitionVariance = (float)Adjust / 1000;
Adjust = (int)(Configurations.NippleMaximumTransition * 1000);
wombsection.Label(Translations.Option26_Label + " " + Configurations.NippleMaximumTransition* 100 + " / 100", -1, Translations.Option26_Desc);
wombsection.Label(Translations.Option26_Label + " " + Configurations.NippleMaximumTransition * 100 + " / 100", -1, Translations.Option26_Desc);
Adjust = (int)wombsection.Slider(Adjust, 0, 1000);
Configurations.NippleMaximumTransition = (float)Adjust / 1000;
@ -383,7 +383,8 @@ namespace RJW_Menstruation
Configurations.ImplantationChanceAdjust = (int)listmain.Slider(Configurations.ImplantationChanceAdjust, 0, 1000);
Configurations.ImplantationChance = (float)Configurations.ImplantationChanceAdjust / 100;
listmain.Label(Translations.Option4_Label + " " + Configurations.FertilizeChance * 100 + "%", -1, Translations.Option4_Desc);
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;
@ -399,7 +400,7 @@ namespace RJW_Menstruation
Configurations.EggLifespanMultiplier = (float)Adjust / 20;
int semenlifespan = (int)(-5 / ((float)Math.Log10((1 - Configurations.CumFertilityDecayRatio)*10) - 1)) + 1;
int semenlifespan = (int)(-5 / ((float)Math.Log10((1 - Configurations.CumFertilityDecayRatio) * (1 - Configurations.CumDecayRatio) * 10) - 1)) + 1;
string estimatedlifespan;
if (semenlifespan < 0)
{

View file

@ -11,8 +11,7 @@ namespace RJW_Menstruation
public Pawn pawn;
protected float volume; // ml
protected float fertvolume;
public float fertFactor = 1.0f;
public float fertility = 1.0f;
public bool notcum = false; // for other fluids
public string notcumLabel = "";
protected bool useCustomColor = false;
@ -32,7 +31,7 @@ namespace RJW_Menstruation
{
get
{
return fertvolume;
return volume * fertility;
}
}
@ -62,23 +61,20 @@ namespace RJW_Menstruation
{
get
{
if (DNAcache != null) return DNAcache;
try
{
DNAcache = pawn.def.GetModExtension<PawnDNAModExtension>();
}
catch (NullReferenceException)
{
DNAcache = ThingDefOf.Human.GetModExtension<PawnDNAModExtension>();
}
if (DNAcache == null)
{
try
{
DNAcache = pawn.def.GetModExtension<PawnDNAModExtension>();
}
catch (NullReferenceException)
{
DNAcache = ThingDefOf.Human.GetModExtension<PawnDNAModExtension>();
}
if (DNAcache == null)
{
DNAcache = ThingDefOf.Human.GetModExtension<PawnDNAModExtension>();
}
return DNAcache;
DNAcache = ThingDefOf.Human.GetModExtension<PawnDNAModExtension>();
}
else return DNAcache;
return DNAcache;
}
}
protected PawnDNAModExtension DNAcache = null;
@ -130,7 +126,7 @@ namespace RJW_Menstruation
{
this.pawn = pawn;
volume = 1.0f;
fertvolume = 1.0f;
fertility = 1.0f;
}
/// <summary>
@ -145,7 +141,7 @@ namespace RJW_Menstruation
{
this.pawn = pawn;
this.volume = volume;
this.fertvolume = volume;
this.fertility = 0f;
this.notcum = true;
this.notcumLabel = notcumlabel;
this.notcumthickness = decayresist;
@ -156,7 +152,7 @@ namespace RJW_Menstruation
{
this.pawn = pawn;
this.volume = volume;
this.fertvolume = volume * fertility;
this.fertility = fertility;
this.filthDef = filthDef;
}
@ -167,9 +163,8 @@ namespace RJW_Menstruation
Scribe_References.Look(ref pawn, "pawn", true);
Scribe_References.Look(ref internalThing, "internalThing", true);
Scribe_Values.Look(ref volume, "volume", volume, true);
Scribe_Values.Look(ref fertvolume, "fertvolume", fertvolume, true);
Scribe_Values.Look(ref fertility, "fertility", fertility, true);
Scribe_Values.Look(ref notcumthickness, "notcumthickness", notcumthickness, true);
Scribe_Values.Look(ref fertFactor, "fertFactor", fertFactor, true);
Scribe_Values.Look(ref notcum, "notcum", notcum, true);
Scribe_Values.Look(ref notcumLabel, "notcumLabel", notcumLabel, true);
Scribe_Values.Look(ref useCustomColor, "useCustomColor", useCustomColor, true);
@ -183,11 +178,11 @@ namespace RJW_Menstruation
cumthickness = cumthickness.LerpMultiple(DecayResist, 0.3f, speed);
}
public void MergeWithCum(float volumein, float fertility, ThingDef updatefilthDef = null)
public void MergeWithCum(float volumein, float fertility, ThingDef updatefilthDef = null)
{
if (updatefilthDef != null) filthDef = updatefilthDef;
volume += volumein;
fertvolume += volumein*fertility;
this.fertility = (this.volume * this.fertility + volumein * fertility) / (this.volume + volumein);
cumthickness = Mathf.Lerp(cumthickness, 1.0f, volumein / volume);
}
@ -195,12 +190,13 @@ namespace RJW_Menstruation
{
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;
if ((notcum || FertVolume < 0.001f) && volume < 0.01f) return true;
return false;
}
@ -209,17 +205,16 @@ namespace RJW_Menstruation
{
float totalleak = volume;
volume *= Math.Max(0, (1 - (Configurations.CumDecayRatio * (1 - DecayResist)) * leakfactor));
fertvolume *= Math.Max(0, 1 - (Configurations.CumFertilityDecayRatio * (1 - DecayResist) + antisperm));
fertility *= Math.Max(0, 1 - (Configurations.CumFertilityDecayRatio * (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);
fertvolume *= Math.Max(0, 1 - (portion * (1 - DecayResist)) * leakfactor);
volume *= Math.Max(0, 1 - (portion * (1 - DecayResist / 10)) * leakfactor);
CutMinor();
totalleak -= volume;
return totalleak;
@ -227,24 +222,20 @@ namespace RJW_Menstruation
public void CumEffects(Pawn pawn)
{
if (!notcum && DNA != null && volume >= 1.0f)
{
List<IngestionOutcomeDoer> doers = DNA.ingestionOutcomeDoers;
if (!doers.NullOrEmpty()) for (int i = 0; i < doers.Count; i++)
{
doers[i].DoIngestionOutcome(pawn, CumThing);
}
}
if (notcum || DNA == null || volume < 1.0f) return;
List<IngestionOutcomeDoer> doers = DNA.ingestionOutcomeDoers;
if (!doers.NullOrEmpty()) for (int i = 0; i < doers.Count; i++)
{
doers[i].DoIngestionOutcome(pawn, CumThing);
}
}
protected void CutMinor()
{
if (volume < 0.01f) volume = 0f;
if (fertvolume < 0.001f) fertvolume = 0f;
}
}
public class CumMixture : Cum, IDisposable
@ -259,7 +250,7 @@ namespace RJW_Menstruation
cums = new List<string>();
}
public CumMixture(Pawn pawn, float volume, List<string> cums, Color color, ThingDef mixtureDef, bool pure)
public CumMixture(Pawn pawn, float volume, List<string> cums, Color color, ThingDef mixtureDef, bool pure)
{
this.pawn = pawn;
this.volume = volume;
@ -272,7 +263,7 @@ namespace RJW_Menstruation
public void Dispose()
{
cums.Clear();
}
public override void ExposeData()
@ -284,17 +275,12 @@ namespace RJW_Menstruation
public string GetIngredients()
{
string res = "";
if (!cums.NullOrEmpty()) for(int i=0; i<cums.Count; i++)
if (!cums.NullOrEmpty()) for (int i = 0; i < cums.Count; i++)
{
res += cums[i];
if (i < cums.Count - 1) res += ", ";
}
return res;
}
}
}

View file

@ -9,28 +9,32 @@ namespace RJW_Menstruation
[DebugAction("RJW Menstruation", "Set pawn's state to follicular", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
private static void SetFollicular(Pawn p)
{
p.GetMenstruationComp().curStage = HediffComp_Menstruation.Stage.Follicular;
foreach (HediffComp_Menstruation comp in p.GetMenstruationComps())
comp.curStage = HediffComp_Menstruation.Stage.Follicular;
Messages.Message($"{p} is now follicular", 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)
{
p.GetMenstruationComp().curStage = HediffComp_Menstruation.Stage.Ovulatory;
foreach (HediffComp_Menstruation comp in p.GetMenstruationComps())
comp.curStage = HediffComp_Menstruation.Stage.Ovulatory;
Messages.Message($"{p} is now ovulatory", 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)
{
p.GetMenstruationComp().curStage = HediffComp_Menstruation.Stage.Luteal;
foreach (HediffComp_Menstruation comp in p.GetMenstruationComps())
comp.curStage = HediffComp_Menstruation.Stage.Luteal;
Messages.Message($"{p} is now luteal", 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)
{
p.GetMenstruationComp().curStage = HediffComp_Menstruation.Stage.Bleeding;
foreach (HediffComp_Menstruation comp in p.GetMenstruationComps())
comp.curStage = HediffComp_Menstruation.Stage.Bleeding;
Messages.Message($"{p} is now bleeding", MessageTypeDefOf.NeutralEvent, false);
}
/*
@ -49,21 +53,24 @@ namespace RJW_Menstruation
[DebugAction("RJW Menstruation", "Remove all cum from pawn's womb", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
private static void RemoveCums(Pawn p)
{
p.GetMenstruationComp().RemoveAllCums();
foreach (HediffComp_Menstruation comp in p.GetMenstruationComps())
comp.RemoveAllCums();
Messages.Message($"All cum removed from {p}'s womb", 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)
{
p.GetMenstruationComp().eggstack++;
Messages.Message($"1 egg added to {p}'s next ovulation ({p.GetMenstruationComp().eggstack})", MessageTypeDefOf.NeutralEvent, false);
foreach (HediffComp_Menstruation comp in p.GetMenstruationComps())
comp.eggstack++;
Messages.Message($"1 egg added to {p}'s next ovulation ({p.GetFirstMenstruationComp().eggstack})", 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)
{
p.GetMenstruationComp().ovarypower = p.GetMenstruationComp().GetOvaryPowerByAge(p);
Messages.Message($"{p}'s ovarypower recalculated ({p.GetMenstruationComp().ovarypower})", MessageTypeDefOf.NeutralEvent, false);
foreach (HediffComp_Menstruation comp in p.GetMenstruationComps())
comp.ovarypower = comp.GetOvaryPowerByAge();
Messages.Message($"{p}'s ovarypower recalculated ({p.GetFirstMenstruationComp().ovarypower})", MessageTypeDefOf.NeutralEvent, false);
}
}
}

View file

@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using RimWorld;
using Verse;
using RimWorld;
using rjw;
using System.Collections.Generic;
using Verse;
namespace RJW_Menstruation
{
@ -10,18 +9,18 @@ namespace RJW_Menstruation
{
protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested)
{
HediffComp_Menstruation comp = pawn.GetMenstruationComp();
if (comp != null && (comp.curStage.Equals(HediffComp_Menstruation.Stage.Follicular)
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.ClimactericFollicular)
|| comp.curStage.Equals(HediffComp_Menstruation.Stage.ClimactericLuteal)
|| comp.curStage.Equals(HediffComp_Menstruation.Stage.Anestrus)
))
{
comp.SetEstrus(comp.Props.eggLifespanDays);
comp.curStage = HediffComp_Menstruation.Stage.Ovulatory;
comp.ovarypower--;
}
)
{
comp.SetEstrus(comp.Props.eggLifespanDays);
comp.curStage = HediffComp_Menstruation.Stage.Ovulatory;
comp.ovarypower--;
}
}
}
@ -29,16 +28,16 @@ namespace RJW_Menstruation
{
protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested)
{
HediffComp_Menstruation comp = pawn.GetMenstruationComp();
if (comp != null && (comp.curStage.Equals(HediffComp_Menstruation.Stage.Follicular)
|| comp.curStage.Equals(HediffComp_Menstruation.Stage.ClimactericFollicular)
|| comp.curStage.Equals(HediffComp_Menstruation.Stage.Anestrus)
))
{
comp.SetEstrus(comp.Props.eggLifespanDays);
comp.curStage = HediffComp_Menstruation.Stage.Ovulatory;
comp.eggstack += ingested.stackCount - 1;
}
foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps())
if (comp.curStage.Equals(HediffComp_Menstruation.Stage.Follicular)
|| comp.curStage.Equals(HediffComp_Menstruation.Stage.ClimactericFollicular)
|| comp.curStage.Equals(HediffComp_Menstruation.Stage.Anestrus)
)
{
comp.SetEstrus(comp.Props.eggLifespanDays);
comp.curStage = HediffComp_Menstruation.Stage.Ovulatory;
comp.eggstack += ingested.stackCount - 1;
}
}
}
@ -62,11 +61,8 @@ namespace RJW_Menstruation
protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested)
{
HediffComp_Menstruation comp = pawn.GetMenstruationComp();
if (Configurations.EnableMenopause && comp != null)
{
comp.RecoverOvary(1 + effectOffset);
}
foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps())
if (Configurations.EnableMenopause) comp.RecoverOvary(1 + effectOffset);
}
}
@ -74,13 +70,8 @@ namespace RJW_Menstruation
{
protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested)
{
HediffComp_Menstruation comp = pawn.GetMenstruationComp();
if (comp != null)
{
foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps())
comp.eggstack += Rand.Range(1, 4);
}
}
}
@ -88,27 +79,21 @@ namespace RJW_Menstruation
{
protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested)
{
List<Thought_Memory> memories = pawn.needs?.mood?.thoughts?.memories?.Memories.FindAll(
x =>
x =>
x.def == VariousDefOf.CameInsideF
|| x.def == VariousDefOf.CameInsideFFetish
|| x.def == VariousDefOf.HaterCameInsideF);
if (!memories.NullOrEmpty())
if (memories.NullOrEmpty()) return;
foreach (Thought_Memory m in memories)
{
foreach (Thought_Memory m in memories)
{
if (m.def == VariousDefOf.HaterCameInsideF) m.moodPowerFactor = 0.5f;
else m.moodPowerFactor = 0.3f;
}
if (pawn.Has(Quirk.Breeder)) pawn.needs.mood.thoughts.memories.TryGainMemoryFast(VariousDefOf.HateTookContraceptivePill);
else pawn.needs.mood.thoughts.memories.TryGainMemoryFast(VariousDefOf.TookContraceptivePill);
if (m.def == VariousDefOf.HaterCameInsideF) m.moodPowerFactor = 0.5f;
else m.moodPowerFactor = 0.3f;
}
if (pawn.Has(Quirk.Breeder)) pawn.needs.mood.thoughts.memories.TryGainMemoryFast(VariousDefOf.HateTookContraceptivePill);
else pawn.needs.mood.thoughts.memories.TryGainMemoryFast(VariousDefOf.TookContraceptivePill);
}
}
}

View file

@ -1,10 +1,10 @@
using Verse;
using rjw;
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
{

View file

@ -1,21 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using HugsLib;
using RimWorld;
using UnityEngine;
using HugsLib;
using rjw;
using System;
using System.Collections.Generic;
using UnityEngine;
using Verse;
namespace RJW_Menstruation
{
public class CompProperties_Breast : HediffCompProperties
{
public string BreastTex = "Breasts/Breast";
public ColorInt BlacknippleColor = new ColorInt(55,20,0);
public ColorInt BlacknippleColor = new ColorInt(55, 20, 0);
public Color BlackNippleColor
{
@ -24,7 +21,7 @@ namespace RJW_Menstruation
return BlacknippleColor.ToColor;
}
}
public CompProperties_Breast()
{
@ -174,7 +171,7 @@ namespace RJW_Menstruation
Scribe_Values.Look(ref originareola, "originareola", originareola, true);
Scribe_Values.Look(ref originnipple, "originnipple", originnipple, true);
Scribe_Values.Look(ref pregnant, "pregnant", pregnant, true);
}
public override void CompPostTick(ref float severityAdjustment) { }
@ -187,17 +184,14 @@ namespace RJW_Menstruation
public override void CompPostPostRemoved()
{
if (parent?.pawn?.GetBreastComp() == this)
if (parent.pawn.health.hediffSet.hediffs.Contains(parent))
{
Log.Warning("Something tried to remove hediff with wrong way.");
}
else
{
HugsLibController.Instance.TickDelayScheduler.TryUnscheduleCallback(action);
Log.Message(parent.pawn.Label + "breast tick scheduler removed");
base.CompPostPostRemoved();
Log.Warning($"Attempted to remove breast comp from wrong pawn ({parent.pawn}).");
return;
}
HugsLibController.Instance.TickDelayScheduler.TryUnscheduleCallback(action);
if (Configurations.Debug) Log.Message(parent.pawn.Label + " breast tick scheduler removed");
base.CompPostPostRemoved();
}
protected long CalculateLastBirth()
@ -207,13 +201,16 @@ namespace RJW_Menstruation
{
foreach (Pawn child in parent.pawn.relations.Children)
{
bool isFetus;
if (PregnancyHelper.GetPregnancy(parent.pawn) is Hediff_BasePregnancy preg)
bool isFetus = false;
foreach (Hediff_BasePregnancy preg in parent.pawn.health.hediffSet.GetHediffs<Hediff_BasePregnancy>())
{
isFetus = preg.babies.Contains(child);
if (preg.babies.Contains(child))
{
isFetus = true;
break;
}
}
else isFetus = false;
if (
parent.pawn.ageTracker.BirthAbsTicks - child.ageTracker.BirthAbsTicks > ageOfLastBirth &&
!isFetus &&
@ -221,7 +218,7 @@ namespace RJW_Menstruation
)
youngestAge = parent.pawn.ageTracker.BirthAbsTicks - child.ageTracker.BirthAbsTicks;
}
}
}
return youngestAge;
}
@ -234,10 +231,10 @@ namespace RJW_Menstruation
{
ageOfLastBirth = CalculateLastBirth();
}
if (alphaPermanent < 0f)
{
alphaPermanent = (Utility.RandGaussianLike(0.0f, 0.3f) + Rand.Range(0.0f,0.5f))/2;
alphaPermanent = (Utility.RandGaussianLike(0.0f, 0.3f) + Rand.Range(0.0f, 0.5f)) / 2;
originalpha = alphaPermanent;
alpha = alphaPermanent;
alphaCurrent = alphaPermanent;
@ -261,7 +258,7 @@ namespace RJW_Menstruation
HugsLibController.Instance.TickDelayScheduler.ScheduleCallback(action, TICKINTERVAL, parent.pawn);
}
public void Transition()
{
@ -284,7 +281,7 @@ namespace RJW_Menstruation
// Scenario B: Pregnant, grow in the second half of first trimester
else if (parent.pawn.IsPregnant())
{
float pregnancySize = Mathf.InverseLerp(BREAST_GROWTH_START, BREAST_GROWTH_END, parent.pawn.GetPregnancyProgress()) * MAX_BREAST_INCREMENT;
float pregnancySize = Mathf.InverseLerp(BREAST_GROWTH_START, BREAST_GROWTH_END, parent.pawn.GetFarthestPregnancyProgress()) * MAX_BREAST_INCREMENT;
if (breastSizeIncreased > pregnancySize)
{
debugGrowthStatus = "Shrinking due to being oversize for pregnancy";
@ -396,9 +393,9 @@ namespace RJW_Menstruation
{
return "Increase: " + breastSizeIncreased +
"\n" + debugGrowthStatus +
"\nAlpha: " + alpha +
"\nNippleSize: " + nippleSize +
"\nAreolaSize: " + areolaSize +
"\nAlpha: " + alpha +
"\nNippleSize: " + nippleSize +
"\nAreolaSize: " + areolaSize +
"\nAlphaCurrent: " + alphaCurrent +
"\nNippleSizeCurrent: " + nippleSizeCurrent +
"\nAreolaSizeCurrent: " + areolaSizeCurrent +
@ -408,7 +405,7 @@ namespace RJW_Menstruation
"\nAlphaMax: " + MaxAlpha +
"\nNippleSizeMax: " + MaxNipple +
"\nAreolaSizeMax: " + MaxAreola +
"\nPermanentAlpha:" + alphaPermanent +
"\nPermanentAlpha:" + alphaPermanent +
"\nPermanentNipple:" + nippleSizePermanent +
"\nPermanentAreola:" + areolaSizePermanent;
}

View file

@ -1,10 +1,4 @@
using HugsLib;
using RimWorld;
using rjw;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using RimWorld;
using Verse;
namespace RJW_Menstruation
@ -36,60 +30,33 @@ namespace RJW_Menstruation
}
}
protected override void FollicularAction()
// The maximum theoretical rate of ovulation is inducing the moment it goes follicular and no pregnancies
// There will be far more eggs than will ever actually be produced, but it fits the induced ovulator philosophy
protected override float RaceCyclesPerYear()
{
if (!IsBreedingSeason())
{
GoNextStage(Stage.Anestrus);
return;
}
if (curStageHrs >= FollicularIntervalHours)
{
estrusflag = false;
lutealIntervalhours = PeriodRandomizer(lutealIntervalhours, Props.deviationFactor);
GoNextStage(Stage.Luteal);
}
int breedingSeasons = 0;
if (Props.breedingSeason == SeasonalBreed.Always) breedingSeasons = 4;
else
{
curStageHrs += Configurations.CycleAcceleration;
if (!estrusflag && curStageHrs > FollicularIntervalHours - Props.estrusDaysBeforeOvulation * 24)
{
estrusflag = true;
SetEstrus(Props.eggLifespanDays + Props.estrusDaysBeforeOvulation);
}
StayCurrentStage();
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.lutealIntervalDays + Props.bleedingIntervalDays) / Configurations.CycleAccelerationDefault);
}
protected override void ClimactericFollicularAction()
// 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)
{
if (!Configurations.EnableMenopause)
{
RemoveClimactericEffect();
StayCurrentStage();
}
else if (curStageHrs >= (follicularIntervalhours - bleedingIntervalhours) * CycleFactor)
{
estrusflag = false;
lutealIntervalhours = PeriodRandomizer(lutealIntervalhours, Props.deviationFactor);
GoNextStage(Stage.ClimactericLuteal);
}
else if (ovarypower < OvaryPowerThreshold / 3 && Rand.Range(0.0f, 1.0f) < 0.2f) // Might randomly skip to luteal early)
{
estrusflag = false;
lutealIntervalhours = PeriodRandomizer(lutealIntervalhours, Props.deviationFactor * 6);
GoNextStage(Stage.ClimactericLuteal);
}
else
{
curStageHrs += Configurations.CycleAcceleration;
if (!estrusflag && curStageHrs > FollicularIntervalHours - Props.estrusDaysBeforeOvulation * 24)
{
estrusflag = true;
SetEstrus(Props.eggLifespanDays + Props.estrusDaysBeforeOvulation);
}
StayCurrentStage();
}
return 0;
}
protected override void GoOvulatoryStage(bool climacteric)
{
estrusflag = false;
GoNextStage(climacteric ? Stage.ClimactericLuteal : Stage.Luteal);
}
protected override void AfterCumIn(Pawn cummer)
@ -99,7 +66,7 @@ namespace RJW_Menstruation
{
case Stage.Follicular:
case Stage.ClimactericFollicular:
curStage = Stage.Ovulatory;
GoNextStage(Stage.Ovulatory);
break;
}
}

View file

@ -1,47 +1,65 @@
using System;
using RimWorld;
using rjw;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
using rjw;
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)
{
var hedifflist = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn))?.FindAll((Hediff h) => h.def.defName.ToLower().Contains("vagina"));
HediffComp_Menstruation result;
if (hedifflist.NullOrEmpty()) return null;
else
return pawn.GetFirstMenstruationComp();
}
public static IEnumerable<HediffComp_Menstruation> GetMenstruationComps(this Pawn pawn)
{
List<Hediff> hedifflist = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn))?.FindAll(h => VariousDefOf.AllVaginas.Contains(h.def));
if (hedifflist == null) yield break;
foreach (Hediff hediff in hedifflist)
{
foreach (Hediff h in hedifflist)
{
result = h.TryGetComp<HediffComp_Menstruation>();
if (result != null) return result;
}
HediffComp_Menstruation result = hediff.TryGetComp<HediffComp_Menstruation>();
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<HediffComp_Menstruation> comps = pawn.GetMenstruationComps().ToList();
return comps.Where(c => c.IsDangerDay).RandomElementWithFallback() ?? comps.RandomElementWithFallback();
}
public static HediffComp_Menstruation GetMenstruationComp(this Hediff vagina)
{
if (vagina is Hediff_PartBaseNatural || vagina is Hediff_PartBaseArtifical)
{
return vagina.TryGetComp<HediffComp_Menstruation>();
}
return null;
}
public static HediffComp_Menstruation GetMenstruationComp(this Hediff hediff)
public static HediffComp_Menstruation GetMenstruationComp(this Hediff_BasePregnancy pregnancy)
{
if (hediff is Hediff_PartBaseNatural || hediff is Hediff_PartBaseArtifical)
{
return hediff.TryGetComp<HediffComp_Menstruation>();
}
return null;
return pregnancy?.pawn.GetMenstruationComps().FirstOrDefault(comp => comp.Pregnancy == pregnancy);
}
public static HediffComp_Anus GetAnusComp(this Pawn pawn)
{
var hedifflist = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn))?.FindAll((Hediff h) => h.def.defName.ToLower().Contains("anus"));
List<Hediff> hedifflist = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn))?.FindAll((Hediff h) => h.def.defName.ToLower().Contains("anus"));
HediffComp_Anus result;
if (!hedifflist.NullOrEmpty())
{
@ -63,18 +81,11 @@ namespace RJW_Menstruation
return null;
}
public static float GetFertilityChance(this HediffComp_Menstruation comp)
{
return comp.TotalFertCum * Configurations.FertilizeChance * comp.Props.basefertilizationChanceFactor;
return 1.0f - Mathf.Pow(1.0f - Configurations.FertilizeChance, comp.TotalFertCum * comp.Props.basefertilizationChanceFactor);
}
public static HediffComp_Menstruation.Stage GetCurStage(this Pawn pawn)
{
return GetMenstruationComp(pawn)?.curStage ?? HediffComp_Menstruation.Stage.Bleeding;
}
public static Texture2D GetPregnancyIcon(this HediffComp_Menstruation comp, Hediff hediff)
{
string icon = "";
@ -157,19 +168,19 @@ namespace RJW_Menstruation
}
public static Texture2D GetEggIcon(this HediffComp_Menstruation comp, bool includeOvary)
{
if (comp.parent.pawn.IsPregnant(Configurations.InfoDetail != Configurations.DetailLevel.All) && !(PregnancyHelper.GetPregnancy(comp.parent.pawn) is Hediff_MechanoidPregnancy))
{
if (comp.parent.pawn.GetPregnancyProgress() < 0.2f) return ContentFinder<Texture2D>.Get("Eggs/Egg_Implanted00", true);
if (comp.Pregnancy != null && !(comp.Pregnancy is Hediff_MechanoidPregnancy))
{
if (comp.GetPregnancyProgress() < 0.2f) return ContentFinder<Texture2D>.Get("Eggs/Egg_Implanted00", true);
else return ContentFinder<Texture2D>.Get("Womb/Empty", true);
}
switch(comp.curStage)
switch (comp.curStage)
{
case HediffComp_Menstruation.Stage.Follicular:
case HediffComp_Menstruation.Stage.ClimactericFollicular:
if (!includeOvary) break;
if (comp is HediffComp_InducedOvulator) break;
if (comp.curStageHrs > comp.FollicularIntervalHours - 30) // Approximate time for ovulation to occur
if (comp.curStageHrs > comp.CurStageIntervalHours - 30) // Approximate time for ovulation to occur
return ContentFinder<Texture2D>.Get("Ovaries/Ovary_01", true);
else break;
case HediffComp_Menstruation.Stage.Ovulatory:
@ -209,7 +220,7 @@ namespace RJW_Menstruation
public static Texture2D GetGenitalIcon(this Pawn pawn, HediffComp_Menstruation comp, bool drawOrigin = false)
{
var hediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn))?.Find((Hediff h) => h.def.defName.ToLower().Contains("vagina"));
Hediff hediff = comp?.parent;
if (hediff == null) return ContentFinder<Texture2D>.Get("Genitals/Vagina00", true);
//HediffComp_Menstruation comp = hediff.GetMenstruationComp();
string icon;
@ -237,37 +248,32 @@ namespace RJW_Menstruation
public static Texture2D GetAnalIcon(this Pawn pawn, bool drawOrigin = false)
{
var hediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_anusBPR(pawn)).FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("anus"));
if (hediff != null)
{
string icon;
float severity;
HediffComp_Anus comp = hediff.GetAnusComp();
if (comp != null)
{
CompProperties_Anus Props = (CompProperties_Anus)comp.props;
icon = Props.analTex ?? "Genitals/Anal";
if (drawOrigin) severity = comp.OriginAnusSize;
else severity = hediff.Severity;
}
else
{
icon = "Genitals/Anal";
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
Hediff hediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_anusBPR(pawn)).FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("anus"));
if (hediff == null) return ContentFinder<Texture2D>.Get(("Genitals/Anal00"), true);
return ContentFinder<Texture2D>.Get((icon), true);
string icon;
float severity;
HediffComp_Anus comp = hediff.GetAnusComp();
if (comp != null)
{
CompProperties_Anus Props = (CompProperties_Anus)comp.props;
icon = Props.analTex ?? "Genitals/Anal";
if (drawOrigin) severity = comp.OriginAnusSize;
else severity = hediff.Severity;
}
else
{
return ContentFinder<Texture2D>.Get(("Genitals/Anal00"), true);
icon = "Genitals/Anal";
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<Texture2D>.Get((icon), true);
}
public static float GestationHours(this Hediff_BasePregnancy hediff)
@ -280,6 +286,21 @@ namespace RJW_Menstruation
else return (hediff.p_end_tick - hediff.p_start_tick) / GenDate.TicksPerHour;
}
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 IsInEstrus(this Pawn pawn, bool visible = true)
{
if (pawn.Dead) return false;

View file

@ -17,21 +17,26 @@ namespace RJW_Menstruation
protected void PregnancyThought()
{
if (!is_discovered && xxx.is_human(pawn))
if (is_discovered ||
!xxx.is_human(pawn) ||
pawn.Has(Quirk.Breeder) ||
(pawn.relations?.DirectRelations?.Find(x => x.def.Equals(PawnRelationDefOf.Spouse) ||
x.def.Equals(PawnRelationDefOf.Fiance))) != null)
return;
if (pawn.Has(Quirk.ImpregnationFetish) || pawn.relations?.DirectRelations?.Find(x => x.def.Equals(PawnRelationDefOf.Lover)) != null)
{
if (!pawn.Has(Quirk.Breeder) && pawn.relations?.DirectRelations?.Find(x => x.def.Equals(PawnRelationDefOf.Spouse) || x.def.Equals(PawnRelationDefOf.Fiance)) == null)
{
if (pawn.Has(Quirk.ImpregnationFetish) || pawn.relations?.DirectRelations?.Find(x => x.def.Equals(PawnRelationDefOf.Lover)) != null)
{
pawn.needs.mood.thoughts.memories.TryGainMemory(VariousDefOf.UnwantedPregnancyMild);
}
else
{
pawn.needs.mood.thoughts.memories.TryGainMemory(VariousDefOf.UnwantedPregnancy);
}
}
pawn.needs.mood.thoughts.memories.TryGainMemory(VariousDefOf.UnwantedPregnancyMild);
}
else
{
pawn.needs.mood.thoughts.memories.TryGainMemory(VariousDefOf.UnwantedPregnancy);
}
}
public override void Miscarry()
{
this.GetMenstruationComp().Pregnancy = null;
base.Miscarry();
}
public override void GiveBirth()
@ -47,42 +52,43 @@ namespace RJW_Menstruation
Initialize(pawn, father);
}
List<Pawn> siblings = new List<Pawn>();
foreach (Pawn baby in babies)
{
if (xxx.is_animal(baby))
{
BestialBirth(baby, siblings);
BestialBirth(baby);
}
else
{
HumanlikeBirth(baby, siblings);
HumanlikeBirth(baby);
}
baby.ageTracker.AgeChronologicalTicks = 0;
}
pawn.health.RemoveHediff(this);
HediffComp_Menstruation comp = this.GetMenstruationComp();
if(comp != null) comp.Pregnancy = null;
}
public string GetBabyInfo()
{
if (babies.NullOrEmpty())
return "Null";
string res = "";
if (!babies.NullOrEmpty())
IEnumerable<Pawn> babiesdistinct = babies.Distinct(new RaceComparer());
int iteration = 0;
foreach (Pawn baby in babiesdistinct)
{
var babiesdistinct = babies.Distinct(new RaceComparer());
int iteration = 0;
foreach (Pawn baby in babiesdistinct)
{
int num = babies.Where(x => x.def.Equals(baby.def)).Count();
if (iteration > 0) res += ", ";
res += num + " " + baby.def.label;
iteration++;
}
res += " " + Translations.Dialog_WombInfo02;
return res;
int num = babies.Where(x => x.def.Equals(baby.def)).Count();
if (iteration > 0) res += ", ";
res += num + " " + baby.def.label;
iteration++;
}
return "Null";
res += " " + Translations.Dialog_WombInfo02;
return res;
}
public string GetFatherInfo()
@ -95,7 +101,7 @@ namespace RJW_Menstruation
if (!is_parent_known && Configurations.InfoDetail != Configurations.DetailLevel.All)
return res + Translations.Dialog_FatherUnknown;
var babiesdistinct = babies.Distinct(new FatherComparer(pawn));
IEnumerable<Pawn> babiesdistinct = babies.Distinct(new FatherComparer(pawn));
int iteration = 0;
foreach (Pawn baby in babiesdistinct)
{
@ -106,7 +112,7 @@ namespace RJW_Menstruation
return res;
}
private void HumanlikeBirth(Pawn baby, List<Pawn> siblings)
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
@ -115,7 +121,7 @@ namespace RJW_Menstruation
PawnUtility.TrySpawnHatchedOrBornPawn(baby, mother);
var sex_need = mother.needs?.TryGetNeed<Need_Sex>();
Need_Sex sex_need = mother.needs?.TryGetNeed<Need_Sex>();
if (mother.Faction != null && !(mother.Faction?.IsPlayer ?? false) && sex_need != null)
{
sex_need.CurLevel = 1.0f;
@ -144,17 +150,13 @@ namespace RJW_Menstruation
baby.guest.SetGuestStatus(Faction.OfPlayer, GuestStatus.Prisoner);
}
foreach (Pawn sibling in siblings)
{
baby.relations.AddDirectRelation(PawnRelationDefOf.Sibling, sibling);
}
siblings.Add(baby);
if (xxx.is_human(mother)) TaleRecorder.RecordTale(TaleDefOf.GaveBirth, new object[] { mother, baby });
PostBirth(mother, father, baby);
}
private void BestialBirth(Pawn baby, List<Pawn> siblings)
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
@ -174,14 +176,6 @@ namespace RJW_Menstruation
baby.SetFaction(mother.Faction);
}
if (!RJWSettings.Disable_bestiality_pregnancy_relations)
{
foreach (Pawn sibling in siblings)
{
baby.relations.AddDirectRelation(PawnRelationDefOf.Sibling, sibling);
}
siblings.Add(baby);
}
Train(baby, mother);
PostBirth(mother, father, baby);
@ -198,7 +192,6 @@ namespace RJW_Menstruation
List<Trait> momtraits = new List<Trait>();
List<Trait> poptraits = new List<Trait>();
List<Trait> traits_to_inherit = new List<Trait>();
System.Random rd = new System.Random();
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;
@ -226,7 +219,7 @@ namespace RJW_Menstruation
i = 1;
while (momtraits.Count > 0 && i <= max_num_momtraits_inherited)
{
rand_trait_index = rd.Next(0, momtraits.Count);
rand_trait_index = Rand.Range(0, momtraits.Count);
traits_to_inherit.Add(momtraits[rand_trait_index]);
momtraits.RemoveAt(rand_trait_index);
}
@ -236,7 +229,7 @@ namespace RJW_Menstruation
j = 1;
while (poptraits.Count > 0 && j <= max_num_poptraits_inherited)
{
rand_trait_index = rd.Next(0, poptraits.Count);
rand_trait_index = Rand.Range(0, poptraits.Count);
traits_to_inherit.Add(poptraits[rand_trait_index]);
poptraits.RemoveAt(rand_trait_index);
}
@ -257,7 +250,7 @@ namespace RJW_Menstruation
{
while (poptraits != null && momtraits.Count() > 0 && i <= max_num_momtraits_inherited)
{
rand_trait_index = rd.Next(0, momtraits.Count);
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]);
@ -269,7 +262,7 @@ namespace RJW_Menstruation
{
while (poptraits.Count > 0 && i < max_num_poptraits_inherited)
{
rand_trait_index = rd.Next(0, poptraits.Count);
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]);
@ -295,16 +288,15 @@ namespace RJW_Menstruation
protected void Train(Pawn baby, Pawn mother)
{
if (!xxx.is_human(baby) && baby.Faction == Faction.OfPlayer)
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)
{
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);
}
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);
}
}
@ -352,7 +344,7 @@ namespace RJW_Menstruation
kind: BabyPawnKindDecider(mother, father),
//fixedIdeo: mother.Ideo,
//forbidAnyTitle: true,
forceNoBackstory:true
forceNoBackstory: true
);
int division = 1;
@ -363,7 +355,7 @@ namespace RJW_Menstruation
string firstheadpath = null;
string firstHARcrown = null;
int traitSeed = Rand.Int;
List <Trait> parentTraits = GetInheritableTraits(mother, father);
List<Trait> parentTraits = GetInheritableTraits(mother, father);
while (Rand.Chance(Configurations.EnzygoticTwinsChance) && division < Configurations.MaxEnzygoticTwins) division++;
for (int i = 0; i < division; i++)
{
@ -421,30 +413,28 @@ namespace RJW_Menstruation
public Pawn GenerateBaby(PawnGenerationRequest request, Pawn mother, Pawn father, List<Trait> parentTraits, int traitSeed)
{
Pawn baby = PawnGenerator.GeneratePawn(request);
if (baby != null)
if (baby == null)
{
if (xxx.is_human(baby) || (baby.relations != null && !RJWSettings.Disable_bestiality_pregnancy_relations))
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)
{
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();
if (father.gender != Gender.Female) baby.SetFather(father);
else baby.relations.AddDirectRelation(PawnRelationDefOf.Parent, father);
}
}
else Log.Error("Baby not generated. Request: " + request.ToString());
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;
}
@ -457,7 +447,10 @@ namespace RJW_Menstruation
/// <returns></returns>
public PawnKindDef BabyPawnKindDecider(Pawn mother, Pawn father)
{
PawnKindDef spawn_kind_def = mother.kindDef;
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;
@ -471,18 +464,18 @@ namespace RJW_Menstruation
switch (flag)
{
case 3:
if (!Rand.Chance(RJWPregnancySettings.humanlike_DNA_from_mother)) spawn_kind_def = father.kindDef;
if (!Rand.Chance(RJWPregnancySettings.humanlike_DNA_from_mother)) spawn_kind_def = fatherKindDef;
break;
case 2:
if (RJWPregnancySettings.bestiality_DNA_inheritance == 0f) spawn_kind_def = father.kindDef;
else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = father.kindDef;
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 = father.kindDef;
else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = father.kindDef;
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 = father.kindDef;
if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
break;
}
@ -490,19 +483,19 @@ namespace RJW_Menstruation
bool IsAndroidfather = AndroidsCompatibility.IsAndroid(father);
if (IsAndroidmother && !IsAndroidfather)
{
spawn_kind_def = father.kindDef;
spawn_kind_def = fatherKindDef;
}
else if (!IsAndroidmother && IsAndroidfather)
{
spawn_kind_def = mother.kindDef;
spawn_kind_def = motherKindDef;
}
string MotherRaceName = "";
string FatherRaceName = "";
MotherRaceName = mother.kindDef?.race?.defName;
MotherRaceName = motherKindDef?.race?.defName;
PawnKindDef non_hybrid_kind_def = spawn_kind_def;
if (father != null)
FatherRaceName = father.kindDef?.race?.defName;
FatherRaceName = fatherKindDef?.race?.defName;
if (FatherRaceName != "" && Configurations.UseHybridExtention)
@ -516,24 +509,24 @@ namespace RJW_Menstruation
if (!Configurations.UseHybridExtention || spawn_kind_def == null)
{
spawn_kind_def = non_hybrid_kind_def;
var groups = DefDatabase<RaceGroupDef>.AllDefs.Where(x => !(x.hybridRaceParents.NullOrEmpty() || x.hybridChildKindDef.NullOrEmpty()));
IEnumerable<RaceGroupDef> groups = DefDatabase<RaceGroupDef>.AllDefs.Where(x => !(x.hybridRaceParents.NullOrEmpty() || x.hybridChildKindDef.NullOrEmpty()));
//ModLog.Message(" found custom RaceGroupDefs " + groups.Count());
foreach (var t in groups)
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 = mother.kindDef;
spawn_kind_def = motherKindDef;
else if (t.hybridChildKindDef.Contains("FatherKindDef") && father != null)
spawn_kind_def = father.kindDef;
spawn_kind_def = fatherKindDef;
else
{
//ModLog.Message(" trying hybridChildKindDef " + t.defName);
var child_kind_def_list = new List<PawnKindDef>();
List<PawnKindDef> child_kind_def_list = new List<PawnKindDef>();
child_kind_def_list.AddRange(DefDatabase<PawnKindDef>.AllDefs.Where(x => t.hybridChildKindDef.Contains(x.defName)));
//ModLog.Message(" found custom hybridChildKindDefs " + t.hybridChildKindDef.Count);
@ -547,20 +540,20 @@ namespace RJW_Menstruation
}
else if (!Configurations.UseHybridExtention || spawn_kind_def == null)
{
spawn_kind_def = mother.RaceProps?.AnyPawnKind ?? mother.kindDef;
spawn_kind_def = mother.RaceProps?.AnyPawnKind ?? motherKindDef;
}
if (spawn_kind_def.defName.Contains("Nymph"))
{
//child is nymph, try to find other PawnKindDef
var spawn_kind_def_list = new List<PawnKindDef>();
List<PawnKindDef> spawn_kind_def_list = new List<PawnKindDef>();
spawn_kind_def_list.AddRange(DefDatabase<PawnKindDef>.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<PawnKindDef>.AllDefs.Where(x => x.race == mother.kindDef.race && !x.defName.Contains("Nymph")));
spawn_kind_def_list.AddRange(DefDatabase<PawnKindDef>.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<PawnKindDef>.AllDefs.Where(x => x.race == father.kindDef.race && !x.defName.Contains("Nymph")));
spawn_kind_def_list.AddRange(DefDatabase<PawnKindDef>.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;
@ -568,9 +561,6 @@ namespace RJW_Menstruation
if (!spawn_kind_def_list.NullOrEmpty()) spawn_kind_def = spawn_kind_def_list.RandomElement();
}
return spawn_kind_def;
}
@ -638,17 +628,17 @@ namespace RJW_Menstruation
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
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.
var forcedTraits = personalTraitPool
IEnumerable<Trait> 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<Trait> selectedTraits = new List<Trait>();
var comparer = new TraitComparer(); // trait comparision implementation, because without game compares traits *by reference*, makeing them all unique.
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
{
@ -663,13 +653,13 @@ namespace RJW_Menstruation
while (selectedTraits.Count < traitLimit && personalTraitPool.Count > 0)
{
int index = Rand.Range(0, personalTraitPool.Count); // getting trait and removing from the pull
var trait = personalTraitPool[index];
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;

View file

@ -1,24 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using RimWorld;
using Verse;
using rjw;
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(pawn, toleranceChemical, ref effect);
hediff.Severity = effect;
pawn.health.AddHediff(hediff);
}
{
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(pawn, toleranceChemical, ref effect);
hediff.Severity = effect;
pawn.health.AddHediff(hediff);
}
}

View file

@ -1,5 +1,6 @@
using System.Collections.Generic;
using RimWorld;
using RimWorld;
using System.Collections.Generic;
using System.Linq;
using Verse;
using Verse.AI;
@ -16,11 +17,10 @@ namespace RJW_Menstruation
protected override IEnumerable<Toil> MakeNewToils()
{
HediffComp_Menstruation Comp = pawn.GetMenstruationComp();
List<HediffComp_Menstruation> comps = pawn.GetMenstruationComps().ToList();
this.FailOn(delegate
{
return !(Comp.TotalCumPercent > 0.001);
return comps.All(comp => comp.TotalCumPercent < 0.001);
});
Toil excreting = Toils_General.Wait(excretingTime, TargetIndex.None);//duration of
@ -30,8 +30,9 @@ namespace RJW_Menstruation
{
initAction = delegate ()
{
Comp.CumOut(null, 0.5f);
if (Comp.TotalCumPercent > 0.001) JumpToToil(excreting);
foreach (HediffComp_Menstruation comp in comps)
comp.CumOut(null, 0.5f);
if (comps.Any(comp => comp.TotalCumPercent > 0.001)) JumpToToil(excreting);
}
};
//yield return excreting;
@ -107,7 +108,7 @@ namespace RJW_Menstruation
protected virtual void Finish()
{
if(pawn.CurJobDef == JobDefOf.Wait_MaintainPosture)
if (pawn.CurJobDef == JobDefOf.Wait_MaintainPosture)
{
pawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
}

View file

@ -1,9 +1,9 @@
using System.Collections.Generic;
using System.Linq;
using HarmonyLib;
using Verse;
using HarmonyLib;
using RimWorld;
using RimWorld.Planet;
using System.Collections.Generic;
using System.Linq;
using Verse;
namespace RJW_Menstruation.Patch
{
@ -26,12 +26,11 @@ namespace RJW_Menstruation.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(Pawn p in PawnsFinder.All_AliveOrDead)
foreach (Pawn p in PawnsFinder.AllMapsCaravansAndTravelingTransportPods_Alive_OfPlayerFaction.Union(PawnsFinder.AllMapsCaravansAndTravelingTransportPods_Alive_PrisonersOfColony))
{
HediffComp_Menstruation comp = p.GetMenstruationComp();
if (comp is null) continue;
GetCriticalPawnReason_Patch.cummedPawns.UnionWith(comp.GetCummersAndFertilizers());
foreach (HediffComp_Menstruation comp in p.GetMenstruationComps())
GetCriticalPawnReason_Patch.cummedPawns.UnionWith(comp.GetCummersAndFertilizers());
}
}
}

View file

@ -28,11 +28,9 @@ namespace RJW_Menstruation
foreach (Gizmo gizmo in gizmos)
yield return gizmo;
HediffComp_Menstruation comp = __instance.GetMenstruationComp();
if (comp == null) yield break;
foreach (Gizmo gizmo in GetMenstruationGizmos(__instance, comp))
yield return gizmo;
foreach (HediffComp_Menstruation comp in __instance.GetMenstruationComps())
foreach (Gizmo gizmo in GetMenstruationGizmos(__instance, comp))
yield return gizmo;
}
public static List<Gizmo> GetMenstruationGizmos(Pawn pawn, HediffComp_Menstruation comp)
@ -49,8 +47,8 @@ namespace RJW_Menstruation
else description += comp.GetCurStageLabel + "\n";
if (pawn.IsPregnant())
{
Hediff hediff = PregnancyHelper.GetPregnancy(pawn);
if (Utility.ShowFetusImage((Hediff_BasePregnancy)hediff))
Hediff_BasePregnancy hediff = comp.Pregnancy;
if (Utility.ShowFetusImage(hediff))
{
icon = comp.GetPregnancyIcon(hediff);
if (hediff is Hediff_BasePregnancy h)
@ -100,7 +98,7 @@ namespace RJW_Menstruation
Dialog_WombStatus.ToggleWindow(pawn, comp);
}
};
return gizmo;
}

View file

@ -14,14 +14,14 @@ namespace RJW_Menstruation
{
static First()
{
var har = new Harmony("RJW_Menstruation");
Harmony har = new Harmony("RJW_Menstruation");
har.PatchAll(Assembly.GetExecutingAssembly());
InjectIntoRjwInteractionServices();
}
private static void InjectIntoRjwInteractionServices()
{
var log = LogManager.GetLogger("StaticConstructorOnStartup");
ILog log = LogManager.GetLogger("StaticConstructorOnStartup");
List<IPartPreferenceRule> partKindUsageRules = Unprivater.GetProtectedValue<List<IPartPreferenceRule>>("_partKindUsageRules", typeof(PartPreferenceDetectorService));
partKindUsageRules.Add(new Interactions.EstrusPartKindUsageRule());

View file

@ -2,10 +2,8 @@
using HugsLib;
using RimWorld;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Verse;
using rjw;
namespace RJW_Menstruation
{
@ -16,20 +14,18 @@ namespace RJW_Menstruation
public static void Postfix(Pawn __instance)
{
//Log.Message("Initialize on spawnsetup");
HediffComp_Menstruation comp = __instance.GetMenstruationComp();
if (comp != null)
foreach (HediffComp_Menstruation comp in __instance.GetMenstruationComps())
{
HugsLibController.Instance.TickDelayScheduler.TryUnscheduleCallback(comp.actionref);
comp.Initialize();
}
HediffComp_Breast bcomp = __instance.GetBreastComp();
if (bcomp != null)
{
HugsLibController.Instance.TickDelayScheduler.TryUnscheduleCallback(bcomp.action);
bcomp.Initialize();
}
}
}
@ -38,7 +34,7 @@ namespace RJW_Menstruation
{
public static void Postfix(Vector3 clickPos, Pawn pawn, List<FloatMenuOption> opts)
{
var selftargets = GenUI.TargetsAt(clickPos, TargetingParameters.ForSelf(pawn));
IEnumerable<LocalTargetInfo> selftargets = GenUI.TargetsAt(clickPos, TargetingParameters.ForSelf(pawn));
foreach (LocalTargetInfo t in selftargets)
{

View file

@ -2,12 +2,12 @@
using rjw;
using rjw.Modules.Interactions.Enums;
using rjw.Modules.Interactions.Objects;
using Verse;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using UnityEngine;
using Verse;
namespace RJW_Menstruation
{
@ -15,22 +15,28 @@ namespace RJW_Menstruation
[HarmonyPatch(typeof(PregnancyHelper), nameof(PregnancyHelper.impregnate))]
public static class Impregnate_Patch
{
public static bool Prefix(SexProps props)
public static bool Prefix(SexProps props, out HediffComp_Menstruation __state)
{
xxx.rjwSextype sextype = props.sexType;
Pawn pawn = props.pawn;
Pawn partner = props.partner;
if (PregnancyHelper.GetPregnancy(partner) is Hediff_BasePregnancy oldestPregnancy) __state = oldestPregnancy.GetMenstruationComp();
else __state = null;
if (sextype != xxx.rjwSextype.Vaginal && sextype != xxx.rjwSextype.DoublePenetration) return true;
if (partner.IsAnimal() && !Configurations.EnableAnimalCycle) return true;
if (!InteractionCanCausePregnancy(props)) return false;
var pawnparts = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn));
List<Hediff> pawnparts = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn));
HediffComp_Menstruation comp = partner.GetMenstruationComp();
if (comp is null) return true;
HediffComp_Menstruation comp;
if (pawn.Has(Quirk.ImpregnationFetish) || partner.Has(Quirk.ImpregnationFetish) || 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))
{
@ -44,8 +50,18 @@ namespace RJW_Menstruation
else comp.CumIn(pawn, pawn.GetCumVolume(pawnparts), 0);
return true;
}
public static void Postfix(SexProps props, HediffComp_Menstruation __state)
{
if (__state == null || __state.Pregnancy != null) return;
// It was pregnant, but not anymore. This probably means the pregnancy was destroyed by e.g. a mech implant
Pawn pawn = props.partner;
Hediff_BasePregnancy newestPregnancy = pawn.health.hediffSet.GetHediffs<Hediff_BasePregnancy>().MaxBy(hediff => hediff.loadID);
if (newestPregnancy == null) return;
if (pawn.GetMenstruationComps().Any(comp => comp.Pregnancy == newestPregnancy)) return; // One of the wombs did get it
else __state.Pregnancy = newestPregnancy;
}
/// <summary>
@ -85,31 +101,59 @@ namespace RJW_Menstruation
public static bool Prefix(Pawn pawn, Pawn partner) // partner has vagina
{
if (partner.IsAnimal() && !Configurations.EnableAnimalCycle) return true;
HediffComp_Menstruation comp = partner.GetMenstruationComp();
if (comp != null)
HediffComp_Menstruation comp;
if (pawn.Has(Quirk.ImpregnationFetish) || partner.Has(Quirk.ImpregnationFetish) || partner.IsInEstrus())
comp = partner.GetFertileMenstruationComp();
else comp = partner.GetRandomMenstruationComp();
if (comp == null)
{
if (AndroidsCompatibility.IsAndroid(pawn) && !AndroidsCompatibility.AndroidPenisFertility(pawn))
{
comp.CumIn(pawn, pawn.GetCumVolume(), 0);
return false;
}
else comp.CumIn(pawn, pawn.GetCumVolume(), pawn.health.capacities.GetLevel(xxx.reproduction));
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;
}
ModLog.Message("used original rjw method: Comp missing");
return true;
else comp.CumIn(pawn, pawn.GetCumVolume(), 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 (!Configurations.EnableAnimalCycle && pawn.IsAnimal()) 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<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
if (IsPregnant == null) 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(Pawn mother, Pawn baby)
public static void Postfix(Hediff_BasePregnancy __instance, Pawn mother, Pawn baby)
{
if (Configurations.EnableBirthVaginaMorph)
{
Hediff vagina = mother.health.hediffSet.hediffs.FirstOrFallback(x => x.def.defName.ToLower().Contains("vagina"));
float morph = Mathf.Max(baby.BodySize - Mathf.Pow(vagina.Severity * mother.BodySize,2), 0f);
// The comp still has the pregnancy attached at this point in the process
Hediff vagina = __instance.GetMenstruationComp()?.parent;
if (vagina == null) vagina = 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;
}
}
@ -123,9 +167,9 @@ namespace RJW_Menstruation
// 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.GetMenstruationComp()?.IsDangerDay ?? true))
(PregnancyHelper.CanImpregnate(pawn, partner) && (partner.GetMenstruationComps()?.Any(comp => comp.IsDangerDay) ?? true))
||
(PregnancyHelper.CanImpregnate(partner, pawn) && (pawn.GetMenstruationComp()?.IsDangerDay ?? true)));
(PregnancyHelper.CanImpregnate(partner, pawn) && (pawn.GetMenstruationComps()?.Any(comp => comp.IsDangerDay) ?? true));
}
}
@ -144,9 +188,9 @@ namespace RJW_Menstruation
else __result--;
if (
(PregnancyHelper.CanImpregnate(pawn, partner, props.sexType) && (partner.GetMenstruationComp()?.IsDangerDay ?? true))
(PregnancyHelper.CanImpregnate(pawn, partner, props.sexType) && (partner.GetMenstruationComps()?.Any(comp => comp.IsDangerDay) ?? true))
||
(PregnancyHelper.CanImpregnate(partner, pawn, props.sexType) && (pawn.GetMenstruationComp()?.IsDangerDay ?? true)))
(PregnancyHelper.CanImpregnate(partner, pawn, props.sexType) && (pawn.GetMenstruationComps()?.Any(comp => comp.IsDangerDay) ?? true)))
__result++;
}
}
@ -176,7 +220,7 @@ namespace RJW_Menstruation
{
__result *= (1f + GetNetFertility(fucker, fucked) / 40);
}
else if(xxx.is_animal(fucker) && fucked.IsInEstrus(true) && PregnancyHelper.CanImpregnate(fucker, fucked))
else if (xxx.is_animal(fucker) && fucked.IsInEstrus(true) && PregnancyHelper.CanImpregnate(fucker, fucked))
{
__result *= 1.25f;
}
@ -195,10 +239,11 @@ namespace RJW_Menstruation
private static readonly FieldInfo MinimumFuckabilityToHookup = AccessTools.Field(typeof(RJWHookupSettings), nameof(RJWHookupSettings.MinimumFuckabilityToHookup));
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
if (MinimumFuckabilityToHookup == null) throw new System.InvalidOperationException("MinimumFuckabilityToHookup not found");
bool first_fuckability = true;
foreach(CodeInstruction instruction in instructions)
foreach (CodeInstruction instruction in instructions)
{
if(instruction.LoadsField(MinimumFuckabilityToHookup))
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);
@ -230,14 +275,16 @@ namespace RJW_Menstruation
private static readonly FieldInfo MinimumRelationshipToHookup = AccessTools.Field(typeof(RJWHookupSettings), nameof(RJWHookupSettings.MinimumRelationshipToHookup));
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
if (MinimumAttractivenessToHookup == null) throw new System.InvalidOperationException("MinimumAttractivenessToHookup not found");
if (MinimumRelationshipToHookup == null) 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)
foreach (CodeInstruction instruction in instructions)
{
// Get where the compiler decided to index the pawn at
if (pawn_index is null && instruction.opcode == OpCodes.Stloc_S) // the first stloc.s in the IL is the pawn being loaded out of the list
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;
@ -252,7 +299,7 @@ namespace RJW_Menstruation
yield return CodeInstruction.Call(typeof(FindBestPartner_Patch), nameof(AttractivenessThreshold));
first_attractiveness = false;
}
}
else if (instruction.LoadsField(MinimumRelationshipToHookup))
{
if (pawn_index?.LocalType != typeof(Pawn))
@ -269,6 +316,21 @@ namespace RJW_Menstruation
}
}
[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(CompHediffBodyPart), nameof(CompHediffBodyPart.updatesize))]
public static class Updatesize_Patch
{

View file

@ -101,6 +101,7 @@
<HintPath>..\..\..\..\..\rjw\1.3\Assemblies\RJW.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="UnityEngine">
<HintPath>..\..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.dll</HintPath>
@ -158,7 +159,7 @@
<ItemGroup>
<PackageReference Include="Lib.Harmony">
<Version>2.1.1</Version>
<ExcludeAssets>runtime</ExcludeAssets>
<ExcludeAssets>runtime</ExcludeAssets>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View file

@ -1,11 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
using RimWorld;
using rjw;
using System.Collections.Generic;
using Verse;
namespace RJW_Menstruation
@ -23,7 +19,7 @@ namespace RJW_Menstruation
BodyPartRecord part = Genital_Helper.get_breastsBPR(pawn);
if (part != null)
{
if (pawn.GetBreastComp() != null) yield return part;
}
}

View file

@ -22,14 +22,14 @@ namespace RJW_Menstruation
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);
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);
PropertyInfo propertyInfo = obj?.GetType().GetProperty(name, flags);
return propertyInfo?.GetValue(obj);
}

View file

@ -1,11 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using UnityEngine;
using Verse;
using UnityEngine;
namespace RJW_Menstruation
{

View file

@ -1,8 +1,7 @@
using System;
using System.Xml;
using System.Collections.Generic;
using RimWorld;
using RimWorld;
using rjw;
using System.Collections.Generic;
using System.Xml;
using UnityEngine;
using Verse;
@ -20,10 +19,7 @@ namespace RJW_Menstruation
public HybridExtension GetHybridExtension(string race)
{
if (hybridExtension.NullOrEmpty()) return null;
else
{
return hybridExtension.Find(x => x.thingDef.defName.Equals(race));
}
else return hybridExtension.Find(x => x.thingDef.defName.Equals(race));
}
public PawnKindDef GetHybridWith(string race)
@ -67,21 +63,15 @@ namespace RJW_Menstruation
{
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
#if DEBUG
Log.Message(xmlRoot.Name + "HybridInfo: " + node.Name + " " + node.InnerText);
#endif
hybridInfo.Add(node.Name, ParseHelper.FromString<float>(node.InnerText));
}
}
}
public class HybridInformations : IExposable
@ -145,9 +135,6 @@ namespace RJW_Menstruation
Scribe_Values.Look(ref thingDefName, "thingDefName");
Scribe_Collections.Look(ref hybridExtension, "hybridExtension", LookMode.Deep, new object[0]);
}
}
public class HybridExtensionExposable : HybridExtension, IExposable
@ -197,10 +184,6 @@ namespace RJW_Menstruation
}
}
public class AbsorberModExtension : DefModExtension
{
public bool leakAfterDirty = false;
@ -222,14 +205,12 @@ namespace RJW_Menstruation
public Color fluidColor = Color.white;
public virtual void DirtyEffect() { }
public virtual void WearEffect()
{
absorbedfluids += 0.1f;
if(dirty) wearhours++;
if (dirty) wearhours++;
}
public override Color DrawColorTwo => fluidColor;
@ -250,7 +231,7 @@ namespace RJW_Menstruation
public override void WearEffect()
{
if(dirty) wearhours++;
if (dirty) wearhours++;
absorbedfluids += 0.5f;
}
@ -299,13 +280,5 @@ namespace RJW_Menstruation
color = value;
}
}
}
}

View file

@ -11,7 +11,6 @@ namespace RJW_Menstruation
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_Fertilized = "Stage_Fertilized".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();
@ -100,23 +99,23 @@ namespace RJW_Menstruation
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 Option24_Label = "Option24_Label".Translate();
public static readonly string Option24_Desc = "Option24_Desc".Translate();
public static readonly string Option24_Desc = "Option24_Desc".Translate();
public static readonly string Option25_Label = "Option25_Label".Translate();
public static readonly string Option25_Desc = "Option25_Desc".Translate();
public static readonly string Option25_Desc = "Option25_Desc".Translate();
public static readonly string Option26_Label = "Option26_Label".Translate();
public static readonly string Option26_Desc = "Option26_Desc".Translate();
public static readonly string Option26_Desc = "Option26_Desc".Translate();
public static readonly string Option27_Label = "Option27_Label".Translate();
public static readonly string Option27_Desc = "Option27_Desc".Translate();
public static readonly string Option27_Desc = "Option27_Desc".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 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 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 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 Option32_Desc = "Option32_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();

View file

@ -1,10 +1,7 @@
using System;
using RimWorld;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using rjw;
using UnityEngine;
using Verse;
using Verse.Sound;
@ -26,17 +23,11 @@ namespace RJW_Menstruation
public void BuildRaceList()
{
raceList.Clear();
if (!VariousDefOf.AllRaces.NullOrEmpty())
foreach(ThingDef def in VariousDefOf.AllRaces)
if (!VariousDefOf.AllRaces.NullOrEmpty())
foreach (ThingDef def in VariousDefOf.AllRaces)
{
if (def.race != null)
{
if (Configurations.IsOverrideExist(def)) continue;
else
{
raceList.Add(new FloatMenuOption(def.label, delegate { AddHybridOverride(def);}, def.uiIcon, Color.white ));
}
}
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);
}
@ -44,17 +35,15 @@ namespace RJW_Menstruation
public void AddHybridOverride(ThingDef def)
{
FloatMenuOption option = raceList.FirstOrDefault(x => x.Label.Equals(def?.label));
if (option != null)
if (option == null) return;
raceList.Remove(option);
if (Configurations.HybridOverride.NullOrEmpty())
{
raceList.Remove(option);
if (Configurations.HybridOverride.NullOrEmpty())
{
Configurations.HybridOverride = new List<HybridInformations>();
}
Configurations.HybridOverride.Add(new HybridInformations(def));
Configurations.HybridOverride.SortBy(x => x.GetDef?.label ?? "Undefined");
Configurations.HybridOverride = new List<HybridInformations>();
}
Configurations.HybridOverride.Add(new HybridInformations(def));
Configurations.HybridOverride.SortBy(x => x.GetDef?.label ?? "Undefined");
}
public override Vector2 InitialSize
@ -124,7 +113,7 @@ namespace RJW_Menstruation
buttonRect.x -= 100;
if (Widgets.ButtonText(buttonRect, "Undo"))
{
var element = removeList.Last();
HybridInformations element = removeList.Last();
Configurations.HybridOverride.Add(element);
Configurations.HybridOverride.SortBy(x => x.GetDef?.label ?? "Undefined");
removeList.Remove(element);
@ -138,17 +127,17 @@ namespace RJW_Menstruation
}
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));
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 (!Configurations.HybridOverride.NullOrEmpty())
foreach (HybridInformations extension in Configurations.HybridOverride)
{
if (extension.GetDef != null) DoRow(listmain.GetRect(24f),extension);
if (extension.GetDef != null) DoRow(listmain.GetRect(24f), extension);
}
Widgets.EndScrollView();
listmain.End();
@ -266,7 +255,7 @@ namespace RJW_Menstruation
SoundDefOf.TabClose.PlayOneShotOnCamera();
Find.WindowStack.Add(new Dialog_EditHybrid(info));
}
}
@ -279,18 +268,19 @@ namespace RJW_Menstruation
protected void BuildRaceList()
{
raceList.Clear();
if (!VariousDefOf.AllRaces.NullOrEmpty())
foreach (ThingDef def in VariousDefOf.AllRaces)
if (VariousDefOf.AllRaces.NullOrEmpty()) return;
foreach (ThingDef def in VariousDefOf.AllRaces)
{
if (def.race != null)
{
if (def.race != null)
if (info.hybridExtension.Exists(x => x.DefName == def.defName)) continue;
else
{
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.Add(new FloatMenuOption(def.label, delegate { AddHybridInfo(def); }, Widgets.GetIconFor(def), Color.white));
}
}
}
raceList.SortBy(x => x.Label);
}
@ -320,11 +310,11 @@ namespace RJW_Menstruation
buttonRect.x -= 100;
if (Widgets.ButtonText(buttonRect, "Undo"))
{
var element = removeList.Last();
HybridExtensionExposable element = removeList.Last();
info.hybridExtension.Add(element);
removeList.Remove(element);
}
foreach (HybridExtensionExposable element in removeList)
{
info.hybridExtension.Remove(element);
@ -333,7 +323,7 @@ namespace RJW_Menstruation
float additionalHeight = 0f;
if (!info.hybridExtension.NullOrEmpty()) foreach(HybridExtensionExposable e in info.hybridExtension)
if (!info.hybridExtension.NullOrEmpty()) foreach (HybridExtensionExposable e in info.hybridExtension)
{
additionalHeight += (e.hybridInfo?.Count() ?? 1) * rowH;
}
@ -356,7 +346,7 @@ namespace RJW_Menstruation
}
Widgets.EndScrollView();
listmain.End();
}
@ -376,7 +366,7 @@ namespace RJW_Menstruation
if (Widgets.ButtonText(buttonRect, "Add"))
{
List<FloatMenuOption> list = new List<FloatMenuOption>();
if (!VariousDefOf.AllRaces.NullOrEmpty()) foreach(ThingDef def in VariousDefOf.AllRaces)
if (!VariousDefOf.AllRaces.NullOrEmpty()) foreach (ThingDef def in VariousDefOf.AllRaces)
{
if (def.race != null)
{
@ -392,7 +382,7 @@ namespace RJW_Menstruation
list.SortBy(x => x.Label);
Find.WindowStack.Add(new FloatMenu(list));
}
}
buttonRect.x -= 80f;
@ -403,18 +393,18 @@ namespace RJW_Menstruation
if (!extension.hybridInfo.EnumerableNullOrEmpty())
{
totalWeight = 0;
foreach(KeyValuePair<string,float> element in extension.hybridInfo)
foreach (KeyValuePair<string, float> element in extension.hybridInfo)
{
totalWeight += element.Value;
}
List<string> keys = new List<string>(extension.hybridInfo.Keys);
foreach (string key in keys)
{
DoSubRow(sublist.GetRect(rowH), key, extension, removeelements);
}
}
if(!removeelements.NullOrEmpty()) foreach(string key in removeelements)
if (!removeelements.NullOrEmpty()) foreach (string key in removeelements)
{
extension.hybridInfo.Remove(key);
}
@ -425,7 +415,7 @@ namespace RJW_Menstruation
}
protected void DoSubRow(Rect rect, string key, HybridExtensionExposable extension , List<string> removeelements)
protected void DoSubRow(Rect rect, string key, HybridExtensionExposable extension, List<string> removeelements)
{
bool isPawnKind = false;
int value = (int)extension.hybridInfo.TryGetValue(key);
@ -471,15 +461,15 @@ namespace RJW_Menstruation
}
label += ": " + key;
Widgets.Label(rect, " - " + label);
Widgets.TextFieldNumeric(buttonRect, ref value, ref valuestr,0,9999999);
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)));
TooltipHandler.TipRegion(rect, Translations.CustomHybrid_Tooltip(info.GetDef?.label ?? "Undefined", extension.GetDef?.label ?? "Undefined", label, String.Format("{0,0:0.########%}", value / totalWeight)));
}
}

View file

@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using RimWorld;
using RimWorld;
using rjw;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Verse;
@ -92,7 +92,7 @@ namespace RJW_Menstruation
int index = pawns.IndexOf(window.pawn);
SoundDefOf.TabOpen.PlayOneShotOnCamera();
Pawn newpawn = pawns[(index + 1) % pawns.Count];
window.ChangePawn(newpawn, newpawn.GetMenstruationComp());
window.ChangePawn(newpawn, newpawn.GetFirstMenstruationComp());
}
else if (window.pawn != pawn)
{
@ -151,16 +151,15 @@ namespace RJW_Menstruation
fontstyleleft.normal.textColor = Color.white;
float preginfoheight = 0f;
bool pregnant = pawn.IsPregnant();
Hediff hediff = PregnancyHelper.GetPregnancy(pawn);
if (pregnant && Utility.ShowFetusImage((Hediff_BasePregnancy)hediff))
Hediff_BasePregnancy hediff = comp.Pregnancy;
if (hediff != null && Utility.ShowFetusImage(hediff))
{
womb = comp.GetPregnancyIcon(hediff);
if (hediff is Hediff_MultiplePregnancy m)
{
if (m.GestationProgress < 0.2f) cum = comp.GetCumIcon();
else cum = ContentFinder<Texture2D>.Get(("Womb/Empty"), true);
Pawn fetus = pawn.GetFetus();
Pawn fetus = comp.GetFetus();
if (fetus != null && Utility.ShowFetusInfo())
{
string feinfo = m.GetBabyInfo();
@ -188,7 +187,7 @@ namespace RJW_Menstruation
{
if (b.GestationProgress < 0.2f) cum = comp.GetCumIcon();
else cum = ContentFinder<Texture2D>.Get(("Womb/Empty"), true);
Pawn fetus = pawn.GetFetus();
Pawn fetus = comp.GetFetus();
if (fetus != null && Utility.ShowFetusInfo())
{
preginfoheight = fontheight;
@ -230,7 +229,7 @@ namespace RJW_Menstruation
if (pawn.story != null) GUI.Label(pawnLabel2Rect, pawn.ageTracker.AgeBiologicalYears + ", " + pawn.story.Title, fontstylecenter);
GUI.color = Color.white;
float wombrecth = 0;
if (Configurations.DrawWombStatus)
{
@ -249,7 +248,7 @@ namespace RJW_Menstruation
}
Rect wombInfoRect = new Rect(0f, mainRect.yMax - wombrecth - fontheight - 2, wombRectWidth, fontheight - 4f);
Rect progressRect = new Rect(wombInfoRect.x,wombInfoRect.yMax,wombRectWidth, 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;
@ -286,7 +285,7 @@ namespace RJW_Menstruation
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);
Rect infoRect = new Rect(0, pawnRectHeight + 2 * fontheight, pawnRectWidth, pawnRect.yMax + 2 * fontheight - wombInfoRect.y);
DrawInfos(infoRect);
@ -369,7 +368,7 @@ namespace RJW_Menstruation
GUI.color = new Color(1.00f, 0.47f, 0.47f, 1);
GUI.Box(rect, "", boxstyle);
pawn.DrawBreastIcon(BreastIconRect, Mouse.IsOver(BreastIconRect) && Input.GetMouseButton(0));
@ -388,11 +387,11 @@ namespace RJW_Menstruation
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.SlaaneshTexture,Texture2D.blackTexture, xxx.sex_drive_stat.description);
FillableBarLabeled(lineRect, " " + xxx.sex_drive_stat.LabelCap.CapitalizeFirst() + " " + statvalue.ToStringPercent(), statvalue / 2, TextureCache.SlaaneshTexture, 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.KhorneTexture,Texture2D.blackTexture, xxx.vulnerability_stat.description);
FillableBarLabeled(lineRect, " " + xxx.vulnerability_stat.LabelCap.CapitalizeFirst() + " " + statvalue.ToStringPercent(), statvalue / 2, TextureCache.KhorneTexture, Texture2D.blackTexture, xxx.vulnerability_stat.description);
lineRect.y += height;
statvalue = pawn.GetStatValue(xxx.sex_stat);
@ -409,27 +408,11 @@ namespace RJW_Menstruation
statvalue = pawn.records.GetValue(xxx.CountOfBirthEgg);
FillableBarLabeled(lineRect, " " + xxx.CountOfBirthEgg.LabelCap.CapitalizeFirst() + " " + statvalue, statvalue / 100, TextureCache.NurgleTexture, Texture2D.blackTexture, xxx.CountOfBirthEgg.description);
lineRect.y += height;
statvalue = pawn.records.GetValue(xxx.CountOfWhore);
if (statvalue > 0)
{
FillableBarLabeled(lineRect, " " + xxx.CountOfWhore.LabelCap.CapitalizeFirst() + " " + statvalue, statvalue / 50, TextureCache.SlaaneshTexture, Texture2D.blackTexture, xxx.CountOfWhore.description);
statvalue = pawn.records.GetValue(xxx.EarnedMoneyByWhore);
lineRect.y += height;
FillableBarLabeled(lineRect, " " + VariousDefOf.RJW_EarnedMoneyByWhore.label.CapitalizeFirst() + " " + statvalue, statvalue / 10000, TextureCache.GhalmarazTexture, Texture2D.blackTexture);
lineRect.y += height;
}
else
{
lineRect.y += height;
lineRect.y += height;
}
lineRect.y += height * 3;
statvalue = Configurations.ImplantationChance * comp.ImplantFactor;
float fertchance = comp.GetFertilityChance();
FillableBarLabeled(lineRect, " " + xxx.reproduction.LabelCap.CapitalizeFirst() + " " + statvalue.ToStringPercent(), statvalue, TextureCache.FertilityTexture, Texture2D.blackTexture, Translations.FertilityDesc(String.Format("{0:0.##}", fertchance*100)));
FillableBarLabeled(lineRect, " " + xxx.reproduction.LabelCap.CapitalizeFirst() + " " + statvalue.ToStringPercent(), statvalue, TextureCache.FertilityTexture, Texture2D.blackTexture, Translations.FertilityDesc(String.Format("{0:0.##}", fertchance * 100)));
Rect overayRect = new Rect(lineRect.x, lineRect.y, lineRect.width * Math.Min(1.0f, fertchance), lineRect.height);
GUI.DrawTexture(overayRect, TextureCache.FertChanceTex);
lineRect.y += height;
@ -437,7 +420,7 @@ namespace RJW_Menstruation
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);
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);

View file

@ -37,7 +37,7 @@ namespace RJW_Menstruation
Widgets.FillableBar(progressRect, comp.StageProgress, comp.GetStageTexture);
}

View file

@ -1,13 +1,11 @@
using RimWorld;
using rjw;
using System;
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Verse;
using Verse.Sound;
using System.Threading;
using System.Threading.Tasks;
namespace RJW_Menstruation
@ -16,7 +14,7 @@ namespace RJW_Menstruation
{
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 ColorInt white = new ColorInt(255, 255, 255, 255);
@ -49,10 +47,15 @@ namespace RJW_Menstruation
public static class Utility
{
public static System.Random random = new System.Random(Environment.TickCount);
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.def.race?.AnyPawnKind ??
pawn.kindDef;
}
public static float GetCumVolume(this Pawn pawn)
{
@ -94,16 +97,13 @@ namespace RJW_Menstruation
public static HediffComp_Breast GetBreastComp(this Pawn pawn)
{
var hedifflist = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_breastsBPR(pawn))?.FindAll((Hediff h) => h is Hediff_PartBaseNatural || h is Hediff_PartBaseArtifical);
List<Hediff> hedifflist = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_breastsBPR(pawn))?.FindAll((Hediff h) => h is Hediff_PartBaseNatural || h is Hediff_PartBaseArtifical);
HediffComp_Breast result;
if (hedifflist.NullOrEmpty()) return null;
else
foreach (Hediff h in hedifflist)
{
foreach(Hediff h in hedifflist)
{
result = h.TryGetComp<HediffComp_Breast>();
if (result != null) return result;
}
result = h.TryGetComp<HediffComp_Breast>();
if (result != null) return result;
}
return null;
}
@ -125,66 +125,43 @@ namespace RJW_Menstruation
public static bool HasMenstruationComp(this Pawn pawn)
{
var hedifflist = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn))?.FindAll((Hediff h) => h.def.defName.ToLower().Contains("vagina"));
HediffComp_Menstruation result;
if (hedifflist.NullOrEmpty()) return false;
else
{
foreach (Hediff h in hedifflist)
{
result = h.TryGetComp<HediffComp_Menstruation>();
if (result != null) return true;
}
}
return false;
return pawn.GetMenstruationComps().Any();
}
public static bool HasMenstruationComp(this Hediff hediff)
{
if (hediff is Hediff_PartBaseNatural || hediff is Hediff_PartBaseArtifical)
if ((hediff is Hediff_PartBaseNatural || hediff is Hediff_PartBaseArtifical) && hediff.TryGetComp<HediffComp_Menstruation>() != null)
return true;
else return false;
}
public static float GetFarthestPregnancyProgress(this Pawn pawn)
{
return pawn.health.hediffSet.GetHediffs<Hediff_BasePregnancy>().MaxBy(hediff => hediff.GestationProgress)?.GestationProgress ?? -1;
}
public static float GetPregnancyProgress(this HediffComp_Menstruation comp)
{
if (comp.Pregnancy == null) return -1;
else return comp.Pregnancy.GestationProgress;
}
public static Pawn GetFetus(this HediffComp_Menstruation comp)
{
if (comp.Pregnancy == null) return null;
if (!comp.Pregnancy.babies.NullOrEmpty()) return comp.Pregnancy.babies.First();
else
{
if (hediff.TryGetComp<HediffComp_Menstruation>() != null) return true;
Log.Error("Baby not exist: baby was not created or removed. Remove pregnancy.");
comp.Pregnancy.Miscarry();
return null;
}
return false;
}
public static float GetPregnancyProgress(this Pawn pawn)
public static void DrawBreastIcon(this Pawn pawn, Rect rect, bool drawOrigin = false)
{
Hediff hediff = PregnancyHelper.GetPregnancy(pawn);
if (hediff is Hediff_BasePregnancy h)
{
return h.GestationProgress;
}
return -1;
}
public static Pawn GetFetus(this Pawn pawn)
{
Hediff hediff = PregnancyHelper.GetPregnancy(pawn);
if (hediff is Hediff_BasePregnancy h)
{
if (!h.babies.NullOrEmpty()) return h.babies.First();
else
{
Log.Error("Baby not exist: baby was not created or removed. Remove pregnancy.");
pawn.health.RemoveHediff(hediff);
return null;
}
}
return null;
}
public static Hediff_BasePregnancy GetRJWPregnancy(this Pawn pawn)
{
return (Hediff_BasePregnancy)pawn.health.hediffSet.hediffs.FirstOrDefault(x => x is Hediff_BasePregnancy);
}
public static void DrawBreastIcon(this Pawn pawn, Rect rect , bool drawOrigin = false)
{
var hediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_breastsBPR(pawn)).FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("breast"));
Hediff hediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_breastsBPR(pawn)).FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("breast"));
Texture2D breast, nipple, areola;
if (hediff != null)
{
@ -227,7 +204,7 @@ namespace RJW_Menstruation
nippleicon = icon + "_Nipple0" + GetNippleIndex(nipplesize);
areolaicon = icon + "_Areola0" + GetAreolaIndex(areolasize);
breast = ContentFinder<Texture2D>.Get(icon, false);
areola = ContentFinder<Texture2D>.Get(areolaicon, false);
@ -299,78 +276,75 @@ namespace RJW_Menstruation
milkcomp = pawn.GetComp<CompMilkable>();
}
if (milkcomp != null)
if (milkcomp == null) return;
if (milkcomp is CompMilkable milkable)
{
if (milkcomp is CompMilkable milkable)
bool active = (bool)milkcomp.GetPropertyValue("Active");
if (active)
{
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);
}
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
}
else
{
bool active = (bool)milkcomp.GetPropertyValue("Active");
if (active)
{
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);
}
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)
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)
{
if (fullness < 0.3f) texture = ContentFinder<Texture2D>.Get("Milk/Milkbottle_Small", false);
else if (fullness < 0.7f) texture = ContentFinder<Texture2D>.Get("Milk/Milkbottle_Medium", false);
else texture = ContentFinder<Texture2D>.Get("Milk/Milkbottle_Large", false);
GUIContent icon = new GUIContent(texture);
GUIStyle style = GUIStyle.none;
style.normal.background = texture;
string tooltip = Translations.Button_MilkTooltip;
if (fullness <= 0.0f) return;
TooltipHandler.TipRegion(buttonrect, tooltip);
if (GUI.Button(buttonrect, icon, style))
if (fullness < 0.3f) texture = ContentFinder<Texture2D>.Get("Milk/Milkbottle_Small", false);
else if (fullness < 0.7f) texture = ContentFinder<Texture2D>.Get("Milk/Milkbottle_Medium", false);
else texture = ContentFinder<Texture2D>.Get("Milk/Milkbottle_Large", false);
GUIContent icon = new GUIContent(texture);
GUIStyle style = GUIStyle.none;
style.normal.background = texture;
string tooltip = Translations.Button_MilkTooltip;
TooltipHandler.TipRegion(buttonrect, tooltip);
if (GUI.Button(buttonrect, icon, style))
{
if (fullness < 0.1f
|| !pawn.IsColonistPlayerControlled
|| pawn.Downed) SoundDefOf.ClickReject.PlayOneShotOnCamera();
else
{
if (fullness < 0.1f
|| !pawn.IsColonistPlayerControlled
|| pawn.Downed) SoundDefOf.ClickReject.PlayOneShotOnCamera();
else
{
SoundDefOf.Click.PlayOneShotOnCamera();
pawn.jobs.TryTakeOrderedJob(new Verse.AI.Job(milkjob, pawn));
}
SoundDefOf.Click.PlayOneShotOnCamera();
pawn.jobs.TryTakeOrderedJob(new Verse.AI.Job(milkjob, pawn));
}
Widgets.DrawHighlightIfMouseover(buttonrect);
}
Widgets.DrawHighlightIfMouseover(buttonrect);
}
public static string GetVaginaLabel(this Pawn pawn)
{
var hediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn)).Find((Hediff h) => h.def.defName.ToLower().Contains("vagina"));
Hediff hediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn)).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)
{
var hediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_anusBPR(pawn)).FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("anus"));
Hediff hediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_anusBPR(pawn)).FirstOrDefault((Hediff 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)
{
var hediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_breastsBPR(pawn)).FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("breast"));
Hediff hediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_breastsBPR(pawn)).FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("breast"));
if (hediff != null) return hediff.LabelBase.CapitalizeFirst() + "\n(" + hediff.LabelInBrackets + ")";
else return "";
}
@ -422,25 +396,20 @@ namespace RJW_Menstruation
{
Pawn res = pawn.GetFather();
if (res != null) return res;
else
{
res = pawn.relations?.GetFirstDirectRelationPawn(PawnRelationDefOf.Parent, x => x != mother) ?? null;
if (res == null) res = pawn.relations?.GetFirstDirectRelationPawn(VariousDefOf.Relation_birthgiver, x => x != mother) ?? null;
return res;
}
else res = pawn.relations?.GetFirstDirectRelationPawn(PawnRelationDefOf.Parent, x => x != mother) ?? null;
return res;
}
public static float RandGaussianLike(float min, float max, int iterations = 3)
{
double res = 0;
float res = 0;
for (int i = 0; i < iterations; i++)
{
res += random.NextDouble();
res += Rand.Value;
}
res /= iterations;
return (float)res*(max-min) + min;
return res * (max - min) + min;
}
@ -449,7 +418,7 @@ namespace RJW_Menstruation
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);
@ -457,20 +426,7 @@ namespace RJW_Menstruation
public static bool ShouldShowWombGizmo(this Pawn pawn)
{
if (Configurations.EnableWombIcon)
{
if (!pawn.IsAnimal())
{
return true;
}
else if (Configurations.EnableAnimalCycle)
{
return true;
}
}
return false;
return Configurations.EnableWombIcon && (!pawn.IsAnimal() || Configurations.EnableAnimalCycle);
}
}
}

View file

@ -1,8 +1,8 @@
using RimWorld;
using rjw;
using System.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using Verse;
namespace RJW_Menstruation
@ -11,6 +11,7 @@ namespace RJW_Menstruation
{
public static readonly ThingDef CumFilth = DefDatabase<ThingDef>.GetNamed("FilthCum");
public static readonly ThingDef GirlCumFilth = DefDatabase<ThingDef>.GetNamed("FilthGirlCum");
public static readonly ThingDef Tampon = DefDatabase<ThingDef>.GetNamed("Absorber_Tampon");
public static readonly ThingDef Tampon_Dirty = DefDatabase<ThingDef>.GetNamed("Absorber_Tampon_Dirty");
public static readonly ThingDef FilthMixture = DefDatabase<ThingDef>.GetNamed("FilthMixture");
@ -22,9 +23,6 @@ namespace RJW_Menstruation
public static readonly HediffDef Hediff_Estrus_Concealed = DefDatabase<HediffDef>.GetNamed("Hediff_Estrus_Concealed");
public static readonly HediffDef Hediff_ASA = DefDatabase<HediffDef>.GetNamed("Hediff_ASA");
public static readonly StatDef MaxAbsorbable = DefDatabase<StatDef>.GetNamed("MaxAbsorbable");
// Obsolete, kept for compatibility for now
public static readonly PawnRelationDef Relation_birthgiver = DefDatabase<PawnRelationDef>.AllDefs.FirstOrDefault(d => d.defName == "RJW_Sire");
public static readonly PawnRelationDef Relation_spawn = DefDatabase<PawnRelationDef>.AllDefs.FirstOrDefault(d => d.defName == "RJW_Pup");
public static readonly NeedDef SexNeed = DefDatabase<NeedDef>.GetNamed("Sex");
public static readonly JobDef VaginaWashing = DefDatabase<JobDef>.GetNamed("VaginaWashing");
public static readonly JobDef Job_LactateSelf = DefDatabase<JobDef>.GetNamed("LactateSelf");
@ -42,28 +40,26 @@ namespace RJW_Menstruation
public static readonly ThoughtDef UnwantedPregnancyMild = DefDatabase<ThoughtDef>.GetNamed("UnwantedPregnancyMild");
public static readonly ThoughtDef TookContraceptivePill = DefDatabase<ThoughtDef>.GetNamed("TookContraceptivePill");
public static readonly ThoughtDef HateTookContraceptivePill = DefDatabase<ThoughtDef>.GetNamed("HateTookContraceptivePill");
public static readonly HediffDef_PartBase Vagina = DefDatabase<HediffDef_PartBase>.GetNamed("Vagina");
public static readonly CompProperties_Menstruation VaginaCompProperties = (CompProperties_Menstruation)Vagina.comps.FirstOrDefault(x => x is CompProperties_Menstruation);
public static readonly CompProperties_Menstruation HumanVaginaCompProperties = (CompProperties_Menstruation)Genital_Helper.average_vagina.comps.FirstOrDefault(x => x is CompProperties_Menstruation);
public static readonly KeyBindingDef OpenStatusWindowKey = DefDatabase<KeyBindingDef>.GetNamed("OpenStatusWindow");
public static readonly PawnColumnDef RJW_EarnedMoneyByWhore = DefDatabase<PawnColumnDef>.GetNamed("RJW_EarnedMoneyByWhore");
public static readonly RecordDef AmountofCreampied = DefDatabase<RecordDef>.GetNamed("AmountofCreampied");
public static readonly RecordDef AmountofFertilizedEggs = DefDatabase<RecordDef>.GetNamed("AmountofFertilizedEggs");
public static readonly TaleDef TaleCameInside = DefDatabase<TaleDef>.GetNamed("CameInside");
private static List<ThingDef> allraces = null;
private static List<PawnKindDef> allkinds = null;
private static HashSet<HediffDef> allvaginas = null;
public static List<ThingDef> AllRaces
{
get
{
if (allraces == null)
{
List<ThingDef> allThings = DefDatabase<ThingDef>.AllDefsListForReading;
allraces = allThings.FindAll(x => x.race != null && x.race.IsFlesh);
}
if (allraces != null) return allraces;
List<ThingDef> allThings = DefDatabase<ThingDef>.AllDefsListForReading;
allraces = allThings.FindAll(x => x.race != null && x.race.IsFlesh);
return allraces;
}
}
@ -71,16 +67,37 @@ namespace RJW_Menstruation
{
get
{
if (allkinds == null)
{
List<PawnKindDef> allKinds = DefDatabase<PawnKindDef>.AllDefsListForReading;
allkinds = allKinds.FindAll(x => x.race != null);
}
if (allkinds != null) return allkinds;
List<PawnKindDef> allKinds = DefDatabase<PawnKindDef>.AllDefsListForReading;
allkinds = allKinds.FindAll(x => x.race != null);
return allkinds;
}
}
public static HashSet<HediffDef> AllVaginas
{
get
{
if (allvaginas != null) return allvaginas;
allvaginas = new HashSet<HediffDef>();
List<HediffDef> allHediffs = DefDatabase<HediffDef>.AllDefsListForReading;
foreach(HediffDef hediffDef in allHediffs)
{
if (hediffDef.comps.NullOrEmpty()) continue;
foreach (HediffCompProperties comp in hediffDef.comps)
{
if (comp.compClass == typeof(HediffComp_Menstruation) || comp.compClass.IsSubclassOf(typeof(HediffComp_Menstruation)))
{
allvaginas.Add(hediffDef);
break;
}
}
}
return allvaginas;
}
}
// Defs from Milkable Colonists
public static readonly HediffDef Hediff_Lactating_Drug = DefDatabase<HediffDef>.GetNamedSilentFail("Lactating_Drug");
@ -88,12 +105,5 @@ namespace RJW_Menstruation
public static readonly HediffDef Hediff_Lactating_Permanent = DefDatabase<HediffDef>.GetNamedSilentFail("Lactating_Permanent");
public static readonly HediffDef Hediff_Heavy_Lactating_Permanent = DefDatabase<HediffDef>.GetNamedSilentFail("Heavy_Lactating_Permanent");
public static readonly JobDef Job_LactateSelf_MC = DefDatabase<JobDef>.GetNamedSilentFail("LactateSelf_MC");
}
}

View file

@ -1,13 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using RimWorld;
using RJWSexperience;
using RJW_Menstruation;
using System.Collections.Generic;
using UnityEngine;
using Verse;
namespace RJW_Menstruation.Sexperience
{
@ -34,8 +27,8 @@ namespace RJW_Menstruation.Sexperience
if (res && other is GatheredCumMixture mixture)
{
GatheredCumMixture othercum = mixture;
cumColor = Colors.CMYKLerp(cumColor,othercum.cumColor,count/(amount+count));
if (!othercum.ingredients.NullOrEmpty()) for (int i=0; i<othercum.ingredients.Count; i++)
cumColor = Colors.CMYKLerp(cumColor, othercum.cumColor, count / (amount + count));
if (!othercum.ingredients.NullOrEmpty()) for (int i = 0; i < othercum.ingredients.Count; i++)
{
if (!ingredients.Contains(othercum.ingredients[i])) ingredients.Add(othercum.ingredients[i]);
}
@ -46,7 +39,7 @@ namespace RJW_Menstruation.Sexperience
public override string GetInspectString()
{
string res = "";
if (!ingredients.NullOrEmpty()) for(int i=0; i<ingredients.Count; i++)
if (!ingredients.NullOrEmpty()) for (int i = 0; i < ingredients.Count; i++)
{
res += ingredients[i];
if (i != ingredients.Count - 1) res += ", ";

View file

@ -1,13 +1,8 @@
using System;
using RJWSexperience;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
using Verse;
using Verse.AI;
using RimWorld;
using RJWSexperience;
namespace RJW_Menstruation.Sexperience
{
@ -23,8 +18,6 @@ namespace RJW_Menstruation.Sexperience
protected override IEnumerable<Toil> MakeNewToils()
{
HediffComp_Menstruation Comp = pawn.GetMenstruationComp();
//this.FailOn(delegate
//{
// return !(Comp.TotalCumPercent > 0.001);
@ -38,23 +31,26 @@ namespace RJW_Menstruation.Sexperience
{
initAction = delegate ()
{
if (Comp.TotalCumPercent > 0.001)
{
CumMixture mixture = Comp.MixtureOut(RJWSexperience.VariousDefOf.GatheredCum, 0.5f);
float amount = mixture.Volume;
if (mixture.ispurecum)
bool anyExcreted = false;
foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps())
if (comp.TotalCumPercent > 0.001)
{
Bucket.AddCum(amount);
CumMixture mixture = comp.MixtureOut(RJWSexperience.VariousDefOf.GatheredCum, 0.5f);
float amount = mixture.Volume;
if (mixture.ispurecum)
{
Bucket.AddCum(amount);
}
else
{
GatheredCumMixture cummixture = (GatheredCumMixture)ThingMaker.MakeThing(VariousDefOf.GatheredCumMixture);
cummixture.InitwithCum(mixture);
Bucket.AddCum(amount, cummixture);
}
anyExcreted = true;
}
else
{
GatheredCumMixture cummixture = (GatheredCumMixture)ThingMaker.MakeThing(VariousDefOf.GatheredCumMixture);
cummixture.InitwithCum(mixture);
Bucket.AddCum(amount, cummixture);
}
}
else ReadyForNextToil();
if (Comp.TotalCumPercent > 0.001) JumpToToil(excreting);
if (!anyExcreted) ReadyForNextToil();
if (pawn.GetMenstruationComps().Any(c => c.TotalCumPercent > 0.001)) JumpToToil(excreting);
}
};

View file

@ -1,14 +1,7 @@
using System;
using HarmonyLib;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using RimWorld;
using UnityEngine;
using RJWSexperience;
using rjw;
using HarmonyLib;
using Verse;
namespace RJW_Menstruation.Sexperience
@ -32,7 +25,7 @@ namespace RJW_Menstruation.Sexperience
defaultLabel = label,
defaultDesc = description,
icon = icon,
isActive = delegate() { return comp.DoCleanWomb; },
isActive = delegate () { return comp.DoCleanWomb; },
toggleAction = delegate
{
comp.DoCleanWomb = !comp.DoCleanWomb;

View file

@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HarmonyLib;
using HarmonyLib;
using System.Reflection;
using Verse;
@ -14,7 +9,7 @@ namespace RJW_Menstruation.Sexperience
{
static First()
{
var har = new Harmony("RJW_Menstruation.Sexperience");
Harmony har = new Harmony("RJW_Menstruation.Sexperience");
har.PatchAll(Assembly.GetExecutingAssembly());
}
}

View file

@ -1,16 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RJW_Menstruation;
using HarmonyLib;
using rjw;
using HarmonyLib;
using RimWorld;
using UnityEngine;
using Verse;
using Verse.Sound;
using UnityEngine;
using RJWSexperience;
namespace RJW_Menstruation.Sexperience
{
@ -24,7 +16,7 @@ namespace RJW_Menstruation.Sexperience
Rect buttonRect = new Rect(rect.x, rect.yMax - ICONSIZE, ICONSIZE, ICONSIZE).ContractedBy(2f);
if (__instance.Comp.DoCleanWomb)
{
Widgets.DrawTextureFitted(buttonRect,TextureCache.GatherCum_Bucket,1.0f);
Widgets.DrawTextureFitted(buttonRect, TextureCache.GatherCum_Bucket, 1.0f);
TooltipHandler.TipRegion(buttonRect, Translations.Dialog_DoCleanWomb_Tooltip);
}
else

View file

@ -1,14 +1,10 @@
using System;
using HarmonyLib;
using RimWorld;
using RJWSexperience;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using Verse.AI;
using RimWorld;
using HarmonyLib;
using UnityEngine;
using RJWSexperience;
using Verse;
namespace RJW_Menstruation.Sexperience
{
@ -17,25 +13,20 @@ namespace RJW_Menstruation.Sexperience
{
public static void Postfix(Vector3 clickPos, Pawn pawn, List<FloatMenuOption> opts)
{
var targets = GenUI.TargetsAt(clickPos, TargetingParameters.ForBuilding());
HediffComp_Menstruation comp = pawn.GetMenstruationComp();
IEnumerable<LocalTargetInfo> targets = GenUI.TargetsAt(clickPos, TargetingParameters.ForBuilding());
if (comp != null && comp.TotalCumPercent > 0.001f)
foreach (LocalTargetInfo t in targets)
{
if (t.Thing is Building building)
if (pawn.GetMenstruationComps().Any(comp => comp.TotalCumPercent > 0.001f))
foreach (LocalTargetInfo t in targets)
{
if (building is Building_CumBucket)
if (t.Thing is Building building)
{
opts.AddDistinct(MakeMenu(pawn, building));
break;
if (building is Building_CumBucket)
{
opts.AddDistinct(MakeMenu(pawn, building));
break;
}
}
}
}
}
public static FloatMenuOption MakeMenu(Pawn pawn, LocalTargetInfo target)

View file

@ -1,15 +1,9 @@
using System;
using System.Collections.Generic;
using HarmonyLib;
using rjw;
using RJWSexperience;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
using Verse.AI;
using rjw;
using RJW_Menstruation;
using HarmonyLib;
using RJWSexperience;
namespace RJW_Menstruation.Sexperience
{
@ -20,8 +14,7 @@ namespace RJW_Menstruation.Sexperience
[HarmonyPatch("HasJobOnThing")]
public static bool HasJobOnThing(Pawn pawn, ref bool __result)
{
HediffComp_Menstruation comp = pawn.GetMenstruationComp();
if (comp != null && comp.DoCleanWomb && comp.TotalCumPercent > 0.001f && pawn.Map.listerBuildings.ColonistsHaveBuilding(VariousDefOf.CumBucket))
if (pawn.GetMenstruationComps().Any(comp => comp.DoCleanWomb && comp.TotalCumPercent > 0.001f) && pawn.Map.listerBuildings.ColonistsHaveBuilding(VariousDefOf.CumBucket))
{
__result = true;
return false;
@ -33,8 +26,7 @@ namespace RJW_Menstruation.Sexperience
[HarmonyPatch("JobOnThing")]
public static void JobOnThing(Pawn pawn, ref Job __result)
{
HediffComp_Menstruation comp = pawn.GetMenstruationComp();
if (comp != null && comp.DoCleanWomb && comp.TotalCumPercent > 0.001f)
if (pawn.GetMenstruationComps().Any(comp => comp.DoCleanWomb && comp.TotalCumPercent > 0.001f))
{
Building_CumBucket bucket = pawn.FindClosestBucket();
@ -43,10 +35,6 @@ namespace RJW_Menstruation.Sexperience
__result = JobMaker.MakeJob(VariousDefOf.VaginaWashingwithBucket, null, bucket, bucket.Position);
}
}
}
}
}

View file

@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해

View file

@ -1,9 +1,4 @@
using RimWorld;
using rjw;
using System.Linq;
using System;
using System.Collections.Generic;
using Verse;
using Verse;
namespace RJW_Menstruation.Sexperience
{

View file

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

View file

@ -1,3 +1,25 @@
Version 1.0.7.0
- Not save compatible with previous versions. Expect glitches and many red errors if you try. However, things should stabilize eventually.
- Designed for RJW 5.0.0, but should work with previous versions.
- Support for multiple vaginas, including each having a separate pregnancy.
- More reliably generate a baby's race correctly when using pawnkind diversification mods.
- Overhauled many things under the hood.
- Cycle randomization completely redone. Everyone now has a (hidden) cycle speed and cycle variability.
- Ovary initialization redone. All pawns now get a total number of eggs based on their age and racial properties.
- Coming inside someone with an IUD will give the same total amount of fluid as without, just at a lower fertility.
- The chance to fertilize has been changed to an exponential curve instead of a linear one. This will increase the chances of pregnancy at low amounts of semen and slightly reduce it at high amounts.
- Semen now has a fertility percentage instead of "fertile volume".
- The exact time between fertilization and implantation has been adjusted.
- Removing a vagina will end any pregnancy it has in progress. Please wait until the baby is born first.
- Your colonists can create artwork of someone being born.
- They can also create artwork of someone coming inside someone else.
- Default values changed to account for the new math. The new defaults will have the same odds of pregnancy with a 10ml ejaculation at ovulation (in a human) as before:
- Fertilization chance from 10%/mL to 15%
- Cum decay from 30%/hour to 15%
- Fertility decay from 20%/hour to 5%
Version 1.0.6.6
- Ovipostors add on average 1.5x as much cum to a womb than before.
- The womb tick timing is now more consistent across a save and load, and also spread out across pawns.