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_Ovulatory>排卵</Stage_Ovulatory>
<Stage_Luteal>黄体期</Stage_Luteal> <Stage_Luteal>黄体期</Stage_Luteal>
<Stage_Bleeding>月经来潮</Stage_Bleeding> <Stage_Bleeding>月经来潮</Stage_Bleeding>
<Stage_Fertilized>已受精</Stage_Fertilized>
<Stage_Pregnant>怀孕</Stage_Pregnant> <Stage_Pregnant>怀孕</Stage_Pregnant>
<Stage_Recover>产后恢复</Stage_Recover> <Stage_Recover>产后恢复</Stage_Recover>
<Stage_None></Stage_None> <Stage_None></Stage_None>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -11,8 +11,7 @@ namespace RJW_Menstruation
public Pawn pawn; public Pawn pawn;
protected float volume; // ml protected float volume; // ml
protected float fertvolume; public float fertility = 1.0f;
public float fertFactor = 1.0f;
public bool notcum = false; // for other fluids public bool notcum = false; // for other fluids
public string notcumLabel = ""; public string notcumLabel = "";
protected bool useCustomColor = false; protected bool useCustomColor = false;
@ -32,7 +31,7 @@ namespace RJW_Menstruation
{ {
get get
{ {
return fertvolume; return volume * fertility;
} }
} }
@ -62,23 +61,20 @@ namespace RJW_Menstruation
{ {
get get
{ {
if (DNAcache != null) return DNAcache;
try
{
DNAcache = pawn.def.GetModExtension<PawnDNAModExtension>();
}
catch (NullReferenceException)
{
DNAcache = ThingDefOf.Human.GetModExtension<PawnDNAModExtension>();
}
if (DNAcache == null) if (DNAcache == null)
{ {
try DNAcache = ThingDefOf.Human.GetModExtension<PawnDNAModExtension>();
{
DNAcache = pawn.def.GetModExtension<PawnDNAModExtension>();
}
catch (NullReferenceException)
{
DNAcache = ThingDefOf.Human.GetModExtension<PawnDNAModExtension>();
}
if (DNAcache == null)
{
DNAcache = ThingDefOf.Human.GetModExtension<PawnDNAModExtension>();
}
return DNAcache;
} }
else return DNAcache; return DNAcache;
} }
} }
protected PawnDNAModExtension DNAcache = null; protected PawnDNAModExtension DNAcache = null;
@ -130,7 +126,7 @@ namespace RJW_Menstruation
{ {
this.pawn = pawn; this.pawn = pawn;
volume = 1.0f; volume = 1.0f;
fertvolume = 1.0f; fertility = 1.0f;
} }
/// <summary> /// <summary>
@ -145,7 +141,7 @@ namespace RJW_Menstruation
{ {
this.pawn = pawn; this.pawn = pawn;
this.volume = volume; this.volume = volume;
this.fertvolume = volume; this.fertility = 0f;
this.notcum = true; this.notcum = true;
this.notcumLabel = notcumlabel; this.notcumLabel = notcumlabel;
this.notcumthickness = decayresist; this.notcumthickness = decayresist;
@ -156,7 +152,7 @@ namespace RJW_Menstruation
{ {
this.pawn = pawn; this.pawn = pawn;
this.volume = volume; this.volume = volume;
this.fertvolume = volume * fertility; this.fertility = fertility;
this.filthDef = filthDef; this.filthDef = filthDef;
} }
@ -167,9 +163,8 @@ namespace RJW_Menstruation
Scribe_References.Look(ref pawn, "pawn", true); Scribe_References.Look(ref pawn, "pawn", true);
Scribe_References.Look(ref internalThing, "internalThing", true); Scribe_References.Look(ref internalThing, "internalThing", true);
Scribe_Values.Look(ref volume, "volume", volume, 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 notcumthickness, "notcumthickness", notcumthickness, true);
Scribe_Values.Look(ref fertFactor, "fertFactor", fertFactor, true);
Scribe_Values.Look(ref notcum, "notcum", notcum, true); Scribe_Values.Look(ref notcum, "notcum", notcum, true);
Scribe_Values.Look(ref notcumLabel, "notcumLabel", notcumLabel, true); Scribe_Values.Look(ref notcumLabel, "notcumLabel", notcumLabel, true);
Scribe_Values.Look(ref useCustomColor, "useCustomColor", useCustomColor, true); Scribe_Values.Look(ref useCustomColor, "useCustomColor", useCustomColor, true);
@ -183,11 +178,11 @@ namespace RJW_Menstruation
cumthickness = cumthickness.LerpMultiple(DecayResist, 0.3f, speed); 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; if (updatefilthDef != null) filthDef = updatefilthDef;
volume += volumein; volume += volumein;
fertvolume += volumein*fertility; this.fertility = (this.volume * this.fertility + volumein * fertility) / (this.volume + volumein);
cumthickness = Mathf.Lerp(cumthickness, 1.0f, volumein / volume); cumthickness = Mathf.Lerp(cumthickness, 1.0f, volumein / volume);
} }
@ -195,12 +190,13 @@ namespace RJW_Menstruation
{ {
if (updatefilthDef != null) filthDef = updatefilthDef; if (updatefilthDef != null) filthDef = updatefilthDef;
volume += volumein; volume += volumein;
fertility = volume * fertility / (volume + volumein);
notcumthickness = Mathf.Lerp(notcumthickness, thickness, volumein / volume); notcumthickness = Mathf.Lerp(notcumthickness, thickness, volumein / volume);
} }
public bool ShouldRemove() 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; return false;
} }
@ -209,17 +205,16 @@ namespace RJW_Menstruation
{ {
float totalleak = volume; float totalleak = volume;
volume *= Math.Max(0, (1 - (Configurations.CumDecayRatio * (1 - DecayResist)) * leakfactor)); 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(); CutMinor();
totalleak -= volume; totalleak -= volume;
return totalleak; return totalleak;
} }
public float DismishForce(float portion, float leakfactor = 1.0f) public float DismishForce(float portion, float leakfactor = 1.0f)
{ {
float totalleak = volume; float totalleak = volume;
volume *= Math.Max(0, 1 - (portion * (1 - DecayResist/10)) * leakfactor); volume *= Math.Max(0, 1 - (portion * (1 - DecayResist / 10)) * leakfactor);
fertvolume *= Math.Max(0, 1 - (portion * (1 - DecayResist)) * leakfactor);
CutMinor(); CutMinor();
totalleak -= volume; totalleak -= volume;
return totalleak; return totalleak;
@ -227,24 +222,20 @@ namespace RJW_Menstruation
public void CumEffects(Pawn pawn) public void CumEffects(Pawn pawn)
{ {
if (!notcum && DNA != null && volume >= 1.0f) if (notcum || DNA == null || volume < 1.0f) return;
{
List<IngestionOutcomeDoer> doers = DNA.ingestionOutcomeDoers; List<IngestionOutcomeDoer> doers = DNA.ingestionOutcomeDoers;
if (!doers.NullOrEmpty()) for (int i = 0; i < doers.Count; i++) if (!doers.NullOrEmpty()) for (int i = 0; i < doers.Count; i++)
{ {
doers[i].DoIngestionOutcome(pawn, CumThing); doers[i].DoIngestionOutcome(pawn, CumThing);
} }
}
} }
protected void CutMinor() protected void CutMinor()
{ {
if (volume < 0.01f) volume = 0f; if (volume < 0.01f) volume = 0f;
if (fertvolume < 0.001f) fertvolume = 0f;
} }
} }
public class CumMixture : Cum, IDisposable public class CumMixture : Cum, IDisposable
@ -259,7 +250,7 @@ namespace RJW_Menstruation
cums = new List<string>(); 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.pawn = pawn;
this.volume = volume; this.volume = volume;
@ -272,7 +263,7 @@ namespace RJW_Menstruation
public void Dispose() public void Dispose()
{ {
cums.Clear(); cums.Clear();
} }
public override void ExposeData() public override void ExposeData()
@ -284,17 +275,12 @@ namespace RJW_Menstruation
public string GetIngredients() public string GetIngredients()
{ {
string res = ""; 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]; res += cums[i];
if (i < cums.Count - 1) res += ", "; if (i < cums.Count - 1) res += ", ";
} }
return 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)] [DebugAction("RJW Menstruation", "Set pawn's state to follicular", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
private static void SetFollicular(Pawn p) 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); 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)] [DebugAction("RJW Menstruation", "Set pawn's state to ovulatory", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
private static void SetOvulatory(Pawn p) 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); 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)] [DebugAction("RJW Menstruation", "Set pawn's state to luteal", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
private static void SetLuteal(Pawn p) 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); 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)] [DebugAction("RJW Menstruation", "Set pawn's state to bleeding", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
private static void SetBleeding(Pawn p) 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); 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)] [DebugAction("RJW Menstruation", "Remove all cum from pawn's womb", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
private static void RemoveCums(Pawn p) 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); 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)] [DebugAction("RJW Menstruation", "Add egg to pawn's next ovulation", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
private static void AddEgg(Pawn p) private static void AddEgg(Pawn p)
{ {
p.GetMenstruationComp().eggstack++; foreach (HediffComp_Menstruation comp in p.GetMenstruationComps())
Messages.Message($"1 egg added to {p}'s next ovulation ({p.GetMenstruationComp().eggstack})", MessageTypeDefOf.NeutralEvent, false); 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)] [DebugAction("RJW Menstruation", "Recalculate pawn's ovary power", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.Playing)]
private static void RecalculateOvaryPower(Pawn p) private static void RecalculateOvaryPower(Pawn p)
{ {
p.GetMenstruationComp().ovarypower = p.GetMenstruationComp().GetOvaryPowerByAge(p); foreach (HediffComp_Menstruation comp in p.GetMenstruationComps())
Messages.Message($"{p}'s ovarypower recalculated ({p.GetMenstruationComp().ovarypower})", MessageTypeDefOf.NeutralEvent, false); 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 RimWorld;
using System.Collections.Generic;
using RimWorld;
using Verse;
using rjw; using rjw;
using System.Collections.Generic;
using Verse;
namespace RJW_Menstruation namespace RJW_Menstruation
{ {
@ -10,18 +9,18 @@ namespace RJW_Menstruation
{ {
protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested)
{ {
HediffComp_Menstruation comp = pawn.GetMenstruationComp(); foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps())
if (comp != null && (comp.curStage.Equals(HediffComp_Menstruation.Stage.Follicular) if (comp.curStage.Equals(HediffComp_Menstruation.Stage.Follicular)
|| comp.curStage.Equals(HediffComp_Menstruation.Stage.Luteal) || comp.curStage.Equals(HediffComp_Menstruation.Stage.Luteal)
|| comp.curStage.Equals(HediffComp_Menstruation.Stage.ClimactericFollicular) || comp.curStage.Equals(HediffComp_Menstruation.Stage.ClimactericFollicular)
|| comp.curStage.Equals(HediffComp_Menstruation.Stage.ClimactericLuteal) || comp.curStage.Equals(HediffComp_Menstruation.Stage.ClimactericLuteal)
|| comp.curStage.Equals(HediffComp_Menstruation.Stage.Anestrus) || comp.curStage.Equals(HediffComp_Menstruation.Stage.Anestrus)
)) )
{ {
comp.SetEstrus(comp.Props.eggLifespanDays); comp.SetEstrus(comp.Props.eggLifespanDays);
comp.curStage = HediffComp_Menstruation.Stage.Ovulatory; comp.curStage = HediffComp_Menstruation.Stage.Ovulatory;
comp.ovarypower--; comp.ovarypower--;
} }
} }
} }
@ -29,16 +28,16 @@ namespace RJW_Menstruation
{ {
protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested)
{ {
HediffComp_Menstruation comp = pawn.GetMenstruationComp(); foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps())
if (comp != null && (comp.curStage.Equals(HediffComp_Menstruation.Stage.Follicular) if (comp.curStage.Equals(HediffComp_Menstruation.Stage.Follicular)
|| comp.curStage.Equals(HediffComp_Menstruation.Stage.ClimactericFollicular) || comp.curStage.Equals(HediffComp_Menstruation.Stage.ClimactericFollicular)
|| comp.curStage.Equals(HediffComp_Menstruation.Stage.Anestrus) || comp.curStage.Equals(HediffComp_Menstruation.Stage.Anestrus)
)) )
{ {
comp.SetEstrus(comp.Props.eggLifespanDays); comp.SetEstrus(comp.Props.eggLifespanDays);
comp.curStage = HediffComp_Menstruation.Stage.Ovulatory; comp.curStage = HediffComp_Menstruation.Stage.Ovulatory;
comp.eggstack += ingested.stackCount - 1; comp.eggstack += ingested.stackCount - 1;
} }
} }
} }
@ -62,11 +61,8 @@ namespace RJW_Menstruation
protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested)
{ {
HediffComp_Menstruation comp = pawn.GetMenstruationComp(); foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps())
if (Configurations.EnableMenopause && comp != null) if (Configurations.EnableMenopause) comp.RecoverOvary(1 + effectOffset);
{
comp.RecoverOvary(1 + effectOffset);
}
} }
} }
@ -74,13 +70,8 @@ namespace RJW_Menstruation
{ {
protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested)
{ {
HediffComp_Menstruation comp = pawn.GetMenstruationComp(); foreach (HediffComp_Menstruation comp in pawn.GetMenstruationComps())
if (comp != null)
{
comp.eggstack += Rand.Range(1, 4); comp.eggstack += Rand.Range(1, 4);
}
} }
} }
@ -88,27 +79,21 @@ namespace RJW_Menstruation
{ {
protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested)
{ {
List<Thought_Memory> memories = pawn.needs?.mood?.thoughts?.memories?.Memories.FindAll( List<Thought_Memory> memories = pawn.needs?.mood?.thoughts?.memories?.Memories.FindAll(
x => x =>
x.def == VariousDefOf.CameInsideF x.def == VariousDefOf.CameInsideF
|| x.def == VariousDefOf.CameInsideFFetish || x.def == VariousDefOf.CameInsideFFetish
|| x.def == VariousDefOf.HaterCameInsideF); || 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 (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 (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.Contexts;
using rjw.Modules.Interactions.Enums; using rjw.Modules.Interactions.Enums;
using rjw.Modules.Interactions.Rules.PartKindUsageRules; using rjw.Modules.Interactions.Rules.PartKindUsageRules;
using rjw.Modules.Shared; using rjw.Modules.Shared;
using System.Collections.Generic; using System.Collections.Generic;
using Verse;
namespace RJW_Menstruation.Interactions namespace RJW_Menstruation.Interactions
{ {

View file

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

View file

@ -1,10 +1,4 @@
using HugsLib; using RimWorld;
using RimWorld;
using rjw;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Verse; using Verse;
namespace RJW_Menstruation 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()) int breedingSeasons = 0;
{ if (Props.breedingSeason == SeasonalBreed.Always) breedingSeasons = 4;
GoNextStage(Stage.Anestrus);
return;
}
if (curStageHrs >= FollicularIntervalHours)
{
estrusflag = false;
lutealIntervalhours = PeriodRandomizer(lutealIntervalhours, Props.deviationFactor);
GoNextStage(Stage.Luteal);
}
else else
{ {
curStageHrs += Configurations.CycleAcceleration; if ((Props.breedingSeason & SeasonalBreed.Spring) != 0) breedingSeasons++;
if (!estrusflag && curStageHrs > FollicularIntervalHours - Props.estrusDaysBeforeOvulation * 24) if ((Props.breedingSeason & SeasonalBreed.Summer) != 0) breedingSeasons++;
{ if ((Props.breedingSeason & SeasonalBreed.Fall) != 0) breedingSeasons++;
estrusflag = true; if ((Props.breedingSeason & SeasonalBreed.Winter) != 0) breedingSeasons++;
SetEstrus(Props.eggLifespanDays + Props.estrusDaysBeforeOvulation);
}
StayCurrentStage();
} }
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) return 0;
{ }
RemoveClimactericEffect();
StayCurrentStage(); protected override void GoOvulatoryStage(bool climacteric)
} {
else if (curStageHrs >= (follicularIntervalhours - bleedingIntervalhours) * CycleFactor) estrusflag = false;
{ GoNextStage(climacteric ? Stage.ClimactericLuteal : Stage.Luteal);
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();
}
} }
protected override void AfterCumIn(Pawn cummer) protected override void AfterCumIn(Pawn cummer)
@ -99,7 +66,7 @@ namespace RJW_Menstruation
{ {
case Stage.Follicular: case Stage.Follicular:
case Stage.ClimactericFollicular: case Stage.ClimactericFollicular:
curStage = Stage.Ovulatory; GoNextStage(Stage.Ovulatory);
break; break;
} }
} }

View file

@ -1,47 +1,65 @@
using System; using RimWorld;
using rjw;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
using rjw;
using UnityEngine; using UnityEngine;
using Verse;
namespace RJW_Menstruation namespace RJW_Menstruation
{ {
public static class MenstruationUtility 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) 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")); return pawn.GetFirstMenstruationComp();
HediffComp_Menstruation result; }
if (hedifflist.NullOrEmpty()) return null;
else 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) HediffComp_Menstruation result = hediff.TryGetComp<HediffComp_Menstruation>();
{ if (result != null) yield return result;
result = h.TryGetComp<HediffComp_Menstruation>(); }
if (result != null) 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; 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 pregnancy?.pawn.GetMenstruationComps().FirstOrDefault(comp => comp.Pregnancy == pregnancy);
{
return hediff.TryGetComp<HediffComp_Menstruation>();
}
return null;
} }
public static HediffComp_Anus GetAnusComp(this Pawn pawn) 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; HediffComp_Anus result;
if (!hedifflist.NullOrEmpty()) if (!hedifflist.NullOrEmpty())
{ {
@ -63,18 +81,11 @@ namespace RJW_Menstruation
return null; return null;
} }
public static float GetFertilityChance(this HediffComp_Menstruation comp) 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) public static Texture2D GetPregnancyIcon(this HediffComp_Menstruation comp, Hediff hediff)
{ {
string icon = ""; string icon = "";
@ -157,19 +168,19 @@ namespace RJW_Menstruation
} }
public static Texture2D GetEggIcon(this HediffComp_Menstruation comp, bool includeOvary) 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.Pregnancy != null && !(comp.Pregnancy is Hediff_MechanoidPregnancy))
{ {
if (comp.parent.pawn.GetPregnancyProgress() < 0.2f) return ContentFinder<Texture2D>.Get("Eggs/Egg_Implanted00", true); if (comp.GetPregnancyProgress() < 0.2f) return ContentFinder<Texture2D>.Get("Eggs/Egg_Implanted00", true);
else return ContentFinder<Texture2D>.Get("Womb/Empty", true); else return ContentFinder<Texture2D>.Get("Womb/Empty", true);
} }
switch(comp.curStage) switch (comp.curStage)
{ {
case HediffComp_Menstruation.Stage.Follicular: case HediffComp_Menstruation.Stage.Follicular:
case HediffComp_Menstruation.Stage.ClimactericFollicular: case HediffComp_Menstruation.Stage.ClimactericFollicular:
if (!includeOvary) break; if (!includeOvary) break;
if (comp is HediffComp_InducedOvulator) 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); return ContentFinder<Texture2D>.Get("Ovaries/Ovary_01", true);
else break; else break;
case HediffComp_Menstruation.Stage.Ovulatory: 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) 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); if (hediff == null) return ContentFinder<Texture2D>.Get("Genitals/Vagina00", true);
//HediffComp_Menstruation comp = hediff.GetMenstruationComp(); //HediffComp_Menstruation comp = hediff.GetMenstruationComp();
string icon; string icon;
@ -237,37 +248,32 @@ namespace RJW_Menstruation
public static Texture2D GetAnalIcon(this Pawn pawn, bool drawOrigin = false) 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")); Hediff hediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_anusBPR(pawn)).FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("anus"));
if (hediff != null) if (hediff == null) return ContentFinder<Texture2D>.Get(("Genitals/Anal00"), 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
{
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); 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 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) 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; 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) public static bool IsInEstrus(this Pawn pawn, bool visible = true)
{ {
if (pawn.Dead) return false; if (pawn.Dead) return false;

View file

@ -17,21 +17,26 @@ namespace RJW_Menstruation
protected void PregnancyThought() 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) pawn.needs.mood.thoughts.memories.TryGainMemory(VariousDefOf.UnwantedPregnancyMild);
{
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);
}
}
} }
else
{
pawn.needs.mood.thoughts.memories.TryGainMemory(VariousDefOf.UnwantedPregnancy);
}
}
public override void Miscarry()
{
this.GetMenstruationComp().Pregnancy = null;
base.Miscarry();
} }
public override void GiveBirth() public override void GiveBirth()
@ -47,42 +52,43 @@ namespace RJW_Menstruation
Initialize(pawn, father); Initialize(pawn, father);
} }
List<Pawn> siblings = new List<Pawn>();
foreach (Pawn baby in babies) foreach (Pawn baby in babies)
{ {
if (xxx.is_animal(baby)) if (xxx.is_animal(baby))
{ {
BestialBirth(baby, siblings); BestialBirth(baby);
} }
else else
{ {
HumanlikeBirth(baby, siblings); HumanlikeBirth(baby);
} }
baby.ageTracker.AgeChronologicalTicks = 0; baby.ageTracker.AgeChronologicalTicks = 0;
} }
pawn.health.RemoveHediff(this); pawn.health.RemoveHediff(this);
HediffComp_Menstruation comp = this.GetMenstruationComp();
if(comp != null) comp.Pregnancy = null;
} }
public string GetBabyInfo() public string GetBabyInfo()
{ {
if (babies.NullOrEmpty())
return "Null";
string res = ""; 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 num = babies.Where(x => x.def.Equals(baby.def)).Count();
int iteration = 0; if (iteration > 0) res += ", ";
foreach (Pawn baby in babiesdistinct) res += num + " " + baby.def.label;
{ iteration++;
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;
} }
return "Null"; res += " " + Translations.Dialog_WombInfo02;
return res;
} }
public string GetFatherInfo() public string GetFatherInfo()
@ -95,7 +101,7 @@ namespace RJW_Menstruation
if (!is_parent_known && Configurations.InfoDetail != Configurations.DetailLevel.All) if (!is_parent_known && Configurations.InfoDetail != Configurations.DetailLevel.All)
return res + Translations.Dialog_FatherUnknown; return res + Translations.Dialog_FatherUnknown;
var babiesdistinct = babies.Distinct(new FatherComparer(pawn)); IEnumerable<Pawn> babiesdistinct = babies.Distinct(new FatherComparer(pawn));
int iteration = 0; int iteration = 0;
foreach (Pawn baby in babiesdistinct) foreach (Pawn baby in babiesdistinct)
{ {
@ -106,7 +112,7 @@ namespace RJW_Menstruation
return res; return res;
} }
private void HumanlikeBirth(Pawn baby, List<Pawn> siblings) private void HumanlikeBirth(Pawn baby)
{ {
Pawn mother = pawn; Pawn father = Utility.GetFather(baby, pawn); Pawn mother = pawn; Pawn father = Utility.GetFather(baby, pawn);
//backup melanin, LastName for when baby reset by other mod on spawn/backstorychange //backup melanin, LastName for when baby reset by other mod on spawn/backstorychange
@ -115,7 +121,7 @@ namespace RJW_Menstruation
PawnUtility.TrySpawnHatchedOrBornPawn(baby, mother); 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) if (mother.Faction != null && !(mother.Faction?.IsPlayer ?? false) && sex_need != null)
{ {
sex_need.CurLevel = 1.0f; sex_need.CurLevel = 1.0f;
@ -144,17 +150,13 @@ namespace RJW_Menstruation
baby.guest.SetGuestStatus(Faction.OfPlayer, GuestStatus.Prisoner); baby.guest.SetGuestStatus(Faction.OfPlayer, GuestStatus.Prisoner);
} }
foreach (Pawn sibling in siblings) if (xxx.is_human(mother)) TaleRecorder.RecordTale(TaleDefOf.GaveBirth, new object[] { mother, baby });
{
baby.relations.AddDirectRelation(PawnRelationDefOf.Sibling, sibling);
}
siblings.Add(baby);
PostBirth(mother, father, 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); Pawn mother = pawn; Pawn father = Utility.GetFather(baby, pawn);
//backup melanin, LastName for when baby reset by other mod on spawn/backstorychange //backup melanin, LastName for when baby reset by other mod on spawn/backstorychange
@ -174,14 +176,6 @@ namespace RJW_Menstruation
baby.SetFaction(mother.Faction); 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); Train(baby, mother);
PostBirth(mother, father, baby); PostBirth(mother, father, baby);
@ -198,7 +192,6 @@ namespace RJW_Menstruation
List<Trait> momtraits = new List<Trait>(); List<Trait> momtraits = new List<Trait>();
List<Trait> poptraits = new List<Trait>(); List<Trait> poptraits = new List<Trait>();
List<Trait> traits_to_inherit = 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_momtraits_inherited = RJWPregnancySettings.max_num_momtraits_inherited;
float max_num_poptraits_inherited = RJWPregnancySettings.max_num_poptraits_inherited; float max_num_poptraits_inherited = RJWPregnancySettings.max_num_poptraits_inherited;
float max_num_traits_inherited = max_num_momtraits_inherited + 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; i = 1;
while (momtraits.Count > 0 && i <= max_num_momtraits_inherited) 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]); traits_to_inherit.Add(momtraits[rand_trait_index]);
momtraits.RemoveAt(rand_trait_index); momtraits.RemoveAt(rand_trait_index);
} }
@ -236,7 +229,7 @@ namespace RJW_Menstruation
j = 1; j = 1;
while (poptraits.Count > 0 && j <= max_num_poptraits_inherited) 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]); traits_to_inherit.Add(poptraits[rand_trait_index]);
poptraits.RemoveAt(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) 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])) if (!traits_to_inherit.Contains(momtraits[rand_trait_index]))
{ {
traits_to_inherit.Add(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) 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])) if (!traits_to_inherit.Contains(poptraits[rand_trait_index]))
{ {
traits_to_inherit.Add(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) 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);
{ }
baby.training.Train(TrainableDefOf.Obedience, mother); if (xxx.is_human(mother) && baby.Faction == Faction.OfPlayer && baby.training.CanAssignToTrain(TrainableDefOf.Tameness, out _).Accepted)
} {
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.Tameness, mother);
}
} }
} }
@ -352,7 +344,7 @@ namespace RJW_Menstruation
kind: BabyPawnKindDecider(mother, father), kind: BabyPawnKindDecider(mother, father),
//fixedIdeo: mother.Ideo, //fixedIdeo: mother.Ideo,
//forbidAnyTitle: true, //forbidAnyTitle: true,
forceNoBackstory:true forceNoBackstory: true
); );
int division = 1; int division = 1;
@ -363,7 +355,7 @@ namespace RJW_Menstruation
string firstheadpath = null; string firstheadpath = null;
string firstHARcrown = null; string firstHARcrown = null;
int traitSeed = Rand.Int; 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++; while (Rand.Chance(Configurations.EnzygoticTwinsChance) && division < Configurations.MaxEnzygoticTwins) division++;
for (int i = 0; i < division; i++) 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) public Pawn GenerateBaby(PawnGenerationRequest request, Pawn mother, Pawn father, List<Trait> parentTraits, int traitSeed)
{ {
Pawn baby = PawnGenerator.GeneratePawn(request); 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 (father.gender != Gender.Female) baby.SetFather(father);
if (mother != father) else baby.relations.AddDirectRelation(PawnRelationDefOf.Parent, 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();
} }
} }
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; return baby;
} }
@ -457,7 +447,10 @@ namespace RJW_Menstruation
/// <returns></returns> /// <returns></returns>
public PawnKindDef BabyPawnKindDecider(Pawn mother, Pawn father) 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; int flag = 0;
if (xxx.is_human(mother)) flag += 2; if (xxx.is_human(mother)) flag += 2;
@ -471,18 +464,18 @@ namespace RJW_Menstruation
switch (flag) switch (flag)
{ {
case 3: 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; break;
case 2: case 2:
if (RJWPregnancySettings.bestiality_DNA_inheritance == 0f) 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 = father.kindDef; else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
break; break;
case 1: case 1:
if (RJWPregnancySettings.bestiality_DNA_inheritance == 1f) 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 = father.kindDef; else if (!Rand.Chance(RJWPregnancySettings.bestial_DNA_from_mother)) spawn_kind_def = fatherKindDef;
break; break;
case 0: 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; break;
} }
@ -490,19 +483,19 @@ namespace RJW_Menstruation
bool IsAndroidfather = AndroidsCompatibility.IsAndroid(father); bool IsAndroidfather = AndroidsCompatibility.IsAndroid(father);
if (IsAndroidmother && !IsAndroidfather) if (IsAndroidmother && !IsAndroidfather)
{ {
spawn_kind_def = father.kindDef; spawn_kind_def = fatherKindDef;
} }
else if (!IsAndroidmother && IsAndroidfather) else if (!IsAndroidmother && IsAndroidfather)
{ {
spawn_kind_def = mother.kindDef; spawn_kind_def = motherKindDef;
} }
string MotherRaceName = ""; string MotherRaceName = "";
string FatherRaceName = ""; string FatherRaceName = "";
MotherRaceName = mother.kindDef?.race?.defName; MotherRaceName = motherKindDef?.race?.defName;
PawnKindDef non_hybrid_kind_def = spawn_kind_def; PawnKindDef non_hybrid_kind_def = spawn_kind_def;
if (father != null) if (father != null)
FatherRaceName = father.kindDef?.race?.defName; FatherRaceName = fatherKindDef?.race?.defName;
if (FatherRaceName != "" && Configurations.UseHybridExtention) if (FatherRaceName != "" && Configurations.UseHybridExtention)
@ -516,24 +509,24 @@ namespace RJW_Menstruation
if (!Configurations.UseHybridExtention || spawn_kind_def == null) if (!Configurations.UseHybridExtention || spawn_kind_def == null)
{ {
spawn_kind_def = non_hybrid_kind_def; 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()); //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)) if ((t.hybridRaceParents.Contains(MotherRaceName) && t.hybridRaceParents.Contains(FatherRaceName))
|| (t.hybridRaceParents.Contains("Any") && (t.hybridRaceParents.Contains(MotherRaceName) || t.hybridRaceParents.Contains(FatherRaceName)))) || (t.hybridRaceParents.Contains("Any") && (t.hybridRaceParents.Contains(MotherRaceName) || t.hybridRaceParents.Contains(FatherRaceName))))
{ {
//ModLog.Message(" has hybridRaceParents"); //ModLog.Message(" has hybridRaceParents");
if (t.hybridChildKindDef.Contains("MotherKindDef")) if (t.hybridChildKindDef.Contains("MotherKindDef"))
spawn_kind_def = mother.kindDef; spawn_kind_def = motherKindDef;
else if (t.hybridChildKindDef.Contains("FatherKindDef") && father != null) else if (t.hybridChildKindDef.Contains("FatherKindDef") && father != null)
spawn_kind_def = father.kindDef; spawn_kind_def = fatherKindDef;
else else
{ {
//ModLog.Message(" trying hybridChildKindDef " + t.defName); //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))); child_kind_def_list.AddRange(DefDatabase<PawnKindDef>.AllDefs.Where(x => t.hybridChildKindDef.Contains(x.defName)));
//ModLog.Message(" found custom hybridChildKindDefs " + t.hybridChildKindDef.Count); //ModLog.Message(" found custom hybridChildKindDefs " + t.hybridChildKindDef.Count);
@ -547,20 +540,20 @@ namespace RJW_Menstruation
} }
else if (!Configurations.UseHybridExtention || spawn_kind_def == null) 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")) if (spawn_kind_def.defName.Contains("Nymph"))
{ {
//child is nymph, try to find other PawnKindDef //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"))); 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 //no other PawnKindDef found try mother
if (spawn_kind_def_list.NullOrEmpty()) 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 //no other PawnKindDef found try father
if (spawn_kind_def_list.NullOrEmpty() && father != null) 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 //no other PawnKindDef found fallback to generic colonist
if (spawn_kind_def_list.NullOrEmpty()) if (spawn_kind_def_list.NullOrEmpty())
spawn_kind_def = PawnKindDefOf.Colonist; 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(); if (!spawn_kind_def_list.NullOrEmpty()) spawn_kind_def = spawn_kind_def_list.RandomElement();
} }
return spawn_kind_def; return spawn_kind_def;
} }
@ -638,17 +628,17 @@ namespace RJW_Menstruation
parentTraitPool.RemoveAll(x => x.ScenForced); parentTraitPool.RemoveAll(x => x.ScenForced);
int numberInherited; int numberInherited;
if (parentTraitPool != null) 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 else
numberInherited = 0; numberInherited = 0;
//Game suggested traits. //Game suggested traits.
var forcedTraits = personalTraitPool IEnumerable<Trait> forcedTraits = personalTraitPool
.Where(x => x.ScenForced) .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 .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>(); 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 selectedTraits.AddRange(forcedTraits); // enforcing scenario forced traits
for (int i = 0; i < numberInherited; i++) // add parent traits first 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) while (selectedTraits.Count < traitLimit && personalTraitPool.Count > 0)
{ {
int index = Rand.Range(0, personalTraitPool.Count); // getting trait and removing from the pull 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); personalTraitPool.RemoveAt(index);
if (!selectedTraits.Any(x => comparer.Equals(x, trait) || // skipping traits conflicting with already added if (!selectedTraits.Any(x => comparer.Equals(x, trait) || // skipping traits conflicting with already added
x.def.ConflictsWith(trait))) x.def.ConflictsWith(trait)))
selectedTraits.Add(new Trait(trait.def, trait.Degree, false)); selectedTraits.Add(new Trait(trait.def, trait.Degree, false));
} }
pawn.story.traits.allTraits = selectedTraits; pawn.story.traits.allTraits = selectedTraits;

