Compare commits

...

19 commits

Author SHA1 Message Date
amevarashi
a722673244 1.0.2.1 2023-06-28 20:04:08 +05:00
amevarashi
83ffa00fb6 Fixed SecondaryRomanceChanceFactor transpiler 2023-06-28 20:02:42 +05:00
amevarashi
a19953c688 1.0.2.0 2023-06-25 19:12:12 +05:00
amevarashi
e622b7a391 Added settings for romance patches
Added in-game explanation for DefExtension_ModifyMtb effect
2023-06-25 18:54:32 +05:00
amevarashi
77dd1a23d6 Swapped baseMoodEffect of holy and elevated pregnancy precepts 2023-04-24 10:59:04 +05:00
amevarashi
670584500b Fix IDE messages 2023-04-23 17:15:07 +05:00
amevarashi
032b031123 Change VariousDefOf to RsiDefOf 2023-04-23 16:41:27 +05:00
amevarashi
f7206347da Moved precepts romanceChanceFactor to DefExtention 2023-04-23 16:16:28 +05:00
amevarashi
be1e5c5d5d Replaced manual sexperience patch with the Prepare method 2023-04-23 15:38:38 +05:00
amevarashi
7e30ebe68e Optimized incest checks 2023-04-22 15:08:57 +05:00
amevarashi
7107947cac Bestiality_Acceptable nullifies RJW bestiality thoughts 2023-02-19 16:09:10 +05:00
amevarashi
785eac31de Patched SecondaryRomanceChanceFactor for incest precept 2022-11-24 23:10:03 +05:00
amevarashi
355d409eb6 Removed "not obedient" social thought for raping a slave 2022-11-23 20:12:13 +05:00
amevarashi
d33fa5e3ea Moved manual romance rules into XML 2022-11-23 19:42:47 +05:00
amevarashi
bcc9feb61a Changed Incestuos_IncestOnly would_fuck multiplier for blood related pawns: 2.0 -> 1.0
Changed Incestuos_IncestOnly would_fuck multiplier for non-blood related pawns: 1.0 -> 0.1
2022-11-21 22:47:52 +05:00
amevarashi
7d6f0d043c Added isBloodRelated filter attribute 2022-11-21 22:40:44 +05:00
amevarashi
765e6c0778 Moved PreceptDefs into a separate class 2022-11-20 18:55:13 +05:00
amevarashi
3bedfec30e Patched manual romance to respect incestuous precepts 2022-11-20 18:47:55 +05:00
amevarashi
180404cee1 Removed Incestuos_IncestOnly conflict with Zoophile 2022-11-20 17:56:21 +05:00
43 changed files with 1116 additions and 572 deletions

View file

@ -27,16 +27,9 @@
<li> <li>
<filter> <filter>
<relations> <relations>
<hasOneOfRelations> <hasOneOfRelationDegrees>
<li>Parent</li> <li>CloseRelative</li>
<li>Child</li> </hasOneOfRelationDegrees>
<li>Sibling</li>
<li>HalfSibling</li>
<li>Grandparent</li>
<li>Grandchild</li>
<li>NephewOrNiece</li>
<li>UncleOrAunt</li>
</hasOneOfRelations>
</relations> </relations>
</filter> </filter>
<historyEventDef>RSI_CloseRelativeMarriage</historyEventDef> <historyEventDef>RSI_CloseRelativeMarriage</historyEventDef>
@ -44,24 +37,9 @@
<li> <li>
<filter> <filter>
<relations> <relations>
<hasOneOfRelations> <hasOneOfRelationDegrees>
<li>Parent</li> <li>FarRelative</li>
<li>Child</li> </hasOneOfRelationDegrees>
<li>Sibling</li>
<li>HalfSibling</li>
<li>Grandparent</li>
<li>Grandchild</li>
<li>NephewOrNiece</li>
<li>UncleOrAunt</li>
<li>GreatGrandparent</li>
<li>GreatGrandchild</li>
<li>GranduncleOrGrandaunt</li>
<li>GrandnephewOrGrandniece</li>
<li>CousinOnceRemoved</li>
<li>SecondCousin</li>
<li>Cousin</li>
<li>Kin</li>
</hasOneOfRelations>
</relations> </relations>
</filter> </filter>
<historyEventDef>RSI_IncestuosMarriage</historyEventDef> <historyEventDef>RSI_IncestuosMarriage</historyEventDef>
@ -90,16 +68,9 @@
<li> <li>
<filter> <filter>
<relations> <relations>
<hasOneOfRelations> <hasOneOfRelationDegrees>
<li>Parent</li> <li>CloseRelative</li>
<li>Child</li> </hasOneOfRelationDegrees>
<li>Sibling</li>
<li>HalfSibling</li>
<li>Grandparent</li>
<li>Grandchild</li>
<li>NephewOrNiece</li>
<li>UncleOrAunt</li>
</hasOneOfRelations>
</relations> </relations>
</filter> </filter>
<historyEventDef>RSI_CloseRelativeSex</historyEventDef> <historyEventDef>RSI_CloseRelativeSex</historyEventDef>
@ -107,24 +78,9 @@
<li> <li>
<filter> <filter>
<relations> <relations>
<hasOneOfRelations> <hasOneOfRelationDegrees>
<li>Parent</li> <li>FarRelative</li>
<li>Child</li> </hasOneOfRelationDegrees>
<li>Sibling</li>
<li>HalfSibling</li>
<li>Grandparent</li>
<li>Grandchild</li>
<li>NephewOrNiece</li>
<li>UncleOrAunt</li>
<li>GreatGrandparent</li>
<li>GreatGrandchild</li>
<li>GranduncleOrGrandaunt</li>
<li>GrandnephewOrGrandniece</li>
<li>CousinOnceRemoved</li>
<li>SecondCousin</li>
<li>Cousin</li>
<li>Kin</li>
</hasOneOfRelations>
</relations> </relations>
</filter> </filter>
<historyEventDef>RSI_IncestuosSex</historyEventDef> <historyEventDef>RSI_IncestuosSex</historyEventDef>
@ -145,6 +101,29 @@
<displayOrderInIssue>60</displayOrderInIssue> <displayOrderInIssue>60</displayOrderInIssue>
<displayOrderInImpact>1000</displayOrderInImpact> <displayOrderInImpact>1000</displayOrderInImpact>
<defaultSelectionWeight>100</defaultSelectionWeight> <defaultSelectionWeight>100</defaultSelectionWeight>
<modExtensions>
<li Class="RJWSexperience.Ideology.Precepts.DefExtension_Incest">
<allowManualRomanceOnlyFor>
<li>CloseRelative</li>
<li>FarRelative</li>
<li>NotRelated</li>
</allowManualRomanceOnlyFor>
<bloodRelationDegreeRomanceFactors>
<li>
<bloodRelationDegree>CloseRelative</bloodRelationDegree>
<romanceChanceFactor>1</romanceChanceFactor>
</li>
<li>
<bloodRelationDegree>FarRelative</bloodRelationDegree>
<romanceChanceFactor>1</romanceChanceFactor>
</li>
<li>
<bloodRelationDegree>NotRelated</bloodRelationDegree>
<romanceChanceFactor>1</romanceChanceFactor>
</li>
</bloodRelationDegreeRomanceFactors>
</li>
</modExtensions>
</PreceptDef> </PreceptDef>
<PreceptDef> <PreceptDef>
@ -172,16 +151,9 @@
<li> <li>
<filter> <filter>
<relations> <relations>
<hasOneOfRelations> <hasOneOfRelationDegrees>
<li>Parent</li> <li>CloseRelative</li>
<li>Child</li> </hasOneOfRelationDegrees>
<li>Sibling</li>
<li>HalfSibling</li>
<li>Grandparent</li>
<li>Grandchild</li>
<li>NephewOrNiece</li>
<li>UncleOrAunt</li>
</hasOneOfRelations>
<hasNoneOfRelations> <hasNoneOfRelations>
<li>Spouse</li> <li>Spouse</li>
</hasNoneOfRelations> </hasNoneOfRelations>
@ -191,6 +163,22 @@
</li> </li>
</rules> </rules>
</li> </li>
<li Class="RJWSexperience.Ideology.Precepts.DefExtension_Incest">
<allowManualRomanceOnlyFor>
<li>FarRelative</li>
<li>NotRelated</li>
</allowManualRomanceOnlyFor>
<bloodRelationDegreeRomanceFactors>
<li>
<bloodRelationDegree>FarRelative</bloodRelationDegree>
<romanceChanceFactor>1</romanceChanceFactor>
</li>
<li>
<bloodRelationDegree>NotRelated</bloodRelationDegree>
<romanceChanceFactor>1</romanceChanceFactor>
</li>
</bloodRelationDegreeRomanceFactors>
</li>
</modExtensions> </modExtensions>
</PreceptDef> </PreceptDef>
@ -223,24 +211,10 @@
<li> <li>
<filter> <filter>
<relations> <relations>
<hasOneOfRelations> <hasOneOfRelationDegrees>
<li>Parent</li> <li>CloseRelative</li>
<li>Child</li> <li>FarRelative</li>
<li>Sibling</li> </hasOneOfRelationDegrees>
<li>HalfSibling</li>
<li>Grandparent</li>
<li>Grandchild</li>
<li>NephewOrNiece</li>
<li>UncleOrAunt</li>
<li>GreatGrandparent</li>
<li>GreatGrandchild</li>
<li>GranduncleOrGrandaunt</li>
<li>GrandnephewOrGrandniece</li>
<li>CousinOnceRemoved</li>
<li>SecondCousin</li>
<li>Cousin</li>
<li>Kin</li>
</hasOneOfRelations>
<hasNoneOfRelations> <hasNoneOfRelations>
<li>Spouse</li> <li>Spouse</li>
</hasNoneOfRelations> </hasNoneOfRelations>
@ -282,24 +256,10 @@
<li> <li>
<filter> <filter>
<relations> <relations>
<hasOneOfRelations> <hasOneOfRelationDegrees>
<li>Parent</li> <li>CloseRelative</li>
<li>Child</li> <li>FarRelative</li>
<li>Sibling</li> </hasOneOfRelationDegrees>
<li>HalfSibling</li>
<li>Grandparent</li>
<li>Grandchild</li>
<li>NephewOrNiece</li>
<li>UncleOrAunt</li>
<li>GreatGrandparent</li>
<li>GreatGrandchild</li>
<li>GranduncleOrGrandaunt</li>
<li>GrandnephewOrGrandniece</li>
<li>CousinOnceRemoved</li>
<li>SecondCousin</li>
<li>Cousin</li>
<li>Kin</li>
</hasOneOfRelations>
<hasNoneOfRelations> <hasNoneOfRelations>
<li>Spouse</li> <li>Spouse</li>
</hasNoneOfRelations> </hasNoneOfRelations>
@ -309,6 +269,18 @@
</li> </li>
</rules> </rules>
</li> </li>
<li Class="RJWSexperience.Ideology.Precepts.DefExtension_Incest">
<bloodRelationDegreeRomanceFactors>
<li>
<bloodRelationDegree>CloseRelative</bloodRelationDegree>
<romanceChanceFactor>0.03</romanceChanceFactor> <!-- same as vanilla "parent" -->
</li>
<li>
<bloodRelationDegree>FarRelative</bloodRelationDegree>
<romanceChanceFactor>0.03</romanceChanceFactor>
</li>
</bloodRelationDegreeRomanceFactors>
</li>
</modExtensions> </modExtensions>
</PreceptDef> </PreceptDef>
@ -320,9 +292,6 @@
<impact>High</impact> <impact>High</impact>
<displayOrderInIssue>0</displayOrderInIssue> <displayOrderInIssue>0</displayOrderInIssue>
<displayOrderInImpact>1000</displayOrderInImpact> <displayOrderInImpact>1000</displayOrderInImpact>
<conflictingMemes>
<li>Zoophile</li>
</conflictingMemes>
<comps> <comps>
<li Class="PreceptComp_KnowsMemoryThought"> <li Class="PreceptComp_KnowsMemoryThought">
<eventDef>RSI_NonIncestuosMarriage</eventDef> <eventDef>RSI_NonIncestuosMarriage</eventDef>
@ -339,30 +308,35 @@
<li> <li>
<filter> <filter>
<relations> <relations>
<hasOneOfRelations> <hasOneOfRelationDegrees>
<li>Parent</li> <li>NotRelated</li>
<li>Child</li> </hasOneOfRelationDegrees>
<li>Sibling</li>
<li>HalfSibling</li>
<li>Grandparent</li>
<li>Grandchild</li>
<li>NephewOrNiece</li>
<li>UncleOrAunt</li>
<li>GreatGrandparent</li>
<li>GreatGrandchild</li>
<li>GranduncleOrGrandaunt</li>
<li>GrandnephewOrGrandniece</li>
<li>CousinOnceRemoved</li>
<li>SecondCousin</li>
<li>Cousin</li>
<li>Kin</li>
</hasOneOfRelations>
</relations> </relations>
</filter> </filter>
<multiplier>2.0</multiplier> <multiplier>0.1</multiplier>
</li> </li>
</rules> </rules>
</li> </li>
<li Class="RJWSexperience.Ideology.Precepts.DefExtension_Incest">
<allowManualRomanceOnlyFor>
<li>CloseRelative</li>
<li>FarRelative</li>
</allowManualRomanceOnlyFor>
<bloodRelationDegreeRomanceFactors>
<li>
<bloodRelationDegree>CloseRelative</bloodRelationDegree>
<romanceChanceFactor>1</romanceChanceFactor>
</li>
<li>
<bloodRelationDegree>FarRelative</bloodRelationDegree>
<romanceChanceFactor>1</romanceChanceFactor>
</li>
<li>
<bloodRelationDegree>NotRelated</bloodRelationDegree>
<romanceChanceFactor>0.03</romanceChanceFactor>
</li>
</bloodRelationDegreeRomanceFactors>
</li>
</modExtensions> </modExtensions>
</PreceptDef> </PreceptDef>

View file

@ -100,14 +100,14 @@
<!-- Thoughts : Pregnant --> <!-- Thoughts : Pregnant -->
<ThoughtDef> <ThoughtDef>
<defName>Pregnancy_Respected_Pregnant</defName> <defName>Pregnancy_Respected_Pregnant</defName> <!-- should probably be Pregnancy_Holy_Pregnant -->
<workerClass>RJWSexperience.Ideology.PreceptWorkers.ThoughtWorker_Precept_Pregnant</workerClass> <workerClass>RJWSexperience.Ideology.PreceptWorkers.ThoughtWorker_Precept_Pregnant</workerClass>
<thoughtClass>Thought_Situational</thoughtClass> <thoughtClass>Thought_Situational</thoughtClass>
<stages> <stages>
<li> <li>
<label>pregnant</label> <label>pregnant</label>
<description>I am pregnant. This makes me a pillar of society.</description> <description>I am pregnant. This makes me a pillar of society.</description>
<baseMoodEffect>5</baseMoodEffect> <baseMoodEffect>10</baseMoodEffect>
</li> </li>
</stages> </stages>
</ThoughtDef> </ThoughtDef>
@ -120,19 +120,19 @@
<li> <li>
<label>pregnant</label> <label>pregnant</label>
<description>I am soon making our colony stronger.</description> <description>I am soon making our colony stronger.</description>
<baseMoodEffect>10</baseMoodEffect> <baseMoodEffect>5</baseMoodEffect>
</li> </li>
</stages> </stages>
</ThoughtDef> </ThoughtDef>
<ThoughtDef> <ThoughtDef>
<defName>Pregnancy_Respected_Pregnant_Social</defName> <defName>Pregnancy_Respected_Pregnant_Social</defName> <!-- should probably be Pregnancy_Holy_Pregnant_Social -->
<workerClass>RJWSexperience.Ideology.PreceptWorkers.ThoughtWorker_Precept_Pregnant_Social</workerClass> <workerClass>RJWSexperience.Ideology.PreceptWorkers.ThoughtWorker_Precept_Pregnant_Social</workerClass>
<thoughtClass>Thought_SituationalSocial</thoughtClass> <thoughtClass>Thought_SituationalSocial</thoughtClass>
<stages> <stages>
<li> <li>
<label>pregnant</label> <label>pregnant</label>
<baseOpinionOffset>10</baseOpinionOffset> <baseOpinionOffset>20</baseOpinionOffset>
</li> </li>
</stages> </stages>
</ThoughtDef> </ThoughtDef>
@ -144,7 +144,7 @@
<stages> <stages>
<li> <li>
<label>pregnant</label> <label>pregnant</label>
<baseOpinionOffset>20</baseOpinionOffset> <baseOpinionOffset>10</baseOpinionOffset>
</li> </li>
</stages> </stages>
</ThoughtDef> </ThoughtDef>

View file

@ -76,11 +76,11 @@
<thought>BeenRaped_NotSubmissive</thought> <thought>BeenRaped_NotSubmissive</thought>
<gender>Female</gender> <gender>Female</gender>
</li> </li>
<li Class="RJWSexperience.Ideology.Precepts.Comp_KnowsMemoryThought_Gendered"> <!--<li Class="RJWSexperience.Ideology.Precepts.Comp_KnowsMemoryThought_Gendered">
<eventDef>RSI_RapedSlave</eventDef> <eventDef>RSI_RapedSlave</eventDef>
<thought>Raped_Know_NotBeingSubmissive</thought> <thought>Raped_Know_NotBeingSubmissive</thought>
<doersGender>Male</doersGender> <doersGender>Male</doersGender>
</li> </li>-->
</comps> </comps>
</PreceptDef> </PreceptDef>
@ -140,11 +140,11 @@
<thought>BeenRaped_NotSubmissive</thought> <thought>BeenRaped_NotSubmissive</thought>
<gender>Male</gender> <gender>Male</gender>
</li> </li>
<li Class="RJWSexperience.Ideology.Precepts.Comp_KnowsMemoryThought_Gendered"> <!--<li Class="RJWSexperience.Ideology.Precepts.Comp_KnowsMemoryThought_Gendered">
<eventDef>RSI_RapedSlave</eventDef> <eventDef>RSI_RapedSlave</eventDef>
<thought>Raped_Know_NotBeingSubmissive</thought> <thought>Raped_Know_NotBeingSubmissive</thought>
<doersGender>Female</doersGender> <doersGender>Female</doersGender>
</li> </li>-->
</comps> </comps>
</PreceptDef> </PreceptDef>

View file

@ -8,6 +8,7 @@
<li>Bestiality_OnlyVenerated</li> <li>Bestiality_OnlyVenerated</li>
<li>Bestiality_BondOnly</li> <li>Bestiality_BondOnly</li>
<li>Bestiality_Honorable</li> <li>Bestiality_Honorable</li>
<li>Bestiality_Acceptable</li>
</nullifyingPrecepts> </nullifyingPrecepts>
</value> </value>
</Operation> </Operation>
@ -19,6 +20,7 @@
<li>Bestiality_OnlyVenerated</li> <li>Bestiality_OnlyVenerated</li>
<li>Bestiality_BondOnly</li> <li>Bestiality_BondOnly</li>
<li>Bestiality_Honorable</li> <li>Bestiality_Honorable</li>
<li>Bestiality_Acceptable</li>
</nullifyingPrecepts> </nullifyingPrecepts>
</value> </value>
</Operation> </Operation>
@ -30,6 +32,7 @@
<li>Bestiality_OnlyVenerated</li> <li>Bestiality_OnlyVenerated</li>
<li>Bestiality_BondOnly</li> <li>Bestiality_BondOnly</li>
<li>Bestiality_Honorable</li> <li>Bestiality_Honorable</li>
<li>Bestiality_Acceptable</li>
</nullifyingPrecepts> </nullifyingPrecepts>
</value> </value>
</Operation> </Operation>
@ -41,6 +44,7 @@
<li>Bestiality_OnlyVenerated</li> <li>Bestiality_OnlyVenerated</li>
<li>Bestiality_BondOnly</li> <li>Bestiality_BondOnly</li>
<li>Bestiality_Honorable</li> <li>Bestiality_Honorable</li>
<li>Bestiality_Acceptable</li>
</nullifyingPrecepts> </nullifyingPrecepts>
</value> </value>
</Operation> </Operation>
@ -52,6 +56,7 @@
<li>Bestiality_OnlyVenerated</li> <li>Bestiality_OnlyVenerated</li>
<li>Bestiality_BondOnly</li> <li>Bestiality_BondOnly</li>
<li>Bestiality_Honorable</li> <li>Bestiality_Honorable</li>
<li>Bestiality_Acceptable</li>
</nullifyingPrecepts> </nullifyingPrecepts>
</value> </value>
</Operation> </Operation>
@ -63,6 +68,7 @@
<li>Bestiality_OnlyVenerated</li> <li>Bestiality_OnlyVenerated</li>
<li>Bestiality_BondOnly</li> <li>Bestiality_BondOnly</li>
<li>Bestiality_Honorable</li> <li>Bestiality_Honorable</li>
<li>Bestiality_Acceptable</li>
</nullifyingPrecepts> </nullifyingPrecepts>
</value> </value>
</Operation> </Operation>

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>RJWSexperienceIdeology</identifier> <identifier>RJWSexperienceIdeology</identifier>
<version>1.0.1.2</version> <version>1.0.2.1</version>
<dependencies> <dependencies>
<li>RimJobWorld >= 5.3.0</li> <li>RimJobWorld >= 5.3.0</li>
</dependencies> </dependencies>

View file

@ -1,3 +1,15 @@
## Version 1.0.2.1
* Fixed SecondaryRomanceChanceFactor patch
## Version 1.0.2.0
* Removed Incestuos_IncestOnly conflict with Zoophile
* Patched manual romance to respect incestuous precepts
* Patched SecondaryRomanceChanceFactor for incest precept
* Added settings to disable ether of patches if needed
* Changed Incestuos_IncestOnly would_fuck multiplier for blood related pawns: 2.0 -> 1.0
* Changed Incestuos_IncestOnly would_fuck multiplier for non-blood related pawns: 1.0 -> 0.1
* Removed "not obedient" social thought for raping a slave
* Bestiality_Acceptable now nullifies RJW bestiality thoughts
* Fixed swapped baseMoodEffect of holy and elevated pregnancy precepts
## Version 1.0.1.2 ## Version 1.0.1.2
* Removed 100% certainty spam for sex proselyzing * Removed 100% certainty spam for sex proselyzing
* Maybe removed sex proselyzing error with bestiality * Maybe removed sex proselyzing error with bestiality

View file

@ -9,4 +9,16 @@
<RSNotAnimal>not animal</RSNotAnimal> <RSNotAnimal>not animal</RSNotAnimal>
<RSShouldCanFuck>capable of sex is required</RSShouldCanFuck> <RSShouldCanFuck>capable of sex is required</RSShouldCanFuck>
<RSI_PatchRomanceChanceFactor>Enable romance patch for incest precepts*</RSI_PatchRomanceChanceFactor>
<RSI_PatchRomanceChanceFactorTip>Patch for incest precepts to affect RomanceChanceFactor. May conflict with romance mods./n/n* Requires a game restart to apply changes</RSI_PatchRomanceChanceFactorTip>
<RSI_PatchIncestuousManualRomance>Enable manual romance patch for incest precepts*</RSI_PatchIncestuousManualRomance>
<RSI_PatchIncestuousManualRomanceTip>Patch for incest precepts to affect manual romance options./n/n* Requires a game restart to apply changes</RSI_PatchIncestuousManualRomanceTip>
<RSI_PreceptTipModifyBestialityMtb>Time between bestiality attempts x{0}</RSI_PreceptTipModifyBestialityMtb>
<RSI_PreceptTipModifyFappinMtb>Time between masturbation attempts x{0}</RSI_PreceptTipModifyFappinMtb>
<RSI_PreceptTipModifyNecroMtb>Time between necrophilia attempts x{0}</RSI_PreceptTipModifyNecroMtb>
<RSI_PreceptTipModifyRapeCPMtb>Time between rape attempts x{0}</RSI_PreceptTipModifyRapeCPMtb>
<!-- Rewrite vanilla key -->
<!-- <CantRomanceTargetIncest>forbidden by ideology</CantRomanceTargetIncest> -->
</LanguageData> </LanguageData>