View file

@ -1,24 +1,18 @@
using System; using RimWorld;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse; using Verse;
using rjw;
namespace RJW_Menstruation namespace RJW_Menstruation
{ {
public class IngestionOutcomeDoer_GiveHediff_StackCount : IngestionOutcomeDoer_GiveHediff public class IngestionOutcomeDoer_GiveHediff_StackCount : IngestionOutcomeDoer_GiveHediff
{ {
protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested) protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested)
{ {
Hediff hediff = HediffMaker.MakeHediff(hediffDef, pawn); Hediff hediff = HediffMaker.MakeHediff(hediffDef, pawn);
float effect = ((!(severity > 0f)) ? hediffDef.initialSeverity : severity) * ingested.stackCount; float effect = ((!(severity > 0f)) ? hediffDef.initialSeverity : severity) * ingested.stackCount;
AddictionUtility.ModifyChemicalEffectForToleranceAndBodySize(pawn, toleranceChemical, ref effect); AddictionUtility.ModifyChemicalEffectForToleranceAndBodySize(pawn, toleranceChemical, ref effect);
hediff.Severity = effect; hediff.Severity = effect;
pawn.health.AddHediff(hediff); 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;
using Verse.AI; using Verse.AI;
@ -16,11 +17,10 @@ namespace RJW_Menstruation
protected override IEnumerable<Toil> MakeNewToils() protected override IEnumerable<Toil> MakeNewToils()
{ {
List<HediffComp_Menstruation> comps = pawn.GetMenstruationComps().ToList();
HediffComp_Menstruation Comp = pawn.GetMenstruationComp();
this.FailOn(delegate 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 Toil excreting = Toils_General.Wait(excretingTime, TargetIndex.None);//duration of
@ -30,8 +30,9 @@ namespace RJW_Menstruation
{ {
initAction = delegate () initAction = delegate ()
{ {
Comp.CumOut(null, 0.5f); foreach (HediffComp_Menstruation comp in comps)
if (Comp.TotalCumPercent > 0.001) JumpToToil(excreting); comp.CumOut(null, 0.5f);
if (comps.Any(comp => comp.TotalCumPercent > 0.001)) JumpToToil(excreting);
} }
}; };
//yield return excreting; //yield return excreting;
@ -107,7 +108,7 @@ namespace RJW_Menstruation
protected virtual void Finish() protected virtual void Finish()
{ {
if(pawn.CurJobDef == JobDefOf.Wait_MaintainPosture) if (pawn.CurJobDef == JobDefOf.Wait_MaintainPosture)
{ {
pawn.jobs.EndCurrentJob(JobCondition.InterruptForced); pawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -2,12 +2,12 @@
using rjw; using rjw;
using rjw.Modules.Interactions.Enums; using rjw.Modules.Interactions.Enums;
using rjw.Modules.Interactions.Objects; using rjw.Modules.Interactions.Objects;
using Verse;
using UnityEngine;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Reflection.Emit; using System.Reflection.Emit;
using UnityEngine;
using Verse;
namespace RJW_Menstruation namespace RJW_Menstruation
{ {
@ -15,22 +15,28 @@ namespace RJW_Menstruation
[HarmonyPatch(typeof(PregnancyHelper), nameof(PregnancyHelper.impregnate))] [HarmonyPatch(typeof(PregnancyHelper), nameof(PregnancyHelper.impregnate))]
public static class Impregnate_Patch 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; xxx.rjwSextype sextype = props.sexType;
Pawn pawn = props.pawn; Pawn pawn = props.pawn;
Pawn partner = props.partner; 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 (sextype != xxx.rjwSextype.Vaginal && sextype != xxx.rjwSextype.DoublePenetration) return true;
if (partner.IsAnimal() && !Configurations.EnableAnimalCycle) return true; if (partner.IsAnimal() && !Configurations.EnableAnimalCycle) return true;
if (!InteractionCanCausePregnancy(props)) return false; 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(); HediffComp_Menstruation comp;
if (comp is null) return true; 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)) 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); else comp.CumIn(pawn, pawn.GetCumVolume(pawnparts), 0);
return true; 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> /// <summary>
@ -85,31 +101,59 @@ namespace RJW_Menstruation
public static bool Prefix(Pawn pawn, Pawn partner) // partner has vagina public static bool Prefix(Pawn pawn, Pawn partner) // partner has vagina
{ {
if (partner.IsAnimal() && !Configurations.EnableAnimalCycle) return true; if (partner.IsAnimal() && !Configurations.EnableAnimalCycle) return true;
HediffComp_Menstruation comp = partner.GetMenstruationComp(); HediffComp_Menstruation comp;
if (comp != null) 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)) if (Configurations.Debug) ModLog.Message("used original rjw method: Comp missing");
{ return true;
comp.CumIn(pawn, pawn.GetCumVolume(), 0); }
return false; else if (AndroidsCompatibility.IsAndroid(pawn) && !AndroidsCompatibility.AndroidPenisFertility(pawn))
} {
else comp.CumIn(pawn, pawn.GetCumVolume(), pawn.health.capacities.GetLevel(xxx.reproduction)); comp.CumIn(pawn, pawn.GetCumVolume(), 0);
return false; return false;
} }
ModLog.Message("used original rjw method: Comp missing"); else comp.CumIn(pawn, pawn.GetCumVolume(), pawn.health.capacities.GetLevel(xxx.reproduction));
return true; 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))] [HarmonyPatch(typeof(Hediff_BasePregnancy), nameof(Hediff_BasePregnancy.PostBirth))]
public static class RJW_Patch_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) if (Configurations.EnableBirthVaginaMorph)
{ {
Hediff vagina = mother.health.hediffSet.hediffs.FirstOrFallback(x => x.def.defName.ToLower().Contains("vagina")); // The comp still has the pregnancy attached at this point in the process
float morph = Mathf.Max(baby.BodySize - Mathf.Pow(vagina.Severity * mother.BodySize,2), 0f); 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; 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. // This is stricter than can_impregnate, so quickly filter out scenarios that are negative anyways.
if (__result == false || __instance != Quirk.ImpregnationFetish) return; if (__result == false || __instance != Quirk.ImpregnationFetish) return;
__result = __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--; else __result--;
if ( 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++; __result++;
} }
} }
@ -176,7 +220,7 @@ namespace RJW_Menstruation
{ {
__result *= (1f + GetNetFertility(fucker, fucked) / 40); __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; __result *= 1.25f;
} }
@ -195,10 +239,11 @@ namespace RJW_Menstruation
private static readonly FieldInfo MinimumFuckabilityToHookup = AccessTools.Field(typeof(RJWHookupSettings), nameof(RJWHookupSettings.MinimumFuckabilityToHookup)); private static readonly FieldInfo MinimumFuckabilityToHookup = AccessTools.Field(typeof(RJWHookupSettings), nameof(RJWHookupSettings.MinimumFuckabilityToHookup));
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{ {
if (MinimumFuckabilityToHookup == null) throw new System.InvalidOperationException("MinimumFuckabilityToHookup not found");
bool first_fuckability = true; 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 // The first load will be for the estrus-haver considering a partner, the second for a pawn considering the estrus-haver
yield return new CodeInstruction(first_fuckability ? OpCodes.Ldarg_0 : OpCodes.Ldarg_1); yield return new CodeInstruction(first_fuckability ? OpCodes.Ldarg_0 : OpCodes.Ldarg_1);
@ -230,14 +275,16 @@ namespace RJW_Menstruation
private static readonly FieldInfo MinimumRelationshipToHookup = AccessTools.Field(typeof(RJWHookupSettings), nameof(RJWHookupSettings.MinimumRelationshipToHookup)); private static readonly FieldInfo MinimumRelationshipToHookup = AccessTools.Field(typeof(RJWHookupSettings), nameof(RJWHookupSettings.MinimumRelationshipToHookup));
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) 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; LocalBuilder pawn_index = null;
// Like in the last one, we switch the arguments around for the second load // Like in the last one, we switch the arguments around for the second load
bool first_attractiveness = true; bool first_attractiveness = true;
bool first_relationship = 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 // 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 { // a future RJW or compiler update might change this, or maybe another mod's patch
pawn_index = (LocalBuilder)instruction.operand; pawn_index = (LocalBuilder)instruction.operand;
yield return instruction; yield return instruction;
@ -252,7 +299,7 @@ namespace RJW_Menstruation
yield return CodeInstruction.Call(typeof(FindBestPartner_Patch), nameof(AttractivenessThreshold)); yield return CodeInstruction.Call(typeof(FindBestPartner_Patch), nameof(AttractivenessThreshold));
first_attractiveness = false; first_attractiveness = false;
} }
else if (instruction.LoadsField(MinimumRelationshipToHookup)) else if (instruction.LoadsField(MinimumRelationshipToHookup))
{ {
if (pawn_index?.LocalType != typeof(Pawn)) 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))] [HarmonyPatch(typeof(CompHediffBodyPart), nameof(CompHediffBodyPart.updatesize))]
public static class Updatesize_Patch public static class Updatesize_Patch
{ {

View file

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

View file

@ -1,11 +1,7 @@
using System; using RimWorld;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
using rjw; using rjw;
using System.Collections.Generic;
using Verse;
namespace RJW_Menstruation namespace RJW_Menstruation
@ -23,7 +19,7 @@ namespace RJW_Menstruation
BodyPartRecord part = Genital_Helper.get_breastsBPR(pawn); BodyPartRecord part = Genital_Helper.get_breastsBPR(pawn);
if (part != null) if (part != null)
{ {
if (pawn.GetBreastComp() != null) yield return part; 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) public static object GetPropertyValue(this Type type, string name)
{ {
BindingFlags flags = BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; 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); return propertyInfo?.GetValue(null);
} }
public static object GetPropertyValue(this object obj, string name) public static object GetPropertyValue(this object obj, string name)
{ {
BindingFlags flags = BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; 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); return propertyInfo?.GetValue(obj);
} }

View file

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

View file

@ -1,8 +1,7 @@
using System; using RimWorld;
using System.Xml;
using System.Collections.Generic;
using RimWorld;
using rjw; using rjw;
using System.Collections.Generic;
using System.Xml;
using UnityEngine; using UnityEngine;
using Verse; using Verse;
@ -20,10 +19,7 @@ namespace RJW_Menstruation
public HybridExtension GetHybridExtension(string race) public HybridExtension GetHybridExtension(string race)
{ {
if (hybridExtension.NullOrEmpty()) return null; if (hybridExtension.NullOrEmpty()) return null;
else else return hybridExtension.Find(x => x.thingDef.defName.Equals(race));
{
return hybridExtension.Find(x => x.thingDef.defName.Equals(race));
}
} }
public PawnKindDef GetHybridWith(string race) public PawnKindDef GetHybridWith(string race)
@ -67,21 +63,15 @@ namespace RJW_Menstruation
{ {
DirectXmlCrossRefLoader.RegisterObjectWantsCrossRef(this, "thingDef", xmlRoot.Name); DirectXmlCrossRefLoader.RegisterObjectWantsCrossRef(this, "thingDef", xmlRoot.Name);
XmlNodeList childNodes = xmlRoot.ChildNodes; XmlNodeList childNodes = xmlRoot.ChildNodes;
if (childNodes.Count >= 1) foreach (XmlNode node in childNodes) if (childNodes.Count >= 1) foreach (XmlNode node in childNodes)
{ {
#if DEBUG #if DEBUG
Log.Message(xmlRoot.Name + "HybridInfo: " + node.Name + " " + node.InnerText); Log.Message(xmlRoot.Name + "HybridInfo: " + node.Name + " " + node.InnerText);
#endif #endif
hybridInfo.Add(node.Name, ParseHelper.FromString<float>(node.InnerText)); hybridInfo.Add(node.Name, ParseHelper.FromString<float>(node.InnerText));
} }
} }
} }
public class HybridInformations : IExposable public class HybridInformations : IExposable
@ -145,9 +135,6 @@ namespace RJW_Menstruation
Scribe_Values.Look(ref thingDefName, "thingDefName"); Scribe_Values.Look(ref thingDefName, "thingDefName");
Scribe_Collections.Look(ref hybridExtension, "hybridExtension", LookMode.Deep, new object[0]); Scribe_Collections.Look(ref hybridExtension, "hybridExtension", LookMode.Deep, new object[0]);
} }
} }
public class HybridExtensionExposable : HybridExtension, IExposable public class HybridExtensionExposable : HybridExtension, IExposable
@ -197,10 +184,6 @@ namespace RJW_Menstruation
} }
} }
public class AbsorberModExtension : DefModExtension public class AbsorberModExtension : DefModExtension
{ {
public bool leakAfterDirty = false; public bool leakAfterDirty = false;
@ -222,14 +205,12 @@ namespace RJW_Menstruation
public Color fluidColor = Color.white; public Color fluidColor = Color.white;
public virtual void DirtyEffect() { } public virtual void DirtyEffect() { }
public virtual void WearEffect() public virtual void WearEffect()
{ {
absorbedfluids += 0.1f; absorbedfluids += 0.1f;
if(dirty) wearhours++; if (dirty) wearhours++;
} }
public override Color DrawColorTwo => fluidColor; public override Color DrawColorTwo => fluidColor;
@ -250,7 +231,7 @@ namespace RJW_Menstruation
public override void WearEffect() public override void WearEffect()
{ {
if(dirty) wearhours++; if (dirty) wearhours++;
absorbedfluids += 0.5f; absorbedfluids += 0.5f;
} }
@ -299,13 +280,5 @@ namespace RJW_Menstruation
color = value; 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_Ovulatory = "Stage_Ovulatory".Translate();
public static readonly string Stage_Luteal = "Stage_Luteal".Translate(); public static readonly string Stage_Luteal = "Stage_Luteal".Translate();
public static readonly string Stage_Bleeding = "Stage_Bleeding".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_Pregnant = "Stage_Pregnant".Translate();
public static readonly string Stage_Recover = "Stage_Recover".Translate(); public static readonly string Stage_Recover = "Stage_Recover".Translate();
public static readonly string Stage_None = "Stage_None".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_1 = "Option23_Label_1".Translate();
public static readonly string Option23_Label_2 = "Option23_Label_2".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_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_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_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_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_Label = "Option28_Label".Translate();
public static readonly string Option28_Tooltip = "Option28_Tooltip".Translate(); public static readonly string Option28_Tooltip = "Option28_Tooltip".Translate();
public static readonly string Option29_Label = "Option29_Label".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_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_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_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_EnableGatherCumGizmo_Label = "Option_EnableGatherCumGizmo_Label".Translate();
public static readonly string Option_EstrusOverride_Label = "Option_EstrusOverride_Label".Translate(); public static readonly string Option_EstrusOverride_Label = "Option_EstrusOverride_Label".Translate();
public static readonly string Option_EstrusOverride_Desc = "Option_EstrusOverride_Desc".Translate(); public static readonly string Option_EstrusOverride_Desc = "Option_EstrusOverride_Desc".Translate();

View file

@ -1,10 +1,7 @@
using System; using RimWorld;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using rjw;
using UnityEngine; using UnityEngine;
using Verse; using Verse;
using Verse.Sound; using Verse.Sound;
@ -26,17 +23,11 @@ namespace RJW_Menstruation
public void BuildRaceList() public void BuildRaceList()
{ {
raceList.Clear(); raceList.Clear();
if (!VariousDefOf.AllRaces.NullOrEmpty()) if (!VariousDefOf.AllRaces.NullOrEmpty())
foreach(ThingDef def in VariousDefOf.AllRaces) foreach (ThingDef def in VariousDefOf.AllRaces)
{ {
if (def.race != null) if (def.race == null || Configurations.IsOverrideExist(def)) continue;
{ raceList.Add(new FloatMenuOption(def.label, delegate { AddHybridOverride(def); }, def.uiIcon, Color.white));
if (Configurations.IsOverrideExist(def)) continue;
else
{
raceList.Add(new FloatMenuOption(def.label, delegate { AddHybridOverride(def);}, def.uiIcon, Color.white ));
}
}
} }
raceList.SortBy(x => x.Label); raceList.SortBy(x => x.Label);
} }
@ -44,17 +35,15 @@ namespace RJW_Menstruation
public void AddHybridOverride(ThingDef def) public void AddHybridOverride(ThingDef def)
{ {
FloatMenuOption option = raceList.FirstOrDefault(x => x.Label.Equals(def?.label)); 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); Configurations.HybridOverride = new List<HybridInformations>();
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.Add(new HybridInformations(def));
Configurations.HybridOverride.SortBy(x => x.GetDef?.label ?? "Undefined");
} }
public override Vector2 InitialSize public override Vector2 InitialSize
@ -124,7 +113,7 @@ namespace RJW_Menstruation
buttonRect.x -= 100; buttonRect.x -= 100;
if (Widgets.ButtonText(buttonRect, "Undo")) if (Widgets.ButtonText(buttonRect, "Undo"))
{ {
var element = removeList.Last(); HybridInformations element = removeList.Last();
Configurations.HybridOverride.Add(element); Configurations.HybridOverride.Add(element);
Configurations.HybridOverride.SortBy(x => x.GetDef?.label ?? "Undefined"); Configurations.HybridOverride.SortBy(x => x.GetDef?.label ?? "Undefined");
removeList.Remove(element); 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 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(); Listing_Standard listmain = new Listing_Standard();
Widgets.BeginScrollView(outRect, ref scroll, mainRect); Widgets.BeginScrollView(outRect, ref scroll, mainRect);
listmain.Begin(mainRect); listmain.Begin(mainRect);
if (!Configurations.HybridOverride.NullOrEmpty()) if (!Configurations.HybridOverride.NullOrEmpty())
foreach(HybridInformations extension in Configurations.HybridOverride) 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(); Widgets.EndScrollView();
listmain.End(); listmain.End();
@ -266,7 +255,7 @@ namespace RJW_Menstruation
SoundDefOf.TabClose.PlayOneShotOnCamera(); SoundDefOf.TabClose.PlayOneShotOnCamera();
Find.WindowStack.Add(new Dialog_EditHybrid(info)); Find.WindowStack.Add(new Dialog_EditHybrid(info));
} }
} }
@ -279,18 +268,19 @@ namespace RJW_Menstruation
protected void BuildRaceList() protected void BuildRaceList()
{ {
raceList.Clear(); raceList.Clear();
if (!VariousDefOf.AllRaces.NullOrEmpty()) if (VariousDefOf.AllRaces.NullOrEmpty()) return;
foreach (ThingDef def in VariousDefOf.AllRaces)
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; raceList.Add(new FloatMenuOption(def.label, delegate { AddHybridInfo(def); }, Widgets.GetIconFor(def), Color.white));
else
{
raceList.Add(new FloatMenuOption(def.label, delegate { AddHybridInfo(def); }, Widgets.GetIconFor(def), Color.white));
}
} }
} }
}
raceList.SortBy(x => x.Label); raceList.SortBy(x => x.Label);
} }
@ -320,11 +310,11 @@ namespace RJW_Menstruation
buttonRect.x -= 100; buttonRect.x -= 100;
if (Widgets.ButtonText(buttonRect, "Undo")) if (Widgets.ButtonText(buttonRect, "Undo"))
{ {
var element = removeList.Last(); HybridExtensionExposable element = removeList.Last();
info.hybridExtension.Add(element); info.hybridExtension.Add(element);
removeList.Remove(element); removeList.Remove(element);
} }
foreach (HybridExtensionExposable element in removeList) foreach (HybridExtensionExposable element in removeList)
{ {
info.hybridExtension.Remove(element); info.hybridExtension.Remove(element);
@ -333,7 +323,7 @@ namespace RJW_Menstruation
float additionalHeight = 0f; 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; additionalHeight += (e.hybridInfo?.Count() ?? 1) * rowH;
} }
@ -356,7 +346,7 @@ namespace RJW_Menstruation
} }
Widgets.EndScrollView(); Widgets.EndScrollView();
listmain.End(); listmain.End();
} }
@ -376,7 +366,7 @@ namespace RJW_Menstruation
if (Widgets.ButtonText(buttonRect, "Add")) if (Widgets.ButtonText(buttonRect, "Add"))
{ {
List<FloatMenuOption> list = new List<FloatMenuOption>(); 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) if (def.race != null)
{ {
@ -392,7 +382,7 @@ namespace RJW_Menstruation
list.SortBy(x => x.Label); list.SortBy(x => x.Label);
Find.WindowStack.Add(new FloatMenu(list)); Find.WindowStack.Add(new FloatMenu(list));
} }
} }
buttonRect.x -= 80f; buttonRect.x -= 80f;
@ -403,18 +393,18 @@ namespace RJW_Menstruation
if (!extension.hybridInfo.EnumerableNullOrEmpty()) if (!extension.hybridInfo.EnumerableNullOrEmpty())
{ {
totalWeight = 0; totalWeight = 0;
foreach(KeyValuePair<string,float> element in extension.hybridInfo) foreach (KeyValuePair<string, float> element in extension.hybridInfo)
{ {
totalWeight += element.Value; totalWeight += element.Value;
} }
List<string> keys = new List<string>(extension.hybridInfo.Keys); List<string> keys = new List<string>(extension.hybridInfo.Keys);
foreach (string key in keys) foreach (string key in keys)
{ {
DoSubRow(sublist.GetRect(rowH), key, extension, removeelements); 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); 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; bool isPawnKind = false;
int value = (int)extension.hybridInfo.TryGetValue(key); int value = (int)extension.hybridInfo.TryGetValue(key);
@ -471,15 +461,15 @@ namespace RJW_Menstruation
} }
label += ": " + key; label += ": " + key;
Widgets.Label(rect, " - " + label); 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); extension.hybridInfo.SetOrAdd(key, value);
buttonRect.x -= 80f; buttonRect.x -= 80f;
Widgets.Label(buttonRect, String.Format("{0,0:P2}", value / totalWeight)); Widgets.Label(buttonRect, String.Format("{0,0:P2}", value / totalWeight));
Widgets.DrawHighlightIfMouseover(rect); 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 RimWorld;
using System.Collections.Generic;
using RimWorld;
using rjw; using rjw;
using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
using Verse; using Verse;
@ -92,7 +92,7 @@ namespace RJW_Menstruation
int index = pawns.IndexOf(window.pawn); int index = pawns.IndexOf(window.pawn);
SoundDefOf.TabOpen.PlayOneShotOnCamera(); SoundDefOf.TabOpen.PlayOneShotOnCamera();
Pawn newpawn = pawns[(index + 1) % pawns.Count]; Pawn newpawn = pawns[(index + 1) % pawns.Count];
window.ChangePawn(newpawn, newpawn.GetMenstruationComp()); window.ChangePawn(newpawn, newpawn.GetFirstMenstruationComp());
} }
else if (window.pawn != pawn) else if (window.pawn != pawn)
{ {
@ -151,16 +151,15 @@ namespace RJW_Menstruation
fontstyleleft.normal.textColor = Color.white; fontstyleleft.normal.textColor = Color.white;
float preginfoheight = 0f; float preginfoheight = 0f;
bool pregnant = pawn.IsPregnant(); Hediff_BasePregnancy hediff = comp.Pregnancy;
Hediff hediff = PregnancyHelper.GetPregnancy(pawn); if (hediff != null && Utility.ShowFetusImage(hediff))
if (pregnant && Utility.ShowFetusImage((Hediff_BasePregnancy)hediff))
{ {
womb = comp.GetPregnancyIcon(hediff); womb = comp.GetPregnancyIcon(hediff);
if (hediff is Hediff_MultiplePregnancy m) if (hediff is Hediff_MultiplePregnancy m)
{ {
if (m.GestationProgress < 0.2f) cum = comp.GetCumIcon(); if (m.GestationProgress < 0.2f) cum = comp.GetCumIcon();
else cum = ContentFinder<Texture2D>.Get(("Womb/Empty"), true); else cum = ContentFinder<Texture2D>.Get(("Womb/Empty"), true);
Pawn fetus = pawn.GetFetus(); Pawn fetus = comp.GetFetus();
if (fetus != null && Utility.ShowFetusInfo()) if (fetus != null && Utility.ShowFetusInfo())
{ {
string feinfo = m.GetBabyInfo(); string feinfo = m.GetBabyInfo();
@ -188,7 +187,7 @@ namespace RJW_Menstruation
{ {
if (b.GestationProgress < 0.2f) cum = comp.GetCumIcon(); if (b.GestationProgress < 0.2f) cum = comp.GetCumIcon();
else cum = ContentFinder<Texture2D>.Get(("Womb/Empty"), true); else cum = ContentFinder<Texture2D>.Get(("Womb/Empty"), true);
Pawn fetus = pawn.GetFetus(); Pawn fetus = comp.GetFetus();
if (fetus != null && Utility.ShowFetusInfo()) if (fetus != null && Utility.ShowFetusInfo())
{ {
preginfoheight = fontheight; preginfoheight = fontheight;
@ -230,7 +229,7 @@ namespace RJW_Menstruation
if (pawn.story != null) GUI.Label(pawnLabel2Rect, pawn.ageTracker.AgeBiologicalYears + ", " + pawn.story.Title, fontstylecenter); if (pawn.story != null) GUI.Label(pawnLabel2Rect, pawn.ageTracker.AgeBiologicalYears + ", " + pawn.story.Title, fontstylecenter);
GUI.color = Color.white; GUI.color = Color.white;
float wombrecth = 0; float wombrecth = 0;
if (Configurations.DrawWombStatus) if (Configurations.DrawWombStatus)
{ {
@ -249,7 +248,7 @@ namespace RJW_Menstruation
} }
Rect wombInfoRect = new Rect(0f, mainRect.yMax - wombrecth - fontheight - 2, wombRectWidth, fontheight - 4f); 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; buttonstyle.normal.textColor = Color.white;
//boxstyle.normal.background = Texture2D.whiteTexture; //boxstyle.normal.background = Texture2D.whiteTexture;
buttonstyle.alignment = TextAnchor.MiddleLeft; buttonstyle.alignment = TextAnchor.MiddleLeft;
@ -286,7 +285,7 @@ namespace RJW_Menstruation
cumlistRect = new Rect(pawnRectWidth, fontheight, 150f, mainRect.yMax - wombRectHeight - fontheight); cumlistRect = new Rect(pawnRectWidth, fontheight, 150f, mainRect.yMax - wombRectHeight - fontheight);
} }
Rect infoRect = new Rect(0, pawnRectHeight + 2*fontheight, pawnRectWidth, pawnRect.yMax + 2*fontheight - wombInfoRect.y); Rect infoRect = new Rect(0, pawnRectHeight + 2 * fontheight, pawnRectWidth, pawnRect.yMax + 2 * fontheight - wombInfoRect.y);
DrawInfos(infoRect); DrawInfos(infoRect);
@ -369,7 +368,7 @@ namespace RJW_Menstruation
GUI.color = new Color(1.00f, 0.47f, 0.47f, 1); GUI.color = new Color(1.00f, 0.47f, 0.47f, 1);
GUI.Box(rect, "", boxstyle); GUI.Box(rect, "", boxstyle);
pawn.DrawBreastIcon(BreastIconRect, Mouse.IsOver(BreastIconRect) && Input.GetMouseButton(0)); pawn.DrawBreastIcon(BreastIconRect, Mouse.IsOver(BreastIconRect) && Input.GetMouseButton(0));
@ -388,11 +387,11 @@ namespace RJW_Menstruation
float statvalue; float statvalue;
const float height = 24f; const float height = 24f;
statvalue = pawn.GetStatValue(xxx.sex_drive_stat); 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; lineRect.y += height;
statvalue = pawn.GetStatValue(xxx.vulnerability_stat); 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; lineRect.y += height;
statvalue = pawn.GetStatValue(xxx.sex_stat); statvalue = pawn.GetStatValue(xxx.sex_stat);
@ -409,27 +408,11 @@ namespace RJW_Menstruation
statvalue = pawn.records.GetValue(xxx.CountOfBirthEgg); statvalue = pawn.records.GetValue(xxx.CountOfBirthEgg);
FillableBarLabeled(lineRect, " " + xxx.CountOfBirthEgg.LabelCap.CapitalizeFirst() + " " + statvalue, statvalue / 100, TextureCache.NurgleTexture, Texture2D.blackTexture, xxx.CountOfBirthEgg.description); FillableBarLabeled(lineRect, " " + xxx.CountOfBirthEgg.LabelCap.CapitalizeFirst() + " " + statvalue, statvalue / 100, TextureCache.NurgleTexture, Texture2D.blackTexture, xxx.CountOfBirthEgg.description);
lineRect.y += height; lineRect.y += height * 3;
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;
}
statvalue = Configurations.ImplantationChance * comp.ImplantFactor; statvalue = Configurations.ImplantationChance * comp.ImplantFactor;
float fertchance = comp.GetFertilityChance(); 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); Rect overayRect = new Rect(lineRect.x, lineRect.y, lineRect.width * Math.Min(1.0f, fertchance), lineRect.height);
GUI.DrawTexture(overayRect, TextureCache.FertChanceTex); GUI.DrawTexture(overayRect, TextureCache.FertChanceTex);
lineRect.y += height; 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) 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); GUI.Label(rect, label, fontstyleleft);
Widgets.DrawHighlightIfMouseover(rect); Widgets.DrawHighlightIfMouseover(rect);
if (tooltip != null) TooltipHandler.TipRegion(rect, tooltip); if (tooltip != null) TooltipHandler.TipRegion(rect, tooltip);

View file

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

View file

@ -1,13 +1,11 @@
using RimWorld; using RimWorld;
using rjw; using rjw;
using System; using System;
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using UnityEngine; using UnityEngine;
using Verse; using Verse;
using Verse.Sound; using Verse.Sound;
using System.Threading;
using System.Threading.Tasks;
namespace RJW_Menstruation namespace RJW_Menstruation
@ -16,7 +14,7 @@ namespace RJW_Menstruation
{ {
public static Color blood = new Color(0.78f, 0, 0); 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 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 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) public static float GetCumVolume(this Pawn pawn)
{ {
@ -94,16 +97,13 @@ namespace RJW_Menstruation
public static HediffComp_Breast GetBreastComp(this Pawn pawn) 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; HediffComp_Breast result;
if (hedifflist.NullOrEmpty()) return null; 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; return null;
} }
@ -125,66 +125,43 @@ namespace RJW_Menstruation
public static bool HasMenstruationComp(this Pawn pawn) 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")); return pawn.GetMenstruationComps().Any();
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;
} }
public static bool HasMenstruationComp(this Hediff hediff) 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 void DrawBreastIcon(this Pawn pawn, Rect rect, bool drawOrigin = false)
public static float GetPregnancyProgress(this Pawn pawn)
{ {
Hediff hediff = PregnancyHelper.GetPregnancy(pawn); Hediff hediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_breastsBPR(pawn)).FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("breast"));
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"));
Texture2D breast, nipple, areola; Texture2D breast, nipple, areola;
if (hediff != null) if (hediff != null)
{ {
@ -227,7 +204,7 @@ namespace RJW_Menstruation
nippleicon = icon + "_Nipple0" + GetNippleIndex(nipplesize); nippleicon = icon + "_Nipple0" + GetNippleIndex(nipplesize);
areolaicon = icon + "_Areola0" + GetAreolaIndex(areolasize); areolaicon = icon + "_Areola0" + GetAreolaIndex(areolasize);
breast = ContentFinder<Texture2D>.Get(icon, false); breast = ContentFinder<Texture2D>.Get(icon, false);
areola = ContentFinder<Texture2D>.Get(areolaicon, false); areola = ContentFinder<Texture2D>.Get(areolaicon, false);
@ -299,78 +276,75 @@ namespace RJW_Menstruation
milkcomp = pawn.GetComp<CompMilkable>(); 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"); CompMilkable m = milkable;
if (active) res = Math.Max(m.Fullness, res);
{ Widgets.FillableBar(rect, Math.Min(res, 1.0f), TextureCache.MilkTexture, Texture2D.blackTexture, true);
CompMilkable m = milkable; DrawMilkBottle(rect, pawn, VariousDefOf.Job_LactateSelf, m.Fullness);
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"); float fullness = (float)milkcomp.GetMemberValue("fullness");
if (active) res = Math.Max(fullness, res);
{ Widgets.FillableBar(rect, Math.Min(res, 1.0f), TextureCache.MilkTexture, Texture2D.blackTexture, true);
float fullness = (float)milkcomp.GetMemberValue("fullness"); DrawMilkBottle(rect, pawn, VariousDefOf.Job_LactateSelf_MC, 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; Texture2D texture;
Rect buttonrect = new Rect(rect.x, rect.y, rect.height, rect.height); Rect buttonrect = new Rect(rect.x, rect.y, rect.height, rect.height);
if (fullness > 0.0f) if (fullness <= 0.0f) return;
{
if (fullness < 0.3f) texture = ContentFinder<Texture2D>.Get("Milk/Milkbottle_Small", false);
else if (fullness < 0.7f) texture = ContentFinder<Texture2D>.Get("Milk/Milkbottle_Medium", false);
else texture = ContentFinder<Texture2D>.Get("Milk/Milkbottle_Large", false);
GUIContent icon = new GUIContent(texture);
GUIStyle style = GUIStyle.none;
style.normal.background = texture;
string tooltip = Translations.Button_MilkTooltip;
TooltipHandler.TipRegion(buttonrect, tooltip); if (fullness < 0.3f) texture = ContentFinder<Texture2D>.Get("Milk/Milkbottle_Small", false);
if (GUI.Button(buttonrect, icon, style)) 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 SoundDefOf.Click.PlayOneShotOnCamera();
|| !pawn.IsColonistPlayerControlled pawn.jobs.TryTakeOrderedJob(new Verse.AI.Job(milkjob, pawn));
|| pawn.Downed) SoundDefOf.ClickReject.PlayOneShotOnCamera();
else
{
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) 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); return hediff.LabelBase.CapitalizeFirst() + "\n(" + hediff.LabelInBrackets + ")" + "\n" + xxx.CountOfSex.LabelCap.CapitalizeFirst() + ": " + pawn.records.GetAsInt(xxx.CountOfSex);
} }
public static string GetAnusLabel(this Pawn pawn) 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 + ")"; if (hediff != null) return hediff.LabelBase.CapitalizeFirst() + "\n(" + hediff.LabelInBrackets + ")";
else return ""; else return "";
} }
public static string GetBreastLabel(this Pawn pawn) 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 + ")"; if (hediff != null) return hediff.LabelBase.CapitalizeFirst() + "\n(" + hediff.LabelInBrackets + ")";
else return ""; else return "";
} }
@ -422,25 +396,20 @@ namespace RJW_Menstruation
{ {
Pawn res = pawn.GetFather(); Pawn res = pawn.GetFather();
if (res != null) return res; if (res != null) return res;
else else res = pawn.relations?.GetFirstDirectRelationPawn(PawnRelationDefOf.Parent, x => x != mother) ?? null;
{ return res;
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;
}
} }
public static float RandGaussianLike(float min, float max, int iterations = 3) public static float RandGaussianLike(float min, float max, int iterations = 3)
{ {
double res = 0; float res = 0;
for (int i = 0; i < iterations; i++) for (int i = 0; i < iterations; i++)
{ {
res += random.NextDouble(); res += Rand.Value;
} }
res /= iterations; 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); float tmult = Mathf.Pow(1 - t, num);
return tmult * a + (1 - tmult) * b; return tmult * a + (1 - tmult) * b;
} }
public static float VariationRange(this float num, float variant) public static float VariationRange(this float num, float variant)
{ {
return num * Rand.Range(1.0f - variant, 1.0f + 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) public static bool ShouldShowWombGizmo(this Pawn pawn)
{ {
return Configurations.EnableWombIcon && (!pawn.IsAnimal() || Configurations.EnableAnimalCycle);
if (Configurations.EnableWombIcon)
{
if (!pawn.IsAnimal())
{
return true;
}
else if (Configurations.EnableAnimalCycle)
{
return true;
}
}
return false;
} }
} }
} }