View file

@ -0,0 +1,9 @@
namespace RJWSexperience.Ideology
{
public enum BloodRelationDegree
{
CloseRelative,
FarRelative,
NotRelated
}
}

View file

@ -1,20 +1,37 @@
using rjw; using rjw;
using RJWSexperience.Ideology.HistoryEvents; using RJWSexperience.Ideology.HistoryEvents;
using RJWSexperience.Ideology.Patches;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using Verse; using Verse;
namespace RJWSexperience.Ideology namespace RJWSexperience.Ideology
{ {
internal class DebugAction internal static class DebugAction
{ {
[DebugAction("RJW Sexperience Ideology", "Test marriage event", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.PlayingOnMap)] [DebugAction("RJW Sexperience Ideology", "Test marriage event", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.PlayingOnMap)]
private static void GenerateMarriageEvent(Pawn p) public static void GenerateMarriageEvent(Pawn p)
{ {
Pawn hero = p.Map.PlayerPawnsForStoryteller.First(x => x.IsDesignatedHero()); Pawn hero = p.Map.PlayerPawnsForStoryteller.First(x => x.IsDesignatedHero());
if (hero == null) if (hero == null)
return; return;
RsiHistoryEventDefOf.RSI_NonIncestuosMarriage.RecordEventWithPartner(hero, p); RsiDefOf.HistoryEvent.RSI_NonIncestuosMarriage.RecordEventWithPartner(hero, p);
RsiHistoryEventDefOf.RSI_NonIncestuosMarriage.RecordEventWithPartner(p, hero); RsiDefOf.HistoryEvent.RSI_NonIncestuosMarriage.RecordEventWithPartner(p, hero);
}
[DebugAction("RJW Sexperience Ideology", "Manual romance check", false, true, actionType = DebugActionType.Action, allowedGameStates = AllowedGameStates.PlayingOnMap)]
public static void DisplayDebugTable()
{
IEnumerable<Pawn> pawns = Find.CurrentMap.mapPawns.AllPawnsSpawned.Where(pawn => pawn.IsColonist);
IEnumerable<TableDataGetter<Pawn>> columns = pawns
.Select(pawn => new TableDataGetter<Pawn>(pawn.Name.ToStringShort, (Pawn p) => Rimworld_Patch_IncestuousManualRomance.RsiIncestuous(p, pawn)));
var name = new TableDataGetter<Pawn>("Name", (Pawn pawn) => pawn.Name.ToStringShort);
TableDataGetter<Pawn>[] getters = (new List<TableDataGetter<Pawn>>() { name }).Concat(columns).ToArray();
DebugTables.MakeTablesDialog(pawns, getters);
} }
} }
} }

View file

@ -3,31 +3,33 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Verse; using Verse;
namespace RJWSexperience.Ideology namespace RJWSexperience.Ideology.Filters
{ {
/// <summary>
/// Filter to describe how one pawn sees another
/// </summary>
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Def loader")]
public class RelationFilter public class RelationFilter
{ {
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public bool? isVeneratedAnimal; public bool? isVeneratedAnimal;
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public bool? isAlien;
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public List<PawnRelationDef> hasOneOfRelations; public List<PawnRelationDef> hasOneOfRelations;
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public List<PawnRelationDef> hasNoneOfRelations; public List<PawnRelationDef> hasNoneOfRelations;
public List<BloodRelationDegree> hasOneOfRelationDegrees;
private bool initialized = false; private bool initialized = false;
private HashSet<PawnRelationDef> hasOneOfRelationsHashed; private HashSet<PawnRelationDef> hasOneOfRelationsHashed;
private HashSet<PawnRelationDef> hasNoneOfRelationsHashed; private HashSet<PawnRelationDef> hasNoneOfRelationsHashed;
private HashSet<BloodRelationDegree> hasOneOfRelationDegreesHashed;
/// <summary>
/// Check if the pair of pawns fits filter conditions
/// </summary>
public bool Applies(Pawn pawn, Pawn partner) public bool Applies(Pawn pawn, Pawn partner)
{ {
// Fail if any single condition fails
if (isVeneratedAnimal != null && isVeneratedAnimal != pawn.Ideo.IsVeneratedAnimal(partner)) if (isVeneratedAnimal != null && isVeneratedAnimal != pawn.Ideo.IsVeneratedAnimal(partner))
return false; return false;
//if (isAlien != null && isAlien != partner)
// return false;
if (!CheckRelations(pawn, partner)) if (!CheckRelations(pawn, partner))
return false; return false;
@ -39,9 +41,14 @@ namespace RJWSexperience.Ideology
if (!initialized) if (!initialized)
Initialize(); Initialize();
if (hasNoneOfRelationsHashed == null && hasOneOfRelationsHashed == null) if (hasNoneOfRelationsHashed == null && hasOneOfRelationsHashed == null && hasOneOfRelationDegreesHashed == null)
return true; return true;
if (hasOneOfRelationDegreesHashed != null && !hasOneOfRelationDegreesHashed.Contains(RelationHelpers.GetBloodRelationDegree(pawn, partner)))
{
return false;
}
IEnumerable<PawnRelationDef> relations = pawn.GetRelations(partner); IEnumerable<PawnRelationDef> relations = pawn.GetRelations(partner);
if (hasOneOfRelationsHashed != null) if (hasOneOfRelationsHashed != null)
@ -69,6 +76,9 @@ namespace RJWSexperience.Ideology
if (!hasOneOfRelations.NullOrEmpty()) if (!hasOneOfRelations.NullOrEmpty())
hasOneOfRelationsHashed = new HashSet<PawnRelationDef>(hasOneOfRelations); hasOneOfRelationsHashed = new HashSet<PawnRelationDef>(hasOneOfRelations);
if (!hasOneOfRelationDegrees.NullOrEmpty())
hasOneOfRelationDegreesHashed = new HashSet<BloodRelationDegree>(hasOneOfRelationDegrees);
initialized = true; initialized = true;
} }
} }

View file

@ -2,19 +2,24 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Verse; using Verse;
namespace RJWSexperience.Ideology namespace RJWSexperience.Ideology.Filters
{ {
/// <summary>
/// Filter to describe one pawn
/// </summary>
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Def loader")]
public class SinglePawnFilter public class SinglePawnFilter
{ {
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public bool? isAnimal; public bool? isAnimal;
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public bool? isSlave; public bool? isSlave;
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public bool? isPrisoner; public bool? isPrisoner;
/// <summary>
/// Check if pawn fits filter conditions
/// </summary>
public bool Applies(Pawn pawn) public bool Applies(Pawn pawn)
{ {
// Fail if any single condition fails
if (isAnimal != null && isAnimal != pawn.IsAnimal()) if (isAnimal != null && isAnimal != pawn.IsAnimal())
return false; return false;

View file

@ -0,0 +1,34 @@
using System.Diagnostics.CodeAnalysis;
using Verse;
namespace RJWSexperience.Ideology.Filters
{
/// <summary>
/// Filter to describe two pawns and relations between them
/// </summary>
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Def loader")]
public class TwoPawnFilter
{
public SinglePawnFilter doer;
public SinglePawnFilter partner;
public RelationFilter relations;
/// <summary>
/// Check if the pair of pawns fits filter conditions
/// </summary>
public bool Applies(Pawn pawn, Pawn partner)
{
// Fail if any single condition fails
if (doer?.Applies(pawn) == false)
return false;
if (this.partner?.Applies(partner) == false)
return false;
if (relations?.Applies(pawn, partner) == false)
return false;
return true;
}
}
}

View file

@ -1,25 +1,14 @@
using HarmonyLib; using System.Reflection;
using RJWSexperience.Ideology.Patches;
using System.Reflection;
using Verse; using Verse;
namespace RJWSexperience.Ideology namespace RJWSexperience.Ideology
{ {
[StaticConstructorOnStartup] [StaticConstructorOnStartup]
internal static class First internal static class Harmony
{ {
static First() static Harmony()
{ {
var harmony = new Harmony("RJW_Sexperience.Ideology"); new HarmonyLib.Harmony("RJW_Sexperience.Ideology").PatchAll(Assembly.GetExecutingAssembly());
harmony.PatchAll(Assembly.GetExecutingAssembly());
if (ModLister.HasActiveModWithName("RJW Sexperience"))
{
harmony.Patch(AccessTools.Method("RJWSexperience.RJWUtility:ThrowVirginHistoryEvent"),
prefix: null,
postfix: new HarmonyMethod(typeof(Sexperience_Patch_ThrowVirginHistoryEvent), nameof(Sexperience_Patch_ThrowVirginHistoryEvent.Postfix))
);
}
} }
} }
} }

View file

@ -1,16 +1,22 @@
using RimWorld; using RimWorld;
using RJWSexperience.Ideology.Filters;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Verse; using Verse;
namespace RJWSexperience.Ideology.HistoryEvents namespace RJWSexperience.Ideology.HistoryEvents
{ {
/// <summary>
/// Type to associate single HistoryEventDef with a TwoPawnFilter
/// </summary>
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Def loader")]
public class TwoPawnEventRule public class TwoPawnEventRule
{ {
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public HistoryEventDef historyEventDef; public HistoryEventDef historyEventDef;
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public TwoPawnFilter filter; public TwoPawnFilter filter;
/// <summary>
/// Check if the pair of pawns fits filter conditions
/// </summary>
public bool Applies(Pawn pawn, Pawn partner) => filter?.Applies(pawn, partner) == true; public bool Applies(Pawn pawn, Pawn partner) => filter?.Applies(pawn, partner) == true;
} }
} }

View file

@ -12,9 +12,9 @@ namespace RJWSexperience.Ideology
if (ideo == null) if (ideo == null)
return false; return false;
if (ideo.HasPrecept(VariousDefOf.Submissive_Female) && pawn.gender == Gender.Female) if (ideo.HasPrecept(RsiDefOf.Precept.Submissive_Female) && pawn.gender == Gender.Female)
return true; return true;
else if (ideo.HasPrecept(VariousDefOf.Submissive_Male) && pawn.gender == Gender.Male) else if (ideo.HasPrecept(RsiDefOf.Precept.Submissive_Male) && pawn.gender == Gender.Male)
return true; return true;
return false; return false;
@ -89,7 +89,7 @@ namespace RJWSexperience.Ideology
Hediff pregnancy = PregnancyHelper.GetPregnancy(pawn); Hediff pregnancy = PregnancyHelper.GetPregnancy(pawn);
// Currently RJW does not check Biotech pregnancy // Currently RJW does not check Biotech pregnancy
if (pregnancy == null && VariousDefOf.PregnantHuman != null) if (pregnancy == null && RsiDefOf.Hediff.PregnantHuman != null)
{ {
pregnancy = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.PregnantHuman); pregnancy = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDefOf.PregnantHuman);
} }

View file

@ -42,6 +42,7 @@
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="BloodRelationDegree.cs" />
<Compile Include="DebugAction.cs" /> <Compile Include="DebugAction.cs" />
<Compile Include="GlobalSuppressions.cs" /> <Compile Include="GlobalSuppressions.cs" />
<Compile Include="HistoryEvents\DefExtension_SecondaryEvents.cs" /> <Compile Include="HistoryEvents\DefExtension_SecondaryEvents.cs" />
@ -52,16 +53,19 @@
<Compile Include="Harmony.cs" /> <Compile Include="Harmony.cs" />
<Compile Include="HistoryEvents\ArgsNamesCustom.cs" /> <Compile Include="HistoryEvents\ArgsNamesCustom.cs" />
<Compile Include="Keyed.cs" /> <Compile Include="Keyed.cs" />
<Compile Include="Precepts\DefExtension_Incest.cs" />
<Compile Include="Precepts\IPreceptTipPostfix.cs" />
<Compile Include="PreceptWorkers\ThoughtWorker_Precept_GenitalSize.cs" /> <Compile Include="PreceptWorkers\ThoughtWorker_Precept_GenitalSize.cs" />
<Compile Include="PreceptWorkers\ThoughtWorker_Precept_GenitalSize_Social.cs" /> <Compile Include="PreceptWorkers\ThoughtWorker_Precept_GenitalSize_Social.cs" />
<Compile Include="PreceptWorkers\ThoughtWorker_Precept_NonPregnant.cs" /> <Compile Include="PreceptWorkers\ThoughtWorker_Precept_NonPregnant.cs" />
<Compile Include="PreceptWorkers\ThoughtWorker_Precept_NonPregnant_Social.cs" /> <Compile Include="PreceptWorkers\ThoughtWorker_Precept_NonPregnant_Social.cs" />
<Compile Include="PreceptWorkers\ThoughtWorker_Precept_Pregnant.cs" /> <Compile Include="PreceptWorkers\ThoughtWorker_Precept_Pregnant.cs" />
<Compile Include="PreceptWorkers\ThoughtWorker_Precept_Pregnant_Social.cs" /> <Compile Include="PreceptWorkers\ThoughtWorker_Precept_Pregnant_Social.cs" />
<Compile Include="RelationFilter.cs" /> <Compile Include="Filters\RelationFilter.cs" />
<Compile Include="RsiHistoryEventDefOf.cs" /> <Compile Include="RelationHelpers.cs" />
<Compile Include="TwoPawnFilter.cs" /> <Compile Include="RomanceChanceFactorHelpers.cs" />
<Compile Include="SinglePawnFilter.cs" /> <Compile Include="Filters\TwoPawnFilter.cs" />
<Compile Include="Filters\SinglePawnFilter.cs" />
<Compile Include="Precepts\Comp_SelfTookMemoryThought_Gendered.cs" /> <Compile Include="Precepts\Comp_SelfTookMemoryThought_Gendered.cs" />
<Compile Include="Precepts\Comp_KnowsMemoryThought_Gendered.cs" /> <Compile Include="Precepts\Comp_KnowsMemoryThought_Gendered.cs" />
<Compile Include="HistoryEvents\HistoryEventDefExtensionMethods.cs" /> <Compile Include="HistoryEvents\HistoryEventDefExtensionMethods.cs" />
@ -84,17 +88,19 @@
<Compile Include="Rituals\RitualBehaviorWorkers.cs" /> <Compile Include="Rituals\RitualBehaviorWorkers.cs" />
<Compile Include="Rituals\RitualOutcomeComps.cs" /> <Compile Include="Rituals\RitualOutcomeComps.cs" />
<Compile Include="Rituals\RitualRoles.cs" /> <Compile Include="Rituals\RitualRoles.cs" />
<Compile Include="RsiMod.cs" />
<Compile Include="RsiSettings.cs" />
<Compile Include="StatParts.cs" /> <Compile Include="StatParts.cs" />
<Compile Include="IdeoUtility.cs" /> <Compile Include="IdeoUtility.cs" />
<Compile Include="Thoughts\ThoughtDefExtension_IncreaseRecord.cs" /> <Compile Include="Thoughts\ThoughtDefExtension_IncreaseRecord.cs" />
<Compile Include="Thoughts\ThoughtDefExtension_StageFromValue.cs" /> <Compile Include="Thoughts\ThoughtDefExtension_StageFromValue.cs" />
<Compile Include="Thoughts\Thought_IncreaseRecord.cs" /> <Compile Include="Thoughts\Thought_IncreaseRecord.cs" />
<Compile Include="Thoughts\Thought_Opinionbased.cs" /> <Compile Include="Thoughts\Thought_Opinionbased.cs" />
<Compile Include="VariousDefOf.cs" /> <Compile Include="RsiDefOf.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Krafs.Rimworld.Ref"> <PackageReference Include="Krafs.Rimworld.Ref">
<Version>1.4.3537</Version> <Version>1.4.3704</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Lib.Harmony"> <PackageReference Include="Lib.Harmony">
<Version>2.2.2</Version> <Version>2.2.2</Version>

View file

@ -4,11 +4,17 @@ namespace RJWSexperience.Ideology
{ {
public static class Keyed public static class Keyed
{ {
public static readonly string ModTitle = "RSI_Mod_Title".Translate();
public static readonly string MemeStatFactor = "MemeStatFactor".Translate(); public static readonly string MemeStatFactor = "MemeStatFactor".Translate();
public static readonly string RSVictimCondition = "RSVictimCondition".Translate(); public static readonly string RSVictimCondition = "RSVictimCondition".Translate();
public static readonly string RSBreederCondition = "RSBreederCondition".Translate(); public static readonly string RSBreederCondition = "RSBreederCondition".Translate();
public static readonly string RSNotHuman = "RSNotHuman".Translate(); public static readonly string RSNotHuman = "RSNotHuman".Translate();
public static readonly string RSNotAnimal = "RSNotAnimal".Translate(); public static readonly string RSNotAnimal = "RSNotAnimal".Translate();
public static readonly string RSShouldCanFuck = "RSShouldCanFuck".Translate(); public static readonly string RSShouldCanFuck = "RSShouldCanFuck".Translate();
public static readonly string PatchRomanceChanceFactor = "RSI_PatchRomanceChanceFactor".Translate();
public static readonly string PatchRomanceChanceFactorTip = "RSI_PatchRomanceChanceFactorTip".Translate();
public static readonly string PatchIncestuousManualRomance = "RSI_PatchIncestuousManualRomance".Translate();
public static readonly string PatchIncestuousManualRomanceTip = "RSI_PatchIncestuousManualRomanceTip".Translate();
} }
} }

View file

@ -15,7 +15,7 @@ namespace RJWSexperience.Ideology.Patches
if (__result < 0f || pawn.Ideo == null) // ideo is null if don't have dlc if (__result < 0f || pawn.Ideo == null) // ideo is null if don't have dlc
return; return;
if (!RsiHistoryEventDefOf.RSI_SexWithAnimal.CreateEvent(pawn).DoerWillingToDo()) if (!RsiDefOf.HistoryEvent.RSI_SexWithAnimal.CreateEvent(pawn).DoerWillingToDo())
{ {
__result = -2f; __result = -2f;
return; return;
@ -32,7 +32,7 @@ namespace RJWSexperience.Ideology.Patches
if (__result < 0f || pawn.Ideo == null) // ideo is null if don't have dlc if (__result < 0f || pawn.Ideo == null) // ideo is null if don't have dlc
return; return;
if (!RsiHistoryEventDefOf.RSI_Raped.CreateEvent(pawn).DoerWillingToDo()) if (!RsiDefOf.HistoryEvent.RSI_Raped.CreateEvent(pawn).DoerWillingToDo())
{ {
__result = -2f; __result = -2f;
return; return;
@ -48,7 +48,7 @@ namespace RJWSexperience.Ideology.Patches
if (__result < 0f || pawn.Ideo == null) // ideo is null if don't have dlc if (__result < 0f || pawn.Ideo == null) // ideo is null if don't have dlc
return; return;
if (!RsiHistoryEventDefOf.RSI_SexWithCorpse.CreateEvent(pawn).DoerWillingToDo()) if (!RsiDefOf.HistoryEvent.RSI_SexWithCorpse.CreateEvent(pawn).DoerWillingToDo())
{ {
__result = -2f; __result = -2f;
return; return;
@ -65,7 +65,7 @@ namespace RJWSexperience.Ideology.Patches
if (__result < 0f || p.Ideo == null) // ideo is null if don't have dlc if (__result < 0f || p.Ideo == null) // ideo is null if don't have dlc
return; return;
if (!RsiHistoryEventDefOf.RSI_Masturbated.CreateEvent(p).DoerWillingToDo()) if (!RsiDefOf.HistoryEvent.RSI_Masturbated.CreateEvent(p).DoerWillingToDo())
{ {
__result = -2f; __result = -2f;
return; return;

View file

@ -19,7 +19,7 @@ namespace RJWSexperience.Ideology.Patches
Ideo ideo = pawn.Ideo; Ideo ideo = pawn.Ideo;
if (ideo != null && !pawn.IsSubmissive()) if (ideo != null && !pawn.IsSubmissive())
{ {
__result = __result || ideo.HasMeme(VariousDefOf.Rapist); __result = __result || ideo.HasMeme(RsiDefOf.Meme.Rapist);
} }
} }
} }
@ -32,7 +32,7 @@ namespace RJWSexperience.Ideology.Patches
Ideo ideo = pawn.Ideo; Ideo ideo = pawn.Ideo;
if (ideo != null) if (ideo != null)
{ {
__result = __result || ideo.HasMeme(VariousDefOf.Zoophile); __result = __result || ideo.HasMeme(RsiDefOf.Meme.Zoophile);
} }
} }
} }
@ -45,7 +45,7 @@ namespace RJWSexperience.Ideology.Patches
Ideo ideo = pawn.Ideo; Ideo ideo = pawn.Ideo;
if (ideo != null) if (ideo != null)
{ {
__result = __result || ideo.HasMeme(VariousDefOf.Necrophile); __result = __result || ideo.HasMeme(RsiDefOf.Meme.Necrophile);
} }
} }
} }
@ -85,10 +85,10 @@ namespace RJWSexperience.Ideology.Patches
private static void AfterSexHuman(Pawn human, Pawn partner) private static void AfterSexHuman(Pawn human, Pawn partner)
{ {
RsiHistoryEventDefOf.RSI_NonIncestuosSex.RecordEventWithPartner(human, partner); RsiDefOf.HistoryEvent.RSI_NonIncestuosSex.RecordEventWithPartner(human, partner);
if (partner.IsAnimal()) if (partner.IsAnimal())
RsiHistoryEventDefOf.RSI_SexWithAnimal.RecordEventWithPartner(human, partner); RsiDefOf.HistoryEvent.RSI_SexWithAnimal.RecordEventWithPartner(human, partner);
} }
} }
@ -113,11 +113,13 @@ namespace RJWSexperience.Ideology.Patches
public static float PreceptSextype(Pawn pawn, Pawn partner, float score, List<HistoryEventDef> historyEventDefs) public static float PreceptSextype(Pawn pawn, Pawn partner, float score, List<HistoryEventDef> historyEventDefs)
{ {
foreach(HistoryEventDef eventDef in historyEventDefs) for (int i = 0; i < historyEventDefs.Count; i++)
{ {
HistoryEventDef eventDef = historyEventDefs[i];
if (eventDef.CreateEventWithPartner(pawn, partner).DoerWillingToDo()) if (eventDef.CreateEventWithPartner(pawn, partner).DoerWillingToDo())
{ {
float mult = 8.0f * Math.Max(0.3f, 1 / Math.Max(0.01f, pawn.GetStatValue(xxx.sex_drive_stat))); float mult = 8.0f * Math.Max(0.3f, 1 / Math.Max(0.01f, pawn.GetStatValue(xxx.sex_drive_stat, cacheStaleAfterTicks: 60)));
return score * mult; return score * mult;
} }
} }
@ -148,7 +150,7 @@ namespace RJWSexperience.Ideology.Patches
public static void Postfix(Pawn pawn, ref bool __result) public static void Postfix(Pawn pawn, ref bool __result)
{ {
Ideo ideo = pawn.Ideo; Ideo ideo = pawn.Ideo;
if (ideo?.HasMeme(VariousDefOf.Zoophile) == true) if (ideo?.HasMeme(RsiDefOf.Meme.Zoophile) == true)
{ {
SaveStorage.DataStore.GetPawnData(pawn).CanDesignateBreeding = true; SaveStorage.DataStore.GetPawnData(pawn).CanDesignateBreeding = true;
__result = true; __result = true;
@ -213,14 +215,14 @@ namespace RJWSexperience.Ideology.Patches
Ideo mainideo = playerfaction.ideos.PrimaryIdeo; Ideo mainideo = playerfaction.ideos.PrimaryIdeo;
if (mainideo != null) if (mainideo != null)
{ {
if (mainideo.HasPrecept(VariousDefOf.BabyFaction_AlwaysFather)) if (mainideo.HasPrecept(RsiDefOf.Precept.BabyFaction_AlwaysFather))
{ {
Pawn parent = baby.GetFather() ?? baby.GetMother(); Pawn parent = baby.GetFather() ?? baby.GetMother();
ideo = parent.Ideo; ideo = parent.Ideo;
return parent.Faction; return parent.Faction;
} }
else if (mainideo.HasPrecept(VariousDefOf.BabyFaction_AlwaysColony)) else if (mainideo.HasPrecept(RsiDefOf.Precept.BabyFaction_AlwaysColony))
{ {
ideo = mainideo; ideo = mainideo;
return playerfaction; return playerfaction;
@ -241,7 +243,7 @@ namespace RJWSexperience.Ideology.Patches
if (props.pawn?.Ideo == null || !props.hasPartner()) if (props.pawn?.Ideo == null || !props.hasPartner())
return; return;
if (props.partner.Ideo?.HasPrecept(VariousDefOf.ProselyzingByOrgasm) == true) if (props.partner.Ideo?.HasPrecept(RsiDefOf.Precept.ProselyzingByOrgasm) == true)
{ {
// Pawn is the one having the orgasm // Pawn is the one having the orgasm
// Partner is "giving" the orgasm, hence the pawn will be converted towards the partners ideology // Partner is "giving" the orgasm, hence the pawn will be converted towards the partners ideology

View file

@ -1,9 +1,14 @@
using HarmonyLib; using HarmonyLib;
using Mono.Cecil.Cil;
using RimWorld; using RimWorld;
using rjw; using rjw;
using RJWSexperience.Ideology.HistoryEvents; using RJWSexperience.Ideology.HistoryEvents;
using RJWSexperience.Ideology.Precepts; using RJWSexperience.Ideology.Precepts;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using Verse; using Verse;
namespace RJWSexperience.Ideology.Patches namespace RJWSexperience.Ideology.Patches
@ -13,8 +18,8 @@ namespace RJWSexperience.Ideology.Patches
{ {
public static void Postfix(Pawn firstPawn, Pawn secondPawn) public static void Postfix(Pawn firstPawn, Pawn secondPawn)
{ {
RsiHistoryEventDefOf.RSI_NonIncestuosMarriage.RecordEventWithPartner(firstPawn, secondPawn); RsiDefOf.HistoryEvent.RSI_NonIncestuosMarriage.RecordEventWithPartner(firstPawn, secondPawn);
RsiHistoryEventDefOf.RSI_NonIncestuosMarriage.RecordEventWithPartner(secondPawn, firstPawn); RsiDefOf.HistoryEvent.RSI_NonIncestuosMarriage.RecordEventWithPartner(secondPawn, firstPawn);
} }
} }
@ -53,4 +58,193 @@ namespace RJWSexperience.Ideology.Patches
} }
} }
} }
[HarmonyPatch(typeof(RelationsUtility), "Incestuous")]
public static class Rimworld_Patch_IncestuousManualRomance
{
public static bool Prepare() => RsiMod.Prefs.patchIncestuousManualRomance;
/// <summary>
/// Override incestuous check in the manual romance
/// </summary>
/// <param name="one">Pawn to try do romance</param>
/// <param name="two">Target for romance</param>
/// <param name="__result">Result of the original method</param>
/// <returns>Run original method implementation</returns>
public static bool Prefix(Pawn one, Pawn two, ref bool __result)
{
__result = RsiIncestuous(one, two);
return false;
}
/// <summary>
/// Check if Ideology allows romance attempt
/// </summary>
/// <param name="one">Pawn to try do romance</param>
/// <param name="two">Target for romance</param>
/// <returns>Forbid romance option</returns>
public static bool RsiIncestuous(Pawn one, Pawn two)
{
PreceptDef incestuousPrecept = one.Ideo?.PreceptsListForReading.Select(precept => precept.def).FirstOrFallback(def => def.issue == RsiDefOf.Issue.Incestuos);
var allowManualRomanceOnlyFor = incestuousPrecept?.GetModExtension<DefExtension_Incest>()?.allowManualRomanceOnlyFor;
BloodRelationDegree relationDegree = RelationHelpers.GetBloodRelationDegree(one, two);
if (allowManualRomanceOnlyFor == null)
{
return relationDegree < BloodRelationDegree.NotRelated;
}
return !allowManualRomanceOnlyFor.Contains(relationDegree);
}
}
[HarmonyPatch(typeof(Pawn_RelationsTracker), nameof(Pawn_RelationsTracker.SecondaryRomanceChanceFactor))]
public static class Rimworld_Patch_SecondaryRomanceChanceFactor
{
public static bool Prepare() => RsiMod.Prefs.patchRomanceChanceFactor;
/// <summary>
/// <para>
/// Replace
/// float num = 1f;
/// foreach (PawnRelationDef pawnRelationDef in this.pawn.GetRelations(otherPawn))
/// {
/// num *= pawnRelationDef.romanceChanceFactor;
/// }
/// </para>
/// <para>with</para>
/// <para>
/// float num = 1f;
/// num = RomanceChanceFactorHelpers.GetRomanceChanceFactor(this.pawn, otherPawn)
/// </para>
/// </summary>
/// <param name="instructions">Original method body</param>
/// <returns>Modified method body</returns>
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
MethodInfo getRelationsInfo = AccessTools.Method(
typeof(PawnRelationUtility),
nameof(PawnRelationUtility.GetRelations),
new[] { typeof(Pawn), typeof(Pawn) });
MethodInfo helperInfo = AccessTools.Method(
typeof(RomanceChanceFactorHelpers),
nameof(RomanceChanceFactorHelpers.GetRomanceChanceFactor),
new[] { typeof(Pawn), typeof(Pawn) });
// Original IL looks something like this:
// Load this.pawn
// Load otherPawn
// Call GetRelations
// Start loop
// ...
// Mul num and romanceChanceFactor
// Store result
// ...
// Endfinaly
// Idea is to substitute GetRelations call with a method with the same signature,
// store results in the same place original loop does and remove everything else until Endfinaly
IEnumerator<CodeInstruction> enumerator = instructions.GetEnumerator();
bool endOfInstructions = !enumerator.MoveNext();
// Find and replace GetRelations
while (!endOfInstructions)
{
var instruction = enumerator.Current;
if (instruction.Calls(getRelationsInfo))
{
yield return new CodeInstruction(OpCodes.Call, helperInfo);
enumerator.MoveNext(); // skip original method call
break;
}
yield return instruction;
endOfInstructions = !enumerator.MoveNext();
}
if (endOfInstructions)
{
Log.Error("[RSI] Failed to transpile Pawn_RelationsTracker.SecondaryRomanceChanceFactor: PawnRelationUtility.GetRelations call not found");
yield break;
}
// Skip everything until Mul
while (!endOfInstructions)
{
if (enumerator.Current.opcode == OpCodes.Mul)
{
enumerator.MoveNext(); // skip Mul
yield return enumerator.Current; // return next op, it should be "store result"
break;
}
endOfInstructions = !enumerator.MoveNext();
}
if (endOfInstructions)
{
Log.Error("[RSI] Failed to transpile Pawn_RelationsTracker.SecondaryRomanceChanceFactor: Mul not found. This error means half of SecondaryRomanceChanceFactor was erased. Very not good");
yield break;
}
// Skip the rest of the loop
while (!endOfInstructions)
{
if (enumerator.Current.opcode == OpCodes.Endfinally)
{
// Endfinally will be skipped by the next MoveNext()
break;
}
endOfInstructions = !enumerator.MoveNext();
}
if (endOfInstructions)
{
Log.Error("[RSI] Failed to transpile Pawn_RelationsTracker.SecondaryRomanceChanceFactor: Endfinally not found. This error means half of SecondaryRomanceChanceFactor was erased. Very not good");
yield break;
}
// Return the rest of the method
while (enumerator.MoveNext())
{
yield return enumerator.Current;
}
if (Prefs.DevMode) Log.Message("[RSI] Successfully transpiled Pawn_RelationsTracker.SecondaryRomanceChanceFactor");
}
[HarmonyPatch(typeof(Precept), nameof(Precept.GetTip))]
public static class Rimworld_Patch_PreceptTip
{
public static void Postfix(ref string __result, Precept __instance)
{
if (__instance.def.modExtensions.NullOrEmpty())
{
return;
}
bool tipChanged = false;
StringBuilder tipBuilder = new StringBuilder(__result);
tipBuilder.AppendLine();
tipBuilder.AppendInNewLine((Keyed.ModTitle + ":").Colorize(ColoredText.TipSectionTitleColor));
for (int i = 0; i < __instance.def.modExtensions.Count; i++)
{
if (__instance.def.modExtensions[i] is IPreceptTipPostfix tipPostfix)
{
tipBuilder.AppendInNewLine(" - " + tipPostfix.GetTip());
tipChanged = true;
}
}
if (tipChanged)
{
__result = tipBuilder.ToString();
}
}
}
}
} }

View file

@ -1,21 +1,25 @@
using rjw; using HarmonyLib;
using rjw;
using RJWSexperience.Ideology.HistoryEvents; using RJWSexperience.Ideology.HistoryEvents;
using Verse; using Verse;
namespace RJWSexperience.Ideology.Patches namespace RJWSexperience.Ideology.Patches
{ {
[HarmonyPatch("RJWSexperience.RJWUtility", "ThrowVirginHistoryEvent")]
public static class Sexperience_Patch_ThrowVirginHistoryEvent public static class Sexperience_Patch_ThrowVirginHistoryEvent
{ {
public static bool Prepare() => ModsConfig.IsActive("rjw.sexperience");
public static void Postfix(Pawn exVirgin, Pawn partner, SexProps props, int degree) public static void Postfix(Pawn exVirgin, Pawn partner, SexProps props, int degree)
{ {
const int femaleAfterSurgery = 1; const int femaleAfterSurgery = 1;
if (props.isRape && exVirgin == props.partner) if (props.isRape && exVirgin == props.partner)
RsiHistoryEventDefOf.RSI_VirginStolen.RecordEventWithPartner(exVirgin, partner); RsiDefOf.HistoryEvent.RSI_VirginStolen.RecordEventWithPartner(exVirgin, partner);
else if (degree != femaleAfterSurgery) else if (degree != femaleAfterSurgery)
RsiHistoryEventDefOf.RSI_VirginTaken.RecordEventWithPartner(exVirgin, partner); RsiDefOf.HistoryEvent.RSI_VirginTaken.RecordEventWithPartner(exVirgin, partner);
RsiHistoryEventDefOf.RSI_TookVirgin.RecordEventWithPartner(partner, exVirgin); RsiDefOf.HistoryEvent.RSI_TookVirgin.RecordEventWithPartner(partner, exVirgin);
} }
} }
} }

View file

@ -0,0 +1,73 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Verse;
namespace RJWSexperience.Ideology.Precepts
{
/// <summary>
/// Special Def extension for the Incestuous issue precepts
/// </summary>
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Def loader")]
public class DefExtension_Incest : DefModExtension
{
public List<BloodRelationDegree> allowManualRomanceOnlyFor;
public List<BloodRelationDegreeFactor> bloodRelationDegreeRomanceFactors;
private Dictionary<BloodRelationDegree, float> _relationDegreeFactorsDict;
public bool TryGetRomanceChanceFactor(BloodRelationDegree relationDegree, out float romanceChanceFactor)
{
if (bloodRelationDegreeRomanceFactors.NullOrEmpty())
{
romanceChanceFactor = 1f;
return false;
}
if (_relationDegreeFactorsDict == null)
{
_relationDegreeFactorsDict = new Dictionary<BloodRelationDegree, float>();
foreach (BloodRelationDegreeFactor relationDegreeFactor in bloodRelationDegreeRomanceFactors)
{
_relationDegreeFactorsDict.Add((BloodRelationDegree)relationDegreeFactor.bloodRelationDegree, relationDegreeFactor.romanceChanceFactor);
}
}
return _relationDegreeFactorsDict.TryGetValue(relationDegree, out romanceChanceFactor);
}
public override IEnumerable<string> ConfigErrors()
{
foreach (string error in base.ConfigErrors())
{
yield return error;
}
foreach (BloodRelationDegreeFactor factor in bloodRelationDegreeRomanceFactors)
{
foreach(string error in factor.ConfigErrors())
{
yield return error;
}
}
}
public class BloodRelationDegreeFactor
{
public BloodRelationDegree? bloodRelationDegree;
public float romanceChanceFactor;
public IEnumerable<string> ConfigErrors()
{
if (bloodRelationDegree == null)
{
yield return "<bloodRelationDegree> is empty";
}
if (romanceChanceFactor == 0f)
{
yield return "<romanceChanceFactor> should be > 0";
}
}
}
}
}

View file

@ -2,5 +2,6 @@
{ {
public class DefExtension_ModifyBestialityMtb : DefExtension_ModifyMtb public class DefExtension_ModifyBestialityMtb : DefExtension_ModifyMtb
{ {
protected override string TipTemplateKey => "RSI_PreceptTipModifyBestialityMtb";
} }
} }

View file

@ -2,5 +2,6 @@
{ {
public class DefExtension_ModifyFappinMtb : DefExtension_ModifyMtb public class DefExtension_ModifyFappinMtb : DefExtension_ModifyMtb
{ {
protected override string TipTemplateKey => "RSI_PreceptTipModifyFappinMtb";
} }
} }

View file

@ -1,11 +1,28 @@
using System.Diagnostics.CodeAnalysis; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Verse; using Verse;
namespace RJWSexperience.Ideology.Precepts namespace RJWSexperience.Ideology.Precepts
{ {
public abstract class DefExtension_ModifyMtb : DefModExtension [SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field values are loaded from XML")]
public abstract class DefExtension_ModifyMtb : DefModExtension, IPreceptTipPostfix
{ {
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")] protected abstract string TipTemplateKey { get; }
public float multiplier = 1f; public float multiplier = 1f;
public string GetTip() => TipTemplateKey.Translate(multiplier.ToString());
public override IEnumerable<string> ConfigErrors()
{
if (multiplier == 1f)
{
yield return "There is no point if <multiplier> is 1";
}
else if (multiplier <= 0f)
{
yield return "<multiplier> must be > 0";
}
}
} }
} }

View file

@ -2,5 +2,6 @@
{ {
public class DefExtension_ModifyNecroMtb : DefExtension_ModifyMtb public class DefExtension_ModifyNecroMtb : DefExtension_ModifyMtb
{ {
protected override string TipTemplateKey => "RSI_PreceptTipModifyNecroMtb";
} }
} }

View file

@ -1,30 +1,41 @@
using System.Collections.Generic; using RJWSexperience.Ideology.Filters;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Verse; using Verse;
namespace RJWSexperience.Ideology.Precepts namespace RJWSexperience.Ideology.Precepts
{ {
/// <summary>
/// Def extension to enable changing SexAppraiser results based on filters
/// </summary>
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Def loader")]
public class DefExtension_ModifyPreference : DefModExtension public class DefExtension_ModifyPreference : DefModExtension
{ {
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public List<Rule> rules; public List<Rule> rules;
/// <summary>
/// Apply SexAppraiser modifiers from rules with a satisfied filter
/// </summary>
public void Apply(Pawn pawn, Pawn partner, ref float preference) public void Apply(Pawn pawn, Pawn partner, ref float preference)
{ {
foreach (Rule rule in rules) foreach (Rule rule in rules.Where(rule => rule.Applies(pawn, partner)))
{ {
if (rule.Applies(pawn, partner))
preference *= rule.multiplier; preference *= rule.multiplier;
} }
} }
/// <summary>
/// Type to associate SexAppraiser result modifier with a TwoPawnFilter
/// </summary>
public class Rule public class Rule
{ {
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public float multiplier = 1f; public float multiplier = 1f;
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public TwoPawnFilter filter; public TwoPawnFilter filter;
/// <summary>
/// Check if the pair of pawns fits filter conditions
/// </summary>
public bool Applies(Pawn pawn, Pawn partner) public bool Applies(Pawn pawn, Pawn partner)
{ {
if (filter == null) if (filter == null)

View file

@ -2,5 +2,6 @@
{ {
public class DefExtension_ModifyRapeCPMtb : DefExtension_ModifyMtb public class DefExtension_ModifyRapeCPMtb : DefExtension_ModifyMtb
{ {
protected override string TipTemplateKey => "RSI_PreceptTipModifyRapeCPMtb";
} }
} }

View file

@ -0,0 +1,7 @@
namespace RJWSexperience.Ideology.Precepts
{
public interface IPreceptTipPostfix
{
string GetTip();
}
}

View file

@ -0,0 +1,52 @@
using RimWorld;
using System.Linq;
using Verse;
namespace RJWSexperience.Ideology
{
public static class RelationHelpers
{
/// <summary>
/// Get degree of blood relation between two pawns
/// </summary>
public static BloodRelationDegree GetBloodRelationDegree(Pawn pawn, Pawn partner)
{
if (!pawn.relations.FamilyByBlood.Contains(partner))
{
return BloodRelationDegree.NotRelated;
}
PawnRelationDef closestBloodRelation = pawn
.GetRelations(partner)
?.Where(def => def.familyByBloodRelation)
?.OrderByDescending(def => def.importance)
?.FirstOrFallback();
if (closestBloodRelation == null)
{
return BloodRelationDegree.NotRelated;
}
return GetBloodRelationDegree(closestBloodRelation);
}
/// <summary>
/// Get degree of blood relation for a relationDef
/// </summary>
public static BloodRelationDegree GetBloodRelationDegree(PawnRelationDef relationDef)
{
if (!relationDef.familyByBloodRelation)
{
return BloodRelationDegree.NotRelated;
}
else if (relationDef.importance <= PawnRelationDefOf.Cousin.importance)
{
return BloodRelationDegree.FarRelative;
}
else
{
return BloodRelationDegree.CloseRelative;
}
}
}
}

View file

@ -1,13 +1,9 @@
using System; using RimWorld;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using rjw; using rjw;
using System;
using System.Collections.Generic;
using Verse; using Verse;
using Verse.AI; using Verse.AI;
using RimWorld;
namespace RJWSexperience.Ideology namespace RJWSexperience.Ideology
{ {
@ -15,26 +11,24 @@ namespace RJWSexperience.Ideology
{ {
protected override Job TryGiveJob(Pawn pawn) protected override Job TryGiveJob(Pawn pawn)
{ {
if (pawn.Drafted) return null; if (pawn.Drafted || pawn.mindState == null)
DutyDef dutyDef = null;
PawnDuty duty = null;
if (pawn.mindState != null)
{ {
duty = pawn.mindState.duty; return null;
dutyDef = duty.def;
} }
else return null;
if (dutyDef == DutyDefOf.TravelOrLeave || !xxx.can_do_loving(pawn)) PawnDuty duty = pawn.mindState.duty;
if (duty.def == DutyDefOf.TravelOrLeave || !xxx.can_do_loving(pawn))
{ {
return null; return null;
} }
Pawn target = FindPartner(pawn, duty); Pawn target = FindPartner(pawn, duty);
if (target == null || !pawn.CanReserveAndReach(target, PathEndMode.ClosestTouch, Danger.None,1)) return JobMaker.MakeJob(VariousDefOf.DrugMasturbate); if (target == null || !pawn.CanReserveAndReach(target, PathEndMode.ClosestTouch, Danger.None, 1))
return JobMaker.MakeJob(RsiDefOf.Job.DrugMasturbate);
return JobMaker.MakeJob(VariousDefOf.DrugSex, target); return JobMaker.MakeJob(RsiDefOf.Job.DrugSex, target);
} }
protected Pawn FindPartner(Pawn pawn, PawnDuty duty) protected Pawn FindPartner(Pawn pawn, PawnDuty duty)
@ -42,14 +36,11 @@ namespace RJWSexperience.Ideology
if (duty != null) if (duty != null)
{ {
List<Pawn> pawns = pawn.Map.mapPawns.AllPawnsSpawned.FindAll(x => x.mindState?.duty?.def == duty.def); List<Pawn> pawns = pawn.Map.mapPawns.AllPawnsSpawned.FindAll(x => x.mindState?.duty?.def == duty.def);
return pawns.RandomElementByWeightWithDefault(x => SexAppraiser.would_fuck(pawn,x), 0.1f); return pawns.RandomElementByWeightWithDefault(x => SexAppraiser.would_fuck(pawn, x), 0.1f);
} }
return null; return null;
} }
} }
/// <summary> /// <summary>
@ -65,7 +56,7 @@ namespace RJWSexperience.Ideology
protected override IEnumerable<Toil> MakeNewToils() protected override IEnumerable<Toil> MakeNewToils()
{ {
setup_ticks(); setup_ticks();
var PartnerJob = VariousDefOf.GettinDrugSex; var PartnerJob = RsiDefOf.Job.GettinDrugSex;
this.FailOnDespawnedNullOrForbidden(iTarget); this.FailOnDespawnedNullOrForbidden(iTarget);
this.FailOn(() => !Partner.health.capacities.CanBeAwake); this.FailOn(() => !Partner.health.capacities.CanBeAwake);
@ -73,41 +64,46 @@ namespace RJWSexperience.Ideology
this.FailOn(() => Partner == null); this.FailOn(() => Partner == null);
yield return Toils_Goto.GotoThing(iTarget, PathEndMode.OnCell); yield return Toils_Goto.GotoThing(iTarget, PathEndMode.OnCell);
Toil WaitForPartner = new Toil(); Toil WaitForPartner = new Toil
WaitForPartner.defaultCompleteMode = ToilCompleteMode.Delay; {
WaitForPartner.initAction = delegate defaultCompleteMode = ToilCompleteMode.Delay,
initAction = delegate
{ {
ticksLeftThisToil = 5000; ticksLeftThisToil = 5000;
}; },
WaitForPartner.tickAction = delegate tickAction = delegate
{ {
pawn.GainComfortFromCellIfPossible(); pawn.GainComfortFromCellIfPossible();
if (pawn.Position.DistanceTo(Partner.Position) <= 1f) if (pawn.Position.DistanceTo(Partner.Position) <= 1f)
{ {
ReadyForNextToil(); ReadyForNextToil();
} }
}
}; };
yield return WaitForPartner; yield return WaitForPartner;
Toil StartPartnerJob = new Toil(); Toil StartPartnerJob = new Toil
StartPartnerJob.defaultCompleteMode = ToilCompleteMode.Instant;
StartPartnerJob.socialMode = RandomSocialMode.Off;
StartPartnerJob.initAction = delegate
{ {
var dri = Partner.jobs.curDriver as JobDriver_DrugSexReceiver; defaultCompleteMode = ToilCompleteMode.Instant,
if (dri == null) socialMode = RandomSocialMode.Off,
initAction = delegate
{
if (!(Partner.jobs.curDriver is JobDriver_DrugSexReceiver))
{ {
Job gettingQuickie = JobMaker.MakeJob(PartnerJob, pawn, Partner); Job gettingQuickie = JobMaker.MakeJob(PartnerJob, pawn, Partner);
Partner.jobs.StartJob(gettingQuickie, JobCondition.InterruptForced); Partner.jobs.StartJob(gettingQuickie, JobCondition.InterruptForced);
} }
}
}; };
yield return StartPartnerJob; yield return StartPartnerJob;
Toil SexToil = new Toil(); Toil SexToil = new Toil
SexToil.defaultCompleteMode = ToilCompleteMode.Never; {
SexToil.socialMode = RandomSocialMode.Off; defaultCompleteMode = ToilCompleteMode.Never,
SexToil.defaultDuration = duration; socialMode = RandomSocialMode.Off,
SexToil.handlingFacing = true; defaultDuration = duration,
handlingFacing = true
};
SexToil.FailOn(() => Partner.CurJob.def != PartnerJob); SexToil.FailOn(() => Partner.CurJob.def != PartnerJob);
SexToil.initAction = delegate SexToil.initAction = delegate
{ {
@ -148,7 +144,6 @@ namespace RJWSexperience.Ideology
/// </summary> /// </summary>
public class JobDriver_DrugSexReceiver : JobDriver_SexBaseRecieverLoved public class JobDriver_DrugSexReceiver : JobDriver_SexBaseRecieverLoved
{ {
protected override IEnumerable<Toil> MakeNewToils() protected override IEnumerable<Toil> MakeNewToils()
{ {
setup_ticks(); setup_ticks();
@ -175,16 +170,18 @@ namespace RJWSexperience.Ideology
protected Toil MakeSexToil() protected Toil MakeSexToil()
{ {
Toil get_loved = new Toil(); Toil get_loved = new Toil
get_loved.defaultCompleteMode = ToilCompleteMode.Never;
get_loved.socialMode = RandomSocialMode.Off;
get_loved.handlingFacing = true;
get_loved.tickAction = delegate
{ {
defaultCompleteMode = ToilCompleteMode.Never,
socialMode = RandomSocialMode.Off,
handlingFacing = true,
tickAction = delegate
{
}
}; };
get_loved.AddEndCondition(new Func<JobCondition>(() => get_loved.AddEndCondition(new Func<JobCondition>(() =>
{ {
if (parteners.Count <= 0) if (parteners.Count == 0)
{ {
return JobCondition.Succeeded; return JobCondition.Succeeded;
} }
@ -205,7 +202,6 @@ namespace RJWSexperience.Ideology
/// </summary> /// </summary>
public class JobDriver_DrugMasturabate : JobDriver_Masturbate public class JobDriver_DrugMasturabate : JobDriver_Masturbate
{ {
protected override IEnumerable<Toil> MakeNewToils() protected override IEnumerable<Toil> MakeNewToils()
{ {
setup_ticks(); setup_ticks();
@ -252,6 +248,4 @@ namespace RJWSexperience.Ideology
}; };
} }
} }
} }

View file

@ -1,13 +1,9 @@
using System; using RimWorld;
using rjw;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse; using Verse;
using Verse.AI; using Verse.AI;
using Verse.AI.Group;
using RimWorld;
using rjw;
namespace RJWSexperience.Ideology namespace RJWSexperience.Ideology
{ {
@ -15,30 +11,27 @@ namespace RJWSexperience.Ideology
{ {
protected override Job TryGiveJob(Pawn pawn) protected override Job TryGiveJob(Pawn pawn)
{ {
if (pawn.Drafted) return null; if (pawn.Drafted || pawn.mindState == null)
DutyDef dutyDef = null;
PawnDuty duty = null;
if (pawn.mindState != null)
{ {
duty = pawn.mindState.duty; return null;
dutyDef = duty.def;
} }
else return null;
if (dutyDef == DutyDefOf.TravelOrLeave || !xxx.can_do_loving(pawn)) PawnDuty duty = pawn.mindState.duty;
if (duty.def == DutyDefOf.TravelOrLeave || !xxx.can_do_loving(pawn))
{ {
return null; return null;
} }
Pawn target = duty.focusSecond.Pawn; Pawn target = duty.focusSecond.Pawn;
if (!pawn.CanReach(target, PathEndMode.ClosestTouch, Danger.None)) return null; if (!pawn.CanReach(target, PathEndMode.ClosestTouch, Danger.None))
return null;
return JobMaker.MakeJob(VariousDefOf.Gangbang, target); return JobMaker.MakeJob(RsiDefOf.Job.Gangbang, target);
} }
} }
public class JobDriver_Gangbang : JobDriver_SexBaseInitiator public class JobDriver_Gangbang : JobDriver_SexBaseInitiator
{ {
public override bool TryMakePreToilReservations(bool errorOnFailed) public override bool TryMakePreToilReservations(bool errorOnFailed)
@ -56,26 +49,28 @@ namespace RJWSexperience.Ideology
this.FailOn(() => Partner.Drafted); this.FailOn(() => Partner.Drafted);
yield return Toils_Goto.GotoThing(iTarget, PathEndMode.OnCell); yield return Toils_Goto.GotoThing(iTarget, PathEndMode.OnCell);
Toil StartPartnerJob = new Toil(); Toil StartPartnerJob = new Toil
StartPartnerJob.defaultCompleteMode = ToilCompleteMode.Instant;
StartPartnerJob.socialMode = RandomSocialMode.Off;
StartPartnerJob.initAction = delegate
{ {
defaultCompleteMode = ToilCompleteMode.Instant,
var dri = Partner.jobs.curDriver as JobDriver_SexBaseRecieverRaped; socialMode = RandomSocialMode.Off,
if (dri == null) initAction = delegate
{ {
Job gettin_loved = JobMaker.MakeJob(VariousDefOf.GettinGangbang, pawn, Bed); if (!(Partner.jobs.curDriver is JobDriver_SexBaseRecieverRaped))
{
Job gettin_loved = JobMaker.MakeJob(RsiDefOf.Job.GettinGangbang, pawn, Bed);
Partner.jobs.StartJob(gettin_loved, JobCondition.InterruptForced); Partner.jobs.StartJob(gettin_loved, JobCondition.InterruptForced);
} }
}
}; };
yield return StartPartnerJob; yield return StartPartnerJob;
Toil SexToil = new Toil(); Toil SexToil = new Toil
SexToil.defaultCompleteMode = ToilCompleteMode.Never; {
SexToil.defaultDuration = duration; defaultCompleteMode = ToilCompleteMode.Never,
SexToil.handlingFacing = true; defaultDuration = duration,
SexToil.FailOn(() => Partner.CurJob.def != VariousDefOf.GettinGangbang); handlingFacing = true
};
SexToil.FailOn(() => Partner.CurJob.def != RsiDefOf.Job.GettinGangbang);
SexToil.initAction = delegate SexToil.initAction = delegate
{ {
Start(); Start();
@ -114,22 +109,24 @@ namespace RJWSexperience.Ideology
setup_ticks(); setup_ticks();
parteners.Add(Partner);// add job starter, so this wont fail, before Initiator starts his job parteners.Add(Partner);// add job starter, so this wont fail, before Initiator starts his job
Toil get_banged = new Toil(); Toil get_banged = new Toil
get_banged.defaultCompleteMode = ToilCompleteMode.Never; {
get_banged.handlingFacing = true; defaultCompleteMode = ToilCompleteMode.Never,
get_banged.initAction = delegate handlingFacing = true,
initAction = delegate
{ {
pawn.pather.StopDead(); pawn.pather.StopDead();
pawn.jobs.curDriver.asleep = false; pawn.jobs.curDriver.asleep = false;
}; },
get_banged.tickAction = delegate tickAction = delegate
{ {
if ((parteners.Count > 0) && pawn.IsHashIntervalTick(ticks_between_hearts / parteners.Count) && pawn.IsHashIntervalTick(ticks_between_hearts)) if ((parteners.Count > 0) && pawn.IsHashIntervalTick(ticks_between_hearts / parteners.Count) && pawn.IsHashIntervalTick(ticks_between_hearts))
ThrowMetaIconF(pawn.Position, pawn.Map, FleckDefOf.Heart); ThrowMetaIconF(pawn.Position, pawn.Map, FleckDefOf.Heart);
}
}; };
get_banged.AddEndCondition(new Func<JobCondition>(() => get_banged.AddEndCondition(new Func<JobCondition>(() =>
{ {
if (parteners.Count <= 0) if (parteners.Count == 0)
{ {
return JobCondition.Succeeded; return JobCondition.Succeeded;
} }
@ -148,12 +145,12 @@ namespace RJWSexperience.Ideology
Partner.jobs.jobQueue.EnqueueFirst(tobed); Partner.jobs.jobQueue.EnqueueFirst(tobed);
} }
else if (pawn.HostileTo(Partner)) else if (pawn.HostileTo(Partner))
{
pawn.health.AddHediff(xxx.submitting); pawn.health.AddHediff(xxx.submitting);
}
}); });
get_banged.socialMode = RandomSocialMode.Off; get_banged.socialMode = RandomSocialMode.Off;
yield return get_banged; yield return get_banged;
} }
} }
} }

View file

@ -1,14 +1,8 @@
using System; using RimWorld;
using rjw;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse; using Verse;
using Verse.AI; using Verse.AI;
using Verse.AI.Group;
using RimWorld;
using rjw;
namespace RJWSexperience.Ideology namespace RJWSexperience.Ideology
{ {
@ -16,17 +10,14 @@ namespace RJWSexperience.Ideology
{ {
protected override Job TryGiveJob(Pawn pawn) protected override Job TryGiveJob(Pawn pawn)
{ {
if (pawn.Drafted) return null; if (pawn.Drafted || pawn.mindState == null)
DutyDef dutyDef = null;
PawnDuty duty = null;
if (pawn.mindState != null)
{ {
duty = pawn.mindState.duty; return null;
dutyDef = duty.def;
} }
else return null;
if (dutyDef == DutyDefOf.TravelOrLeave || !xxx.can_do_loving(pawn)) PawnDuty duty = pawn.mindState.duty;
if (duty.def == DutyDefOf.TravelOrLeave || !xxx.can_do_loving(pawn))
{ {
return null; return null;
} }
@ -35,11 +26,10 @@ namespace RJWSexperience.Ideology
if (!pawn.CanReach(target, PathEndMode.ClosestTouch, Danger.None)) return null; if (!pawn.CanReach(target, PathEndMode.ClosestTouch, Danger.None)) return null;
return JobMaker.MakeJob(VariousDefOf.RapeVictim, target); return JobMaker.MakeJob(RsiDefOf.Job.RapeVictim, target);
} }
} }
/// <summary> /// <summary>
/// copied from rjw /// copied from rjw
/// </summary> /// </summary>
@ -64,25 +54,28 @@ namespace RJWSexperience.Ideology
SexUtility.RapeTargetAlert(pawn, Partner); SexUtility.RapeTargetAlert(pawn, Partner);
Toil StartPartnerJob = new Toil(); Toil StartPartnerJob = new Toil
StartPartnerJob.defaultCompleteMode = ToilCompleteMode.Instant;
StartPartnerJob.socialMode = RandomSocialMode.Off;
StartPartnerJob.initAction = delegate
{ {
var dri = Partner.jobs.curDriver as JobDriver_SexBaseRecieverRaped; defaultCompleteMode = ToilCompleteMode.Instant,
if (dri == null) socialMode = RandomSocialMode.Off,
initAction = delegate
{
if (!(Partner.jobs.curDriver is JobDriver_SexBaseRecieverRaped))
{ {
Job gettin_raped = JobMaker.MakeJob(PartnerJob, pawn); Job gettin_raped = JobMaker.MakeJob(PartnerJob, pawn);
Partner.jobs.StartJob(gettin_raped, JobCondition.InterruptForced, null, false, true, null); Partner.jobs.StartJob(gettin_raped, JobCondition.InterruptForced, null, false, true, null);
} }
}
}; };
yield return StartPartnerJob; yield return StartPartnerJob;
Toil SexToil = new Toil(); Toil SexToil = new Toil
SexToil.defaultCompleteMode = ToilCompleteMode.Never; {
SexToil.defaultDuration = duration; defaultCompleteMode = ToilCompleteMode.Never,
SexToil.handlingFacing = true; defaultDuration = duration,
handlingFacing = true
};
SexToil.FailOn(() => Partner.CurJob.def != PartnerJob); SexToil.FailOn(() => Partner.CurJob.def != PartnerJob);
SexToil.initAction = delegate SexToil.initAction = delegate
{ {

View file

@ -1,12 +1,6 @@
using System; using RimWorld;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse; using Verse;
using Verse.AI;
using RimWorld;
namespace RJWSexperience.Ideology namespace RJWSexperience.Ideology
{ {
@ -14,7 +8,7 @@ namespace RJWSexperience.Ideology
{ {
public LordJob_Ritual_Gangbang() { } public LordJob_Ritual_Gangbang() { }
public LordJob_Ritual_Gangbang(string targetID ,TargetInfo selectedTarget, Precept_Ritual ritual, RitualObligation obligation, List<RitualStage> allStages, RitualRoleAssignments assignments, Pawn organizer = null) : base(selectedTarget, ritual, obligation, allStages, assignments, organizer) public LordJob_Ritual_Gangbang(string targetID, TargetInfo selectedTarget, Precept_Ritual ritual, RitualObligation obligation, List<RitualStage> allStages, RitualRoleAssignments assignments, Pawn organizer = null) : base(selectedTarget, ritual, obligation, allStages, assignments, organizer)
{ {
foreach (RitualRole ritualRole in assignments.AllRolesForReading) foreach (RitualRole ritualRole in assignments.AllRolesForReading)
{ {
@ -25,6 +19,5 @@ namespace RJWSexperience.Ideology
} }
} }
} }
} }
} }

View file

@ -1,6 +1,6 @@
using RimWorld; using RimWorld;
using Verse;
using rjw; using rjw;
using Verse;
namespace RJWSexperience.Ideology namespace RJWSexperience.Ideology
{ {
@ -42,7 +42,6 @@ namespace RJWSexperience.Ideology
public override bool AppliesToPawn(Pawn p, out string reason, TargetInfo selectedTarget, LordJob_Ritual ritual = null, RitualRoleAssignments assignments = null, Precept_Ritual precept = null, bool skipReason = false) public override bool AppliesToPawn(Pawn p, out string reason, TargetInfo selectedTarget, LordJob_Ritual ritual = null, RitualRoleAssignments assignments = null, Precept_Ritual precept = null, bool skipReason = false)
{ {
reason = null; reason = null;
if (!xxx.is_human(p)) if (!xxx.is_human(p))
{ {
@ -57,11 +56,7 @@ namespace RJWSexperience.Ideology
return false; return false;
} }
public static bool CanBeBreedee(Pawn pawn) public static bool CanBeBreedee(Pawn pawn) => xxx.can_be_fucked(pawn);
{
if (xxx.can_be_fucked(pawn)) return true;
return false;
}
} }
public class RitualRole_AnimalBreeder : RitualRole public class RitualRole_AnimalBreeder : RitualRole
@ -92,15 +87,15 @@ namespace RJWSexperience.Ideology
public static bool CanBeBreeder(Pawn animal, Precept_Ritual precept) public static bool CanBeBreeder(Pawn animal, Precept_Ritual precept)
{ {
if (precept != null && precept.ideo.HasPrecept(VariousDefOf.Bestiality_OnlyVenerated) && !precept.ideo.IsVeneratedAnimal(animal)) if (precept != null && precept.ideo.HasPrecept(RsiDefOf.Precept.Bestiality_OnlyVenerated) && !precept.ideo.IsVeneratedAnimal(animal))
{
return false;
}
if (!xxx.can_rape(animal))
{ {
return false; return false;
} }
if (!xxx.can_rape(animal)) return false;
return true; return true;
} }
} }
} }

View file

@ -0,0 +1,89 @@
using RimWorld;
using RJWSexperience.Ideology.Precepts;
using System.Collections.Generic;
using System.Linq;
using Verse;
namespace RJWSexperience.Ideology
{
public static class RomanceChanceFactorHelpers
{
/// <summary>
/// Default value for parent relation
/// </summary>
private const float parentRomanceChanceFactor = 0.03f;
/// <summary>
/// Get ideology adjusted romanceChanceFactor
/// </summary>
public static float GetRomanceChanceFactor(Pawn pawn, Pawn partner)
{
float romanceChanceFactor = 1f;
if (!pawn.relations.FamilyByBlood.Contains(partner))
{
if (pawn.Ideo?.HasPrecept(RsiDefOf.Precept.Incestuos_IncestOnly) == true)
{
return parentRomanceChanceFactor;
}
else
{
return romanceChanceFactor;
}
}
PreceptDef incestuousPrecept = pawn.Ideo?.PreceptsListForReading.Select(precept => precept.def).FirstOrFallback(def => def.issue == RsiDefOf.Issue.Incestuos);
IEnumerable<PawnRelationDef> relations = pawn.GetRelations(partner).Where(def => def.familyByBloodRelation);
foreach (PawnRelationDef relationDef in relations)
{
romanceChanceFactor *= GetRomanceChanceFactor(relationDef, incestuousPrecept);
}
return romanceChanceFactor;
}
/// <summary>
/// Get ideology adjusted romanceChanceFactor for the relation
/// </summary>
public static float GetRomanceChanceFactor(PawnRelationDef relationDef, PreceptDef incestuousPrecept)
{
if (incestuousPrecept == null)
{
return relationDef.romanceChanceFactor;
}
var incestDefExt = incestuousPrecept.GetModExtension<DefExtension_Incest>();
if (incestDefExt == null)
{
return relationDef.romanceChanceFactor;
}
BloodRelationDegree relationDegree = RelationHelpers.GetBloodRelationDegree(relationDef);
if (incestDefExt.TryGetRomanceChanceFactor(relationDegree, out var romanceChanceOverride))
{
return romanceChanceOverride;
}
return relationDef.romanceChanceFactor;
}
[DebugAction("RJW Sexperience Ideology", "Show romanceChanceFactors", false, true, actionType = DebugActionType.Action, allowedGameStates = AllowedGameStates.Entry)]
public static void DisplayDebugTable()
{
IEnumerable<PreceptDef> incestuousPrecepts = DefDatabase<PreceptDef>
.AllDefsListForReading
.Where(def => def.issue == RsiDefOf.Issue.Incestuos);
IEnumerable<TableDataGetter<PawnRelationDef>> preceptGetters = incestuousPrecepts
.Select(precept => new TableDataGetter<PawnRelationDef>(precept.defName,(PawnRelationDef rel) => GetRomanceChanceFactor(rel, precept)));
var relName = new TableDataGetter<PawnRelationDef>("Relation Def", (PawnRelationDef rel) => rel.defName);
TableDataGetter<PawnRelationDef>[] getters = (new List<TableDataGetter<PawnRelationDef>>() { relName }).Concat(preceptGetters).ToArray();
DebugTables.MakeTablesDialog(DefDatabase<PawnRelationDef>.AllDefsListForReading, getters);
}
}
}

View file

@ -0,0 +1,65 @@
using RimWorld;
using Verse;
namespace RJWSexperience.Ideology
{
public static class RsiDefOf
{
[DefOf]
public static class Job
{
public static readonly JobDef RapeVictim;
public static readonly JobDef Gangbang;
public static readonly JobDef GettinGangbang;
public static readonly JobDef DrugSex;
public static readonly JobDef GettinDrugSex;
public static readonly JobDef DrugMasturbate;
}
[DefOf]
public static class Meme
{
public static readonly MemeDef Zoophile;
public static readonly MemeDef Rapist;
public static readonly MemeDef Necrophile;
}
[DefOf]
public static class Issue
{
public static readonly IssueDef Incestuos;
}
[DefOf]
public static class Precept
{
public static readonly PreceptDef Incestuos_IncestOnly;
public static readonly PreceptDef Bestiality_OnlyVenerated;
public static readonly PreceptDef BabyFaction_AlwaysFather;
public static readonly PreceptDef BabyFaction_AlwaysColony;
public static readonly PreceptDef Submissive_Male;
public static readonly PreceptDef Submissive_Female;
public static readonly PreceptDef ProselyzingByOrgasm;
}
[DefOf]
public static class HistoryEvent
{
public static readonly HistoryEventDef RSI_SexWithAnimal;
public static readonly HistoryEventDef RSI_Raped;
public static readonly HistoryEventDef RSI_NonIncestuosMarriage;
public static readonly HistoryEventDef RSI_NonIncestuosSex;
public static readonly HistoryEventDef RSI_SexWithCorpse;
public static readonly HistoryEventDef RSI_VirginTaken;
public static readonly HistoryEventDef RSI_VirginStolen;
public static readonly HistoryEventDef RSI_TookVirgin;
public static readonly HistoryEventDef RSI_Masturbated;
}
[DefOf]
public static class Hediff
{
[MayRequireBiotech] public static readonly HediffDef PregnantHuman;
}
}
}

View file

@ -1,18 +0,0 @@
using RimWorld;
namespace RJWSexperience.Ideology
{
[DefOf]
public static class RsiHistoryEventDefOf
{
[MayRequireIdeology] public static readonly HistoryEventDef RSI_SexWithAnimal;
[MayRequireIdeology] public static readonly HistoryEventDef RSI_Raped;
[MayRequireIdeology] public static readonly HistoryEventDef RSI_NonIncestuosMarriage;
[MayRequireIdeology] public static readonly HistoryEventDef RSI_NonIncestuosSex;
[MayRequireIdeology] public static readonly HistoryEventDef RSI_SexWithCorpse;
[MayRequireIdeology] public static readonly HistoryEventDef RSI_VirginTaken;
[MayRequireIdeology] public static readonly HistoryEventDef RSI_VirginStolen;
[MayRequireIdeology] public static readonly HistoryEventDef RSI_TookVirgin;
[MayRequireIdeology] public static readonly HistoryEventDef RSI_Masturbated;
}
}

View file

@ -0,0 +1,26 @@
using UnityEngine;
using Verse;
namespace RJWSexperience.Ideology
{
public class RsiMod : Mod
{
public static RsiSettings Prefs { get; private set; }
public RsiMod(ModContentPack content) : base(content)
{
Prefs = GetSettings<RsiSettings>();
}
public override string SettingsCategory() => Keyed.ModTitle;
public override void DoSettingsWindowContents(Rect inRect)
{
Listing_Standard listmain = new Listing_Standard();
listmain.Begin(inRect);
listmain.CheckboxLabeled(Keyed.PatchRomanceChanceFactor, ref Prefs.patchRomanceChanceFactor, Keyed.PatchRomanceChanceFactorTip);
listmain.CheckboxLabeled(Keyed.PatchIncestuousManualRomance, ref Prefs.patchIncestuousManualRomance, Keyed.PatchIncestuousManualRomanceTip);
listmain.End();
}
}
}

View file

@ -0,0 +1,17 @@
using Verse;
namespace RJWSexperience.Ideology
{
public class RsiSettings : ModSettings
{
public bool patchRomanceChanceFactor;
public bool patchIncestuousManualRomance;
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look(ref patchRomanceChanceFactor, "patchSecondaryRomanceChanceFactor", true);
Scribe_Values.Look(ref patchIncestuousManualRomance, "patchIncestuousManualRomance", true);
}
}
}

View file

@ -1,30 +0,0 @@
using rjw;
using System.Diagnostics.CodeAnalysis;
using Verse;
namespace RJWSexperience.Ideology
{
public class TwoPawnFilter
{
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public SinglePawnFilter doer;
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public SinglePawnFilter partner;
[SuppressMessage("Minor Code Smell", "S1104:Fields should not have public accessibility", Justification = "Field value loaded from XML")]
public RelationFilter relations;
public bool Applies(Pawn pawn, Pawn partner)
{
if (doer?.Applies(pawn) == false)
return false;
if (this.partner?.Applies(partner) == false)
return false;
if (relations?.Applies(pawn, partner) == false)
return false;
return true;
}
}
}

View file

@ -1,27 +0,0 @@
using RimWorld;
using Verse;
namespace RJWSexperience.Ideology
{
[DefOf]
public static class VariousDefOf
{
public static readonly JobDef RapeVictim;
public static readonly JobDef Gangbang;
public static readonly JobDef GettinGangbang;
public static readonly JobDef DrugSex;
public static readonly JobDef GettinDrugSex;
public static readonly JobDef DrugMasturbate;
[MayRequireIdeology] public static readonly MemeDef Zoophile;
[MayRequireIdeology] public static readonly MemeDef Rapist;
[MayRequireIdeology] public static readonly MemeDef Necrophile;
[MayRequireIdeology] public static readonly PreceptDef Bestiality_OnlyVenerated;
[MayRequireIdeology] public static readonly PreceptDef BabyFaction_AlwaysFather;
[MayRequireIdeology] public static readonly PreceptDef BabyFaction_AlwaysColony;
[MayRequireIdeology] public static readonly PreceptDef Submissive_Male;
[MayRequireIdeology] public static readonly PreceptDef Submissive_Female;
[MayRequireIdeology] public static readonly PreceptDef ProselyzingByOrgasm;
[MayRequireBiotech] public static readonly HediffDef PregnantHuman;
}
}