View file

@ -1,8 +1,8 @@
using RimWorld; using RimWorld;
using rjw; using rjw;
using System.Linq;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Verse; using Verse;
namespace RJW_Menstruation namespace RJW_Menstruation
@ -11,6 +11,7 @@ namespace RJW_Menstruation
{ {
public static readonly ThingDef CumFilth = DefDatabase<ThingDef>.GetNamed("FilthCum"); 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 = DefDatabase<ThingDef>.GetNamed("Absorber_Tampon");
public static readonly ThingDef Tampon_Dirty = DefDatabase<ThingDef>.GetNamed("Absorber_Tampon_Dirty"); public static readonly ThingDef Tampon_Dirty = DefDatabase<ThingDef>.GetNamed("Absorber_Tampon_Dirty");
public static readonly ThingDef FilthMixture = DefDatabase<ThingDef>.GetNamed("FilthMixture"); public static readonly ThingDef 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_Estrus_Concealed = DefDatabase<HediffDef>.GetNamed("Hediff_Estrus_Concealed");
public static readonly HediffDef Hediff_ASA = DefDatabase<HediffDef>.GetNamed("Hediff_ASA"); public static readonly HediffDef Hediff_ASA = DefDatabase<HediffDef>.GetNamed("Hediff_ASA");
public static readonly StatDef MaxAbsorbable = DefDatabase<StatDef>.GetNamed("MaxAbsorbable"); 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 NeedDef SexNeed = DefDatabase<NeedDef>.GetNamed("Sex");
public static readonly JobDef VaginaWashing = DefDatabase<JobDef>.GetNamed("VaginaWashing"); public static readonly JobDef VaginaWashing = DefDatabase<JobDef>.GetNamed("VaginaWashing");
public static readonly JobDef Job_LactateSelf = DefDatabase<JobDef>.GetNamed("LactateSelf"); 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 UnwantedPregnancyMild = DefDatabase<ThoughtDef>.GetNamed("UnwantedPregnancyMild");
public static readonly ThoughtDef TookContraceptivePill = DefDatabase<ThoughtDef>.GetNamed("TookContraceptivePill"); public static readonly ThoughtDef TookContraceptivePill = DefDatabase<ThoughtDef>.GetNamed("TookContraceptivePill");
public static readonly ThoughtDef HateTookContraceptivePill = DefDatabase<ThoughtDef>.GetNamed("HateTookContraceptivePill"); 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 HumanVaginaCompProperties = (CompProperties_Menstruation)Genital_Helper.average_vagina.comps.FirstOrDefault(x => x is CompProperties_Menstruation);
public static readonly CompProperties_Menstruation VaginaCompProperties = (CompProperties_Menstruation)Vagina.comps.FirstOrDefault(x => x is CompProperties_Menstruation);
public static readonly KeyBindingDef OpenStatusWindowKey = DefDatabase<KeyBindingDef>.GetNamed("OpenStatusWindow"); 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 AmountofCreampied = DefDatabase<RecordDef>.GetNamed("AmountofCreampied");
public static readonly RecordDef AmountofFertilizedEggs = DefDatabase<RecordDef>.GetNamed("AmountofFertilizedEggs"); 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<ThingDef> allraces = null;
private static List<PawnKindDef> allkinds = null; private static List<PawnKindDef> allkinds = null;
private static HashSet<HediffDef> allvaginas = null;
public static List<ThingDef> AllRaces public static List<ThingDef> AllRaces
{ {
get get
{ {
if (allraces == null) if (allraces != null) return allraces;
{
List<ThingDef> allThings = DefDatabase<ThingDef>.AllDefsListForReading;
List<ThingDef> allThings = DefDatabase<ThingDef>.AllDefsListForReading; allraces = allThings.FindAll(x => x.race != null && x.race.IsFlesh);
allraces = allThings.FindAll(x => x.race != null && x.race.IsFlesh);
}
return allraces; return allraces;
} }
} }
@ -71,16 +67,37 @@ namespace RJW_Menstruation
{ {
get get
{ {
if (allkinds == null) if (allkinds != null) return allkinds;
{
List<PawnKindDef> allKinds = DefDatabase<PawnKindDef>.AllDefsListForReading; List<PawnKindDef> allKinds = DefDatabase<PawnKindDef>.AllDefsListForReading;
allkinds = allKinds.FindAll(x => x.race != null); allkinds = allKinds.FindAll(x => x.race != null);
}
return allkinds; 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 // Defs from Milkable Colonists
public static readonly HediffDef Hediff_Lactating_Drug = DefDatabase<HediffDef>.GetNamedSilentFail("Lactating_Drug"); 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_Lactating_Permanent = DefDatabase<HediffDef>.GetNamedSilentFail("Lactating_Permanent");
public static readonly HediffDef Hediff_Heavy_Lactating_Permanent = DefDatabase<HediffDef>.GetNamedSilentFail("Heavy_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"); 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.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using RimWorld;
using RJWSexperience;
using RJW_Menstruation;
using UnityEngine; using UnityEngine;
using Verse;
namespace RJW_Menstruation.Sexperience namespace RJW_Menstruation.Sexperience
{ {
@ -34,8 +27,8 @@ namespace RJW_Menstruation.Sexperience
if (res && other is GatheredCumMixture mixture) if (res && other is GatheredCumMixture mixture)
{ {
GatheredCumMixture othercum = mixture; GatheredCumMixture othercum = mixture;
cumColor = Colors.CMYKLerp(cumColor,othercum.cumColor,count/(amount+count)); cumColor = Colors.CMYKLerp(cumColor, othercum.cumColor, count / (amount + count));
if (!othercum.ingredients.NullOrEmpty()) for (int i=0; i<othercum.ingredients.Count; i++) if (!othercum.ingredients.NullOrEmpty()) for (int i = 0; i < othercum.ingredients.Count; i++)
{ {
if (!ingredients.Contains(othercum.ingredients[i])) ingredients.Add(othercum.ingredients[i]); if (!ingredients.Contains(othercum.ingredients[i])) ingredients.Add(othercum.ingredients[i]);
} }
@ -46,7 +39,7 @@ namespace RJW_Menstruation.Sexperience
public override string GetInspectString() public override string GetInspectString()
{ {
string res = ""; 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]; res += ingredients[i];
if (i != ingredients.Count - 1) res += ", "; if (i != ingredients.Count - 1) res += ", ";

View file

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

View file

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

View file

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

View file

@ -1,16 +1,8 @@
using System; using HarmonyLib;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RJW_Menstruation;
using HarmonyLib;
using rjw;
using RimWorld; using RimWorld;
using UnityEngine;
using Verse; using Verse;
using Verse.Sound; using Verse.Sound;
using UnityEngine;
using RJWSexperience;
namespace RJW_Menstruation.Sexperience 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); Rect buttonRect = new Rect(rect.x, rect.yMax - ICONSIZE, ICONSIZE, ICONSIZE).ContractedBy(2f);
if (__instance.Comp.DoCleanWomb) 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); TooltipHandler.TipRegion(buttonRect, Translations.Dialog_DoCleanWomb_Tooltip);
} }
else else

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Manifest> <Manifest>
<identifier>RJW Menstruation</identifier> <identifier>RJW Menstruation</identifier>
<version>1.0.6.6</version> <version>1.0.7.0</version>
<dependencies> <dependencies>
</dependencies> </dependencies>
<incompatibleWith /> <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 Version 1.0.6.6
- Ovipostors add on average 1.5x as much cum to a womb than before. - 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. - The womb tick timing is now more consistent across a save and load, and also spread out across pawns.