Initial commit

This commit is contained in:
AbstractConcept 2022-11-02 00:56:22 -05:00
parent fe7c28ad8e
commit 55402b9891
54 changed files with 2515 additions and 92 deletions

Binary file not shown.

Binary file not shown.

32
About/About.xml Normal file
View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<ModMetaData>
<name>Privacy, Please!</name>
<author>AbstractConcept</author>
<supportedVersions>
<li>1.4</li>
</supportedVersions>
<packageId>abscon.privacy.please</packageId>
<modDependencies>
<li>
<packageId>brrainz.harmony</packageId>
<displayName>Harmony</displayName>
<steamWorkshopUrl>steam://url/CommunityFilePage/2009463077</steamWorkshopUrl>
<downloadUrl>https://github.com/pardeike/HarmonyRimWorld/releases/latest</downloadUrl>
</li>
<li>
<packageId>rim.job.world</packageId>
<displayName>RimJobWorld</displayName>
<downloadUrl>https://www.loverslab.com/topic/110270-mod-rimjobworld/</downloadUrl>
</li>
</modDependencies>
<loadAfter>
<li>UnlimitedHugs.HugsLib</li>
<li>brrainz.harmony</li>
<li>rim.job.world</li>
</loadAfter>
<description>
</description>
</ModMetaData>

View File

@ -0,0 +1,35 @@
Privacy, Please!
This mod adds a greater awareness of sex to people. When people witness (or are witnessed taking part in) various sexual activities, those involved will exhibit different reactions depending on their traits and ideologies. Sexperience - Ideology is highly recommended in order to help customise your colonists' opinions on different sexual activities.
Sex acts that can provoke reactions include:
- Consensual sex: Encountering two lovin' individuals will generally result in the embarrassment of all involved and the couplating couple immediately ceasing their activities (unless the couple are both Exhibitionists)
- Masturbation: Finding some masturbating will likely embarrass both parties and the discovered individual immediately stopping what they were doing (unless they happen to be an Exhibitionist). Reactions to masturbation can be modified through the Masturbation precept (included in Sexperience - Ideology)
- Cheating: Discovering a partner cheating will greatly upset most people (unless they happen to be a Culkold). Reactions to cheating can be modified through the Lovin' precept ('free and approved' lovin' will nullify discontent from cheating).
- Bestiality: Witnessing bestiality will generally cause individuals to Panic (unless they are a Zoophile). Reactions to bestiality can be modified through the Bestiality precept (included in Sexperience - Ideology)
- Rape: Witnessing rape will generally cause individuals to Panic (unless they are a Rapist). Reactions to rape can be modified through the Rape precept (included in Sexperience - Ideology).
- Necrophilia: Witnessing necrophilia will generally cause individuals to become Nauseated (unless they are a Necrophile). Reactions to necrophilia can be modified through the Necrophilia precept (included in Sexperience - Ideology).
- Xenophilia: Stumbing upon humanoids of different species lovin' will generally be treated like encountering any other lovein' couple (unless the witness happens Xenophobe, who will likely Harrass the poor couple). Reactions to xenophilia can be modified through the Alien Dating precept (included in Humanoid Alien Races).
As hinted above, some individuals will be unable to ignore what they just witnessed, resulting in the following reactions:
- Panic: the witness will likely run away and hide, though more aggressive types may start a social fight with the transgressor.
- Nauseated: the witness will run away and likely vomit after what they just saw.
- Harass: the witness will start insulting the transgressor, though this might escalate to violence.
Options have been included to toggle whether people should react to these various sex acts and whether people will turn a blind eye to them during rituals and parties. Additional options have been included to toggle whether prisoners, slaves, and members of other factions should react to witnessed sexual activities.
This mod also provides improved threesome support. Threesomes can now be triggered via two new ways:
- When a pawn sets off to bed their partner a passer-by might be invited to accompany them.
- If a pawn encounters a couple having sex then they may just might be invited to join in.
The chance of a threesome occurring can be configured in the mod options. In all cases, however, those involved must have a good opinion of each other and the passer-by mustn't be doing an player ordered or important job at the time.
Two new RJW quirks are also included - Cuckold and Voyeur. Cuckolds get a thrill witnessing their partners cheated on them, while Voyeurs just like to watch others in general (providing what they're seeing isn't too upset, of course).
Misc features
- Those using S16's apparel mod or the UnderWhere mod can make use of an inculded setting that will allow you toggle whether wearing underwear alone is sufficient to satisfy an ideological need for modesty. You may want to turn this setting off if you want ideologies to be stricter about what they consider to be modest. Ideologies which prefer to wear fewer clothes than normal are not affected by this setting.
- The scantier underwear from these mods now only covers either the chest or groin. Wearing underwear will counts as covering private parts for the purposes of determining nudity if not running Ideology.
- New situational mood: Exposed underwear. Non-Exhibitionists will be upset if they are not wearing enough clothing to cover up their underwear. This mood can be toggled on or off.
- Any lewd fluids that people produce will not be marked for cleaning until they are done with what they are doing.

5
About/Manifest.xml Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Manifest>
<version>1.0.0</version>
<downloadUri>https://gitgud.io/AbstractConcept/rimworld-animations-patch</downloadUri>
</Manifest>

15
Defs/FleckDefs.xml Normal file
View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<FleckDef ParentName="FleckBase_Thrown">
<defName>Eye</defName>
<graphicData>
<texPath>UI/Flecks/Eye</texPath>
</graphicData>
<altitudeLayer>MetaOverlays</altitudeLayer>
<fadeInTime>0.08</fadeInTime>
<solidTime>1.4</solidTime>
<fadeOutTime>1.5</fadeOutTime>
</FleckDef>
</Defs>

53
Defs/HediffDefs.xml Normal file
View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<HediffDef>
<defName>Disquiet</defName>
<label>disquiet</label>
<description>This person saw something that upset them and it's weighting on their thoughts.</description>
<stages>
<li>
<label>present</label>
<becomeVisible>false</becomeVisible>
</li>
</stages>
</HediffDef>
<HediffDef>
<defName>Panicked</defName>
<label>panicked</label>
<description>This person saw something that has shaked them to their core. Will they run or fight?</description>
<stages>
<li>
<label>present</label>
<becomeVisible>false</becomeVisible>
</li>
</stages>
</HediffDef>
<HediffDef>
<defName>Nauseated</defName>
<label>nauseated</label>
<description>This poor soul saw something something so utterly foul that they just might be sick from the thought.</description>
<stages>
<li>
<label>present</label>
<becomeVisible>false</becomeVisible>
</li>
</stages>
</HediffDef>
<HediffDef>
<defName>Indignant</defName>
<label>indignant</label>
<description>This person witnessed something quite distasteful and is going to give the offender a piece of their mind.</description>
<stages>
<li>
<label>present</label>
<becomeVisible>false</becomeVisible>
</li>
</stages>
</HediffDef>
</Defs>

19
Defs/JobDefs.xml Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<JobDef>
<defName>JoinInSex</defName>
<driverClass>Privacy_Please.JobDriver_JoinInSex</driverClass>
<reportString>joining in on some fun.</reportString>
<casualInterruptible>false</casualInterruptible>
</JobDef>
<JobDef>
<defName>WatchSex</defName>
<driverClass>Privacy_Please.JobDriver_WatchSex</driverClass>
<reportString>watching from afar.</reportString>
<casualInterruptible>false</casualInterruptible>
</JobDef>
</Defs>

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<!-- Issues -->
<IssueDef>
<defName>Exhibitionism</defName>
<label>exhibitionism</label>
<iconPath>UI/Issues/Exhibitionism</iconPath>
</IssueDef>
<!-- Precepts -->
<PreceptDef>
<defName>Exhibitionism_Forbidden</defName>
<issue>Exhibitionism</issue>
<label>forbidden</label>
<description>Physical intimacy in the presence of others is a wicked thing.</description>
<impact>High</impact>
<displayOrderInIssue>50</displayOrderInIssue>
<displayOrderInImpact>1000</displayOrderInImpact>
<defaultSelectionWeight>100</defaultSelectionWeight>
</PreceptDef>
<PreceptDef>
<defName>Exhibitionism_Disapproved</defName>
<issue>Exhibitionism</issue>
<label>disapproved</label>
<description>Performing sexual acts in front of others is shameful.</description>
<impact>Low</impact>
<displayOrderInIssue>40</displayOrderInIssue>
<displayOrderInImpact>1000</displayOrderInImpact>
<defaultSelectionWeight>100</defaultSelectionWeight>
</PreceptDef>
<PreceptDef>
<defName>Exhibitionism_Acceptable</defName>
<issue>Exhibitionism</issue>
<label>acceptable</label>
<description>Sex a normal and natural event and should attract no special attention from others.</description>
<impact>Low</impact>
<displayOrderInIssue>30</displayOrderInIssue>
<displayOrderInImpact>1000</displayOrderInImpact>
<defaultSelectionWeight>100</defaultSelectionWeight>
</PreceptDef>
<PreceptDef>
<defName>Exhibitionism_Approved</defName>
<issue>Exhibitionism</issue>
<label>approved</label>
<description>Sex is to be celebrated and people should be encouraged to witness it.</description>
<impact>Medium</impact>
<displayOrderInIssue>20</displayOrderInIssue>
<displayOrderInImpact>1000</displayOrderInImpact>
<defaultSelectionWeight>100</defaultSelectionWeight>
</PreceptDef>
</Defs>

View File

@ -0,0 +1,212 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThoughtDef>
<defName>SeenMasturbating</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>1.0</durationDays>
<stackLimit>3</stackLimit>
<stackedEffectMultiplier>0.5</stackedEffectMultiplier>
<stages>
<li>
<label>was caught masturbatin'</label>
<description>I'm so embarrassed!</description>
<baseMoodEffect>-12</baseMoodEffect>
</li>
</stages>
<nullifyingPrecepts>
<li>Exhibitionism_Acceptable</li>
<li>Exhibitionism_Approved</li>
</nullifyingPrecepts>
</ThoughtDef>
<ThoughtDef>
<defName>SeenHavingSex</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>1.0</durationDays>
<stackLimit>3</stackLimit>
<stackedEffectMultiplier>0.5</stackedEffectMultiplier>
<stages>
<li>
<label>was caught lovin'</label>
<description>Well, that was awkward!</description>
<baseMoodEffect>-8</baseMoodEffect>
</li>
</stages>
<nullifyingPrecepts>
<li>Exhibitionism_Acceptable</li>
<li>Exhibitionism_Approved</li>
</nullifyingPrecepts>
</ThoughtDef>
<ThoughtDef>
<defName>SeenMasturbatingExhibitionist</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>1.0</durationDays>
<stackLimit>1</stackLimit>
<stages>
<li>
<label>exhibitionist caught masturbatin'</label>
<description>It's OK, come and have a closer look...</description>
<baseMoodEffect>4</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SeenHavingSexExhibitionist</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>1.0</durationDays>
<stackLimit>1</stackLimit>
<stages>
<li>
<label>exhibitionist caught lovin'</label>
<description>Heheh, hope they enjoyed the show!</description>
<baseMoodEffect>6</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawMasturbation</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>1.0</durationDays>
<stackLimit>1</stackLimit>
<stackedEffectMultiplier>0.5</stackedEffectMultiplier>
<stages>
<li>
<label>saw someone masturbatin'</label>
<description>Argh! I'm so sorry!</description>
<baseMoodEffect>-6</baseMoodEffect>
</li>
</stages>
<nullifyingPrecepts>
<li>Exhibitionism_Acceptable</li>
<li>Exhibitionism_Approved</li>
</nullifyingPrecepts>
</ThoughtDef>
<ThoughtDef>
<defName>SawSex</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>1.0</durationDays>
<stackLimit>1</stackLimit>
<stackedEffectMultiplier>0.5</stackedEffectMultiplier>
<stages>
<li>
<label>saw someone lovin'</label>
<description>Jeez! Get a room!</description>
<baseMoodEffect>-4</baseMoodEffect>
</li>
</stages>
<nullifyingPrecepts>
<li>Exhibitionism_Acceptable</li>
<li>Exhibitionism_Approved</li>
</nullifyingPrecepts>
</ThoughtDef>
<ThoughtDef>
<defName>SawMasturbationVoyeur</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>1.0</durationDays>
<stackLimit>1</stackLimit>
<stages>
<li>
<label>voyeur saw some masturbatin'</label>
<description>I think that awoke something in me...</description>
<baseMoodEffect>4</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawSexVoyeur</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>1.0</durationDays>
<stackLimit>1</stackLimit>
<stages>
<li>
<label>voyeur saw some lovin'</label>
<description>Damn. So hot!</description>
<baseMoodEffect>6</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>CaughtCheating</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>10.0</durationDays>
<stackLimit>300</stackLimit>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>caught cheating by {0}</label>
<description>What have I done? {1}, please forgive me...</description>
<baseMoodEffect>-10</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SeenCommittingTaboo</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>2.0</durationDays>
<stackLimit>1</stackLimit>
<stackedEffectMultiplier>0.5</stackedEffectMultiplier>
<stages>
<li>
<label>caught committing a taboo</label>
<description>I'm so ashamed.</description>
<baseMoodEffect>-15</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SeenCommittingMajorTaboo</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>3.0</durationDays>
<stackLimit>1</stackLimit>
<stackedEffectMultiplier>0.5</stackedEffectMultiplier>
<stages>
<li>
<label>caught committing a major taboo</label>
<description>How can I face the world after this?</description>
<baseMoodEffect>-20</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawTaboo</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>2.0</durationDays>
<stackLimit>1</stackLimit>
<stackedEffectMultiplier>0.5</stackedEffectMultiplier>
<stages>
<li>
<label>witnessed a taboo</label>
<description>What vile degeneracy!</description>
<baseMoodEffect>-10</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawMajorTaboo</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>3.0</durationDays>
<stackLimit>1</stackLimit>
<stackedEffectMultiplier>0.5</stackedEffectMultiplier>
<stages>
<li>
<label>witnessed a major taboo</label>
<description>Disgusting vermin! You'll get yours!</description>
<baseMoodEffect>-15</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
</Defs>

View File

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThoughtDef>
<defName>SawBestiality_Abhorrent</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<nullifyingTraits>
<li>Zoophile</li>
</nullifyingTraits>
<hediff>Panicked</hediff>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>horrified by bestiality</label>
<description>How could that violate that poor animal like that?!</description>
<baseMoodEffect>-20</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawBestiality_Horrible</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<nullifyingTraits>
<li>Zoophile</li>
</nullifyingTraits>
<hediff>Disquiet</hediff>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>disturbed by bestiality</label>
<description>Get away from that poor creature!</description>
<baseMoodEffect>-15</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawBestiality_Disapproved</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<nullifyingTraits>
<li>Zoophile</li>
</nullifyingTraits>
<hediff>Disquiet</hediff>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>witnessed bestiality</label>
<description>Ew. Just. Ew.</description>
<baseMoodEffect>-10</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawBestiality_Acceptable</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<nullifyingTraits>
<li>Zoophile</li>
</nullifyingTraits>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>saw bestiality</label>
<description>Um, does your 'friend' want some kibble?</description>
<baseMoodEffect>-4</baseMoodEffect>
</li>
</stages>
<nullifyingPrecepts>
<li>Exhibitionism_Acceptable</li>
<li>Exhibitionism_Approved</li>
</nullifyingPrecepts>
</ThoughtDef>
<ThoughtDef>
<defName>SawBestiality_Honorable</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>observed bestiality</label>
<description>The bond between us and our animals is strong.</description>
<baseMoodEffect>+2</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
</Defs>

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<!--<ThoughtDef>
<defName>SawHAR_AlienDating_Prohibited</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<hediff>Indignant</hediff>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>horrified by xenophilia</label>
<description>Filthy degenerates!</description>
<baseMoodEffect>-15</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawHAR_AlienDating_Horrible</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<hediff>Disquiet</hediff>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>disturbed by xenophilia</label>
<description>Oh! That's not right...</description>
<baseMoodEffect>-10</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawHAR_AlienDating_Acceptable</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>saw xenophilia</label>
<description>Oops, sorry about walking in on you!</description>
<baseMoodEffect>-4</baseMoodEffect>
</li>
</stages>
<nullifyingPrecepts>
<li>Exhibitionism_Acceptable</li>
<li>Exhibitionism_Approved</li>
<nullifyingPrecepts>
</ThoughtDef>
<ThoughtDef>
<defName>SawHAR_AlienDating_Preferred</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>noticed xenophilia</label>
<description>I wonder what their kids would look like?</description>
<baseMoodEffect>+1</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawHAR_AlienDating_Know_Honorable</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>observed xenophilia</label>
<description>A blending of species will make us stronger.</description>
<baseMoodEffect>+2</baseMoodEffect>
</li>
</stages>
</ThoughtDef>-->
</Defs>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThoughtDef>
<defName>SawMasturbation_Abhorrent</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<hediff>Indignant</hediff>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>disgusted by masturbatin'</label>
<description>You'll go blind you know!</description>
<baseMoodEffect>-15</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawMasturbation_Disapproved</defName>
<thoughtClass>Thought_Memory</thoughtClass>
<durationDays>1.0</durationDays>
<stackLimit>1</stackLimit>
<stackedEffectMultiplier>0.5</stackedEffectMultiplier>
<stages>
<li>
<label>saw someone masturbatin'</label>
<description>Argh! I'm so sorry!</description>
<baseMoodEffect>-5</baseMoodEffect>
</li>
</stages>
<nullifyingPrecepts>
<li>Exhibitionism_Acceptable</li>
<li>Exhibitionism_Approved</li>
</nullifyingPrecepts>
</ThoughtDef>
</Defs>

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThoughtDef>
<defName>SawNecrophilia_Abhorrent</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<nullifyingTraits>
<li>Necrophiliac</li>
</nullifyingTraits>
<hediff>Nauseated</hediff>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>horrified by necrophilia</label>
<description>*Urp* I'm gunna hurl!</description>
<baseMoodEffect>-20</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawNecrophilia_Horrible</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<nullifyingTraits>
<li>Necrophiliac</li>
</nullifyingTraits>
<hediff>Disquiet</hediff>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>disturbed by necrophilia</label>
<description>What were they thinking?!</description>
<baseMoodEffect>-15</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawNecrophilia_Disapproved</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<nullifyingTraits>
<li>Necrophiliac</li>
</nullifyingTraits>
<hediff>Disquiet</hediff>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>witnessed necrophilia</label>
<description>Even the dead get no rest here.</description>
<baseMoodEffect>-10</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawNecrophilia_Acceptable</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>saw necrophilia</label>
<description>I just hope they bury it when they're done.</description>
<baseMoodEffect>-4</baseMoodEffect>
</li>
</stages>
<nullifyingPrecepts>
<li>Exhibitionism_Acceptable</li>
<li>Exhibitionism_Approved</li>
</nullifyingPrecepts>
</ThoughtDef>
<ThoughtDef>
<defName>SawNecrophilia_Honorable</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>observed necrophilia</label>
<description>Passion transcends the grave.</description>
<baseMoodEffect>+2</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
</Defs>

View File

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThoughtDef>
<defName>SawRape_Abhorrent</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<nullifyingTraits>
<li>Rapist</li>
</nullifyingTraits>
<hediff>Panicked</hediff>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>horrified by rape</label>
<description>Someone please help that poor soul!</description>
<baseMoodEffect>-20</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawRape_Horrible</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<nullifyingTraits>
<li>Rapist</li>
</nullifyingTraits>
<hediff>Disquiet</hediff>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>disturbed by rape</label>
<description>I feel all shaky.</description>
<baseMoodEffect>-15</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawRape_Disapproved</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<nullifyingTraits>
<li>Rapist</li>
</nullifyingTraits>
<hediff>Disquiet</hediff>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>witnessed rape</label>
<description>Is this what life is going to be here?</description>
<baseMoodEffect>-10</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawRape_Acceptable</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>saw rape</label>
<description>Ah. Um, carry on...</description>
<baseMoodEffect>-4</baseMoodEffect>
</li>
</stages>
<nullifyingPrecepts>
<li>Exhibitionism_Acceptable</li>
<li>Exhibitionism_Approved</li>
</nullifyingPrecepts>
</ThoughtDef>
<ThoughtDef>
<defName>SawRape_Honorable</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>observed rape</label>
<description>The strong claim their due from the weak.</description>
<baseMoodEffect>+2</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
</Defs>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThoughtDef>
<defName>ExposeUnderwear</defName>
<workerClass>Privacy_Please.ThoughtWorker_ExposedUnderwear</workerClass>
<validWhileDespawned>true</validWhileDespawned>
<stages>
<li>
<label>exposed underwear</label>
<description>People can see my underwear, it's embarassing.</description>
<baseMoodEffect>-2</baseMoodEffect>
</li>
<li>
<label>visible underwear</label>
<description>My underwear is showing, but's not a big deal.</description>
<baseMoodEffect>0</baseMoodEffect>
</li>
<li>
<label>faunting underwear</label>
<description>It's a bit thrilling to be showing my underwear off!</description>
<baseMoodEffect>1</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
</Defs>

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThoughtDef>
<defName>SawHAR_AlienDating_Prohibited</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<hediff>Indignant</hediff>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>horrified by xenophilia</label>
<description>Filthy degenerates!</description>
<baseMoodEffect>-15</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawHAR_AlienDating_Horrible</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<hediff>Disquiet</hediff>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>disturbed by xenophilia</label>
<description>Oh! That's not right...</description>
<baseMoodEffect>-10</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawHAR_AlienDating_Acceptable</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>saw xenophilia</label>
<description>Oops, sorry about walking in on you!</description>
<baseMoodEffect>-4</baseMoodEffect>
</li>
</stages>
<nullifyingPrecepts>
<li>Exhibitionism_Acceptable</li>
<li>Exhibitionism_Approved</li>
</nullifyingPrecepts>
</ThoughtDef>
<ThoughtDef>
<defName>SawHAR_AlienDating_Preferred</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>noticed xenophilia</label>
<description>I wonder what their kids would look like?</description>
<baseMoodEffect>+1</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
<ThoughtDef>
<defName>SawHAR_AlienDating_Know_Honorable</defName>
<durationDays>3</durationDays>
<stackLimit>3</stackLimit>
<stackLimitForSameOtherPawn>1</stackLimitForSameOtherPawn>
<stages>
<li>
<label>observed xenophilia</label>
<description>A blending of species will make us stronger.</description>
<baseMoodEffect>+2</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
</Defs>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
<!-- Basic settings-->
<privacy_please_basicsettings>Privacy, Please!</privacy_please_basicsettings>
<privacy_please_general>General Options</privacy_please_general>
<need_privacy> People will react to consensual sex</need_privacy>
<need_privacy_desc>Their reaction will depend on their Exhibitionism precept and whether they have the Voyeur RJW quirk.\n\nNon-exhibitionist couples will stop what they are doing when caught.</need_privacy_desc>
<worry_about_masturbation> People will react to masturbation</worry_about_masturbation>
<worry_about_masturbation_desc>Their reaction will depend on their Exhibitionism precept and whether they have the Voyeur RJW quirk.\n\nNon-exhibitionists masturbators will stop what they are doing when caught.</worry_about_masturbation_desc>
<worry_about_infidelity> People will react to a cheating partner</worry_about_infidelity>
<worry_about_infidelity_desc>Their reaction will depend on their Lovin' precept, ignoring cheating if lovin' is 'free and approved'.\n\nWitnessing cheating may result in a random extreme reaction occuring.</worry_about_infidelity_desc>
<worry_about_beastiality> People will react to beastiality</worry_about_beastiality>
<worry_about_beastiality_desc>Their reaction will depend on their Bestiality precept (requires Sexperience - Ideology) and whether they have the Zoophile trait.\n\nWitnessing beastiality may result in panick.</worry_about_beastiality_desc>
<worry_about_rape> People will react to rape</worry_about_rape>
<worry_about_rape_desc>Their reaction will depend on their Rape precept (requires Sexperience - Ideology) and whether they have the Rapist trait.\n\nWitnessing rape may result in panick.</worry_about_rape_desc>
<ignore_slave_rape> People will ignore a rape if the victim is a prisoner or slave</ignore_slave_rape>
<worry_about_necro> People will react to necrophilia</worry_about_necro>
<worry_about_necro_desc>Their reaction will depend on their Necrophilia precept (requires Sexperience - Ideology) and whether they have the Necrophile trait.\n\nWitnessing necrophilia may result in vomiting.</worry_about_necro_desc>
<worry_about_xeno> People will react to couplings between humanoids of different species</worry_about_xeno>
<worry_about_xeno_desc>Their reaction will depend on their Alien Dating precept (requires Humanoid Alien Races) and whether they have the Xenophile or Xenophobe traits.\n\nWitnessing xenophilia as a Xenophobe may result in the lovin' couple being harrassed.</worry_about_xeno_desc>
<worry_about_incest> People will react to incest</worry_about_incest>
<worry_about_incest_desc>Their reaction will depend on their Incest precept (requires Sexperience - Ideology).\n\nWitnessing incest may result in harrassment.</worry_about_incest_desc>
<major_taboo_can_start_fights> Witnessing a major taboo may result in an extreme reactions</major_taboo_can_start_fights>
<major_taboo_can_start_fights_desc>Individuals who witness a sexual act that seriously upsets them may cause them to flee from, insult, or even attack the offender.</major_taboo_can_start_fights_desc>
<ignore_ritual_and_party_sex> People will ignore sexual acts that are a part of a ritual or gathering</ignore_ritual_and_party_sex>
<ignore_ritual_and_party_sex_desc>The demands required by rituals and customs must be respected.</ignore_ritual_and_party_sex_desc>
<slaves_ignore_sex> Prisoners and slaves ignore sexual acts</slaves_ignore_sex>
<slaves_ignore_sex_desc>Prisoners and slaves have discovered that it is better to simply ignore what is occurring around them.</slaves_ignore_sex_desc>
<other_factions_ignore_sex> People belonging to other factions will ignore sexual acts</other_factions_ignore_sex>
<other_factions_ignore_sex_desc>Members of friendly factions will politely ignore any sexual acts occurring around them.\n\nHostile factions will always ignore such frivolities, regardless of this setting.</other_factions_ignore_sex_desc>
<chance_for_other_to_join_in_sex> People who are lovin' have a chance to invite passers-by to join them for some fun (default is 0.25)</chance_for_other_to_join_in_sex>
<chance_for_other_to_join_in_sex_desc>Note that setting this value to its maximum will not guarantee that this event will occur, it will just maximize the chance of an invitation being made.\n\nAll individuals involved must be attracted to and have a good opinion of each other, and the activity must not violate their traits or ideology.\n\nSet this value to zero to prevent these invitations being made.</chance_for_other_to_join_in_sex_desc>
<privacy_please_clothing>Clothing options</privacy_please_clothing>
<underwear_sufficent_for_ideos> Underwear satisfies ideological needs for modesty</underwear_sufficent_for_ideos>
<underwear_sufficent_for_ideos_desc>If an ideology demands that certain body parts must be covered, wearing underwear (clothing that only covers the chest or groin) can help fulfill this requirement.\n\nYou may want to turn this setting off if you want ideologies to be more strict about what they consider to be 'modestly clothed'.\n\nIdeologies which prefer to wear fewer clothes than normal are not affected by this setting.</underwear_sufficent_for_ideos_desc>
<exposed_underwear_mood> People feel embarrassed if their underwear is showing</exposed_underwear_mood>
<exposed_underwear_mood_desc>It isn't as bad as being naked, but people would prefer to be fully clothed. Exhibitionists, however, seem to get a small thrill out of having their underwear exposed.\n\nClothing which only covers the chest or groin will be considered underwear.</exposed_underwear_mood_desc>
<privacy_please_debugging>Debugging options</privacy_please_debugging>
<debug_mode> Turn on debugging console messages</debug_mode>
<debug_mode_desc>Only required for debugging purposes.</debug_mode_desc>
</LanguageData>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<LanguageData>
<VoyeurQuirk><![CDATA[
{pawn} gets a thrill out of spying upon others while they are engaged in intimate acts.
]]></VoyeurQuirk>
<CuckoldQuirk><![CDATA[
{pawn} gets turned on when watching their partner have sex with others.
]]></CuckoldQuirk>
</LanguageData>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
<Operation Class="PatchOperationSequence">
<success>Normal</success>
<operations>
<li Class="PatchOperationAdd">
<success>Always</success>
<xpath>Defs/ThoughtDef[defName="CheatedOnMe"][not(nullifyingPrecepts)]</xpath>
<value>
<nullifyingPrecepts />
</value>
</li>
<li Class="PatchOperationAdd">
<success>Always</success>
<xpath>Defs/ThoughtDef[defName="Affair"][not(nullifyingPrecepts)]</xpath>
<value>
<nullifyingPrecepts />
</value>
</li>
<li Class="PatchOperationAdd">
<xpath>Defs/ThoughtDef[defName="CheatedOnMe"]/nullifyingPrecepts</xpath>
<value>
<li>Lovin_FreeApproved</li>
</value>
</li>
<li Class="PatchOperationAdd">
<xpath>Defs/ThoughtDef[defName="Affair"]/nullifyingPrecepts</xpath>
<value>
<li>Lovin_FreeApproved</li>
</value>
</li>
</operations>
</Operation>
</Patch>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
<Operation Class="PatchOperationSequence">
<success>Normal</success>
<operations>
<li Class="PatchOperationAdd">
<success>Always</success>
<xpath>Defs/ThingDef[race][not(comps)]</xpath>
<value>
<comps />
</value>
</li>
<li Class="PatchOperationAdd">
<success>Always</success>
<xpath>Defs/AlienRace.ThingDef_AlienRace[not(comps)]</xpath>
<value>
<comps />
</value>
</li>
<li Class="PatchOperationAdd">
<xpath>Defs/ThingDef[@Name="BasePawn"]/comps</xpath>
<value>
<li Class="Privacy_Please.CompProperties_PawnThoughtData" />
</value>
</li>
<li Class="PatchOperationAdd">
<xpath>Defs/AlienRace.ThingDef_AlienRace/comps</xpath>
<value>
<li Class="Privacy_Please.CompProperties_PawnThoughtData" />
</value>
</li>
</operations>
</Operation>
</Patch>

39
Patches/FilthDefs.xml Normal file
View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
<Operation Class="PatchOperationSequence">
<success>Normal</success>
<operations>
<li Class="PatchOperationAdd">
<success>Always</success>
<xpath>Defs/ThingDef[defName="FilthCum"][not(comps)]</xpath>
<value>
<comps />
</value>
</li>
<li Class="PatchOperationAdd">
<success>Always</success>
<xpath>Defs/ThingDef[defName="FilthGirlCum"][not(comps)]</xpath>
<value>
<comps />
</value>
</li>
<li Class="PatchOperationAdd">
<xpath>Defs/ThoughtDef[defName="CheatedOnMe"]/nullifyingPrecepts</xpath>
<value>
<li>Lovin_FreeApproved</li>
</value>
</li>
<li Class="PatchOperationAdd">
<xpath>Defs/ThoughtDef[defName="Affair"]/nullifyingPrecepts</xpath>
<value>
<li>Lovin_FreeApproved</li>
</value>
</li>
</operations>
</Operation>
</Patch>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
<Operation Class="PatchOperationFindMod">
<mods>
<li>UnderWhere</li>
</mods>
<match Class="PatchOperationSequence">
<success>Always</success>
<operations>
<li Class="PatchOperationReplace">
<xpath>Defs/ThingDef[defName="UnderWhere_Panties" or defName="UnderWhere_Boxers" or defName="UnderWhere_Loincloth"]/apparel/bodyPartGroups</xpath>
<value>
<bodyPartGroups>
<li>GenitalsBPG</li>
</bodyPartGroups>
</value>
</li>
<li Class="PatchOperationReplace">
<xpath>Defs/ThingDef[defName="UnderWhere_Bra" or defName="UnderWhere_Chestwrap"]/apparel/bodyPartGroups</xpath>
<value>
<bodyPartGroups>
<li>ChestBPG</li>
</bodyPartGroups>
</value>
</li>
</operations>
</match>
</Operation>
</Patch>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<Patch>
<Operation Class="PatchOperationFindMod">
<mods>
<li>S16's Extension</li>
</mods>
<match Class="PatchOperationSequence">
<success>Always</success>
<operations>
<li Class="PatchOperationReplace">
<xpath>Defs/ThingDef/thingCategories[li="S16_Underwear"]/../apparel/bodyPartGroups</xpath>
<value>
<bodyPartGroups>
<li>GenitalsBPG</li>
</bodyPartGroups>
</value>
</li>
</operations>
</match>
</Operation>
</Patch>

View File

@ -1,92 +0,0 @@
# Privacy-Please
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin https://gitgud.io/AbstractConcept/privacy-please.git
git branch -M master
git push -uf origin master
```
## Integrate with your tools
- [ ] [Set up project integrations](https://gitgud.io/AbstractConcept/privacy-please/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.

Binary file not shown.

View File

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{AC00E678-E117-4BC2-8C3E-DA26509E2F6D}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>Privacy_Please</RootNamespace>
<AssemblyName>Privacy-Please</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\1.4\Assemblies\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Compile Include="Scripts\Comps\CompPawnThoughtData.cs" />
<Compile Include="Scripts\Comps\CompProperties_PawnThoughtData.cs" />
<Compile Include="Scripts\Extensions\PawnExtension.cs" />
<Compile Include="Scripts\JobDrivers\JobDriver_WatchSex.cs" />
<Compile Include="Scripts\JobDrivers\JobDriver_JoinInSex.cs" />
<Compile Include="Scripts\Patches\HarmonyPatch_PatchAll.cs" />
<Compile Include="Scripts\Patches\HarmonyPatch_RJW.cs" />
<Compile Include="Scripts\Patches\HarmonyPatch_ThoughtWorkers.cs" />
<Compile Include="Scripts\Settings\BasicSettings.cs" />
<Compile Include="Scripts\ThoughtWorkers\ThoughtWorker_ExposedUnderwear.cs" />
<Compile Include="Scripts\Utilities\DebugMode.cs" />
<Compile Include="Scripts\Utilities\ModDefOf.cs" />
<Compile Include="Scripts\Utilities\SexInteractionUtility.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="0Harmony">
<HintPath>..\..\..\..\..\workshop\content\294100\2009463077\Current\Assemblies\0Harmony.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="AlienRace">
<HintPath>..\..\..\..\..\workshop\content\294100\839005762\1.4\Assemblies\AlienRace.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Assembly-CSharp">
<HintPath>..\..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Rimworld-Animations">
<HintPath>..\..\rimworld-animations-master\1.4\Assemblies\Rimworld-Animations.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="RJW">
<HintPath>..\..\RJW\1.4\Assemblies\RJW.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="UnityEngine">
<HintPath>..\..\..\RimWorldWin64_Data\Managed\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>..\..\..\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30011.22
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AbsCon_PrivacyPlease", "AbsCon_PrivacyPlease.csproj", "{AC00E678-E117-4BC2-8C3E-DA26509E2F6D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AC00E678-E117-4BC2-8C3E-DA26509E2F6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AC00E678-E117-4BC2-8C3E-DA26509E2F6D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AC00E678-E117-4BC2-8C3E-DA26509E2F6D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AC00E678-E117-4BC2-8C3E-DA26509E2F6D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F81BB2E3-A87F-4B5D-974E-E42884E9B8B6}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using Verse;
using AlienRace;
using UnityEngine;
using rjw;
using HarmonyLib;
namespace Privacy_Please
{
public class CompPawnThoughtData : ThingComp
{
private Pawn pawn;
private int lastExclaimationTick = -1;
private int exclaimationCoolDown = 90;
public override void Initialize(CompProperties props)
{
if (pawn == null)
{ pawn = parent as Pawn; }
}
// Delay the cleaning of filth under the sexing pawns
public override void CompTickRare()
{
base.CompTickRare();
if (pawn?.jobs?.curDriver != null && pawn.jobs.curDriver is JobDriver_Sex)
{
IEnumerable<Thing> filthPile = pawn.PositionHeld.GetThingList(pawn.Map);
if (filthPile == null) return;
foreach(Thing thing in filthPile)
{
if ((thing is Filth) == false) continue;
AccessTools.Field(typeof(Filth), "growTick").SetValue(thing as Filth, Find.TickManager.TicksGame);
}
}
}
public void TryToExclaim()
{
if (Find.TickManager.TicksGame > exclaimationCoolDown + lastExclaimationTick)
{
lastExclaimationTick = Find.TickManager.TicksGame;
FleckMaker.ThrowMetaIcon(pawn.Position, pawn.Map, FleckDefOf.IncapIcon);
}
}
}
}

View File

@ -0,0 +1,13 @@
using System;
using Verse;
namespace Privacy_Please
{
public class CompProperties_PawnThoughtData : CompProperties
{
public CompProperties_PawnThoughtData()
{
base.compClass = typeof(CompPawnThoughtData);
}
}
}

View File

@ -0,0 +1,273 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Verse;
using Verse.AI;
using Verse.AI.Group;
using RimWorld;
using rjw;
using Rimworld_Animations;
using HarmonyLib;
namespace Privacy_Please
{
public static class PawnExtension
{
public static bool IsInBed(this Pawn pawn, out Building bed)
{
bed = pawn.Position.GetThingList(pawn.Map).FirstOrDefault(x => x is Building_Bed) as Building;
return bed != null;
}
public static bool IsSeated(this Pawn pawn, out Building seat)
{
seat = pawn.Position.GetThingList(pawn.Map).FirstOrDefault(x => x is Building && x.def.building.isSittable) as Building;
return seat != null;
}
public static bool IsHavingSex(this Pawn pawn)
{
if (pawn?.jobs?.curDriver == null || pawn.Dead || pawn.jobs.curDriver is JobDriver_Sex == false)
{ return false; }
JobDriver_Sex jobdriver = pawn.jobs.curDriver as JobDriver_Sex;
return jobdriver.Partner != null && jobdriver.Partner != pawn;
}
public static bool IsMasturbating(this Pawn pawn)
{
if (pawn?.jobs?.curDriver == null || pawn.Dead || pawn.jobs.curDriver is JobDriver_Sex == false)
{ return false; }
JobDriver_Sex jobdriver = pawn.jobs.curDriver as JobDriver_Sex;
return jobdriver.Partner == null || jobdriver.Partner == pawn || (jobdriver.Partner is Pawn) == false;
}
public static Pawn GetSexInitiator(this Pawn pawn)
{
if (pawn?.jobs?.curDriver != null && pawn.Dead == false && pawn.jobs.curDriver is JobDriver_SexBaseInitiator)
{ return pawn; }
JobDriver_SexBaseReciever jobDriver = pawn.jobs.curDriver as JobDriver_SexBaseReciever;
if (jobDriver?.Partner?.jobs?.curDriver != null && jobDriver.Partner.Dead == false && jobDriver.Partner.jobs.curDriver is JobDriver_SexBaseInitiator)
{ return jobDriver.Partner; }
return null;
}
public static Pawn GetSexReceiver(this Pawn pawn)
{
if (pawn.jobs.curDriver is JobDriver_SexBaseReciever)
{ return pawn; }
JobDriver_SexBaseInitiator jobDriver = pawn.jobs.curDriver as JobDriver_SexBaseInitiator;
if (jobDriver?.Partner?.jobs?.curDriver != null && jobDriver.Partner.Dead == false && jobDriver.Partner.jobs.curDriver is JobDriver_SexBaseReciever)
{ return jobDriver.Partner; }
return null;
}
public static Pawn GetSexPartner(this Pawn pawn)
{
return (pawn.jobs.curDriver as JobDriver_Sex)?.Partner;
}
public static List<Pawn> GetAllSexParticipants(this Pawn pawn)
{
List<Pawn> participants = new List<Pawn>();
if (pawn?.jobs?.curDriver == null || (pawn.jobs.curDriver is JobDriver_Sex) == false)
{ return participants; }
if (pawn.GetSexReceiver() != null)
{
List<Pawn> partners = (pawn.GetSexReceiver().jobs.curDriver as JobDriver_SexBaseReciever).parteners.ToList();
if (partners != null)
{
foreach (Pawn partner in partners)
{
if (partner != null)
{ participants = partners; }
}
}
}
if (pawn.GetSexInitiator() != null)
{
Pawn partner = (pawn.GetSexInitiator().jobs.curDriver as JobDriver_SexBaseInitiator).Partner;
if (partner != null && partner.Dead == false)
{ participants.AddDistinct(partner); }
}
participants.AddDistinct(pawn);
return participants;
}
public static bool IsLoverOfOther(this Pawn pawn, Pawn other)
{
if (pawn == null || other == null)
{ return false; }
List<DirectPawnRelation> lovers = SpouseRelationUtility.GetLoveRelations(pawn, false);
return lovers.Any(x => x.otherPawn == other);
}
public static bool HasPrivacy(this Pawn pawn, float radius)
{
if (pawn.UnworriedAboutHumanSex() == false)
{ return true; }
if (pawn.IsHavingSex() == false && pawn.IsMasturbating() == false)
{ return true; }
if (pawn.GetLord() != null && (pawn.GetLord().LordJob is LordJob_Ritual || pawn.GetLord().LordJob is LordJob_Joinable_Party) && BasicSettings.ignoreRitualAndPartySex)
{ return true; }
bool hasPrivacy = true;
pawn.IsInBed(out Building bed);
foreach (Thing thing in GenRadial.RadialDistinctThingsAround(pawn.Position, pawn.Map, radius, true))
{
Pawn witness = thing as Pawn;
if (witness == null) continue;
// Caught having sex
if (SexInteractionUtility.PawnCaughtLovinByWitness(pawn, witness))
{
// Try to invite intruder to join in
if (SexInteractionUtility.InvitePasserbyForSex(pawn, witness, out bool brokeTaboo))
{
if (pawn.IsMasturbating())
{
if (bed == null)
{
Job job = new Job(xxx.quick_sex, pawn);
witness.jobs.TryTakeOrderedJob(job);
}
else
{
Job job = new Job(xxx.casual_sex, pawn, bed);
witness.jobs.TryTakeOrderedJob(job);
}
}
else if (pawn.GetSexReceiver() != null)
{
Job job = new Job(DefDatabase<JobDef>.GetNamed("JoinInSex", false), pawn.GetSexReceiver(), bed);
witness.jobs.TryTakeOrderedJob(job);
}
}
// Voyeurs and cuckolds like to watch
else if (CasualSex_Helper.CanHaveSex(witness) && xxx.IsTargetPawnOkay(witness) &&
(xxx.has_quirk(witness, "Voyeur") || (xxx.has_quirk(witness, "Cuckold") && SexInteractionUtility.SexParticipantsIncludesACheatingPartner(witness, pawn.GetAllSexParticipants()))))
{
Job job = new Job(DefDatabase<JobDef>.GetNamed("WatchSex", false), pawn.GetSexReceiver(), bed);
witness.jobs.TryTakeOrderedJob(job);
}
// Do nothing if witness is a lover and no taboo was not broken
else if (brokeTaboo == false && witness.IsLoverOfOther(pawn))
{ }
// Privacy was breached
else
{ hasPrivacy = false; }
}
}
return BasicSettings.needPrivacy == false ||
hasPrivacy ||
xxx.has_quirk(pawn, "Exhibitionist") ||
pawn?.ideo?.Ideo.HasPrecept(ModPreceptDefOf.Exhibitionism_Acceptable) == true ||
pawn?.ideo?.Ideo.HasPrecept(ModPreceptDefOf.Exhibitionism_Approved) == true;
}
public static bool HasPreceptForIssue(this Pawn pawn, string issueDefName, out Precept precept)
{
precept = null;
if (pawn?.Ideo == null)
{ return false; }
foreach (Precept _precept in pawn.Ideo.PreceptsListForReading)
{
if (_precept.def.issue.defName == issueDefName)
{
precept = _precept;
return true;
}
}
return false;
}
public static bool EnjoysViolence(this Pawn pawn)
{
if (pawn.IsAnimal() || pawn.RaceProps.IsMechanoid)
{ return true; }
if (pawn?.story?.traits?.allTraits == null || pawn?.story?.traits?.allTraits.NullOrEmpty() == true)
{ return false; }
List<string> traits = new List<string>() { "Brawler", "Psychopath", "Bloodlust" };
return pawn.story.traits.allTraits.Any(x => traits.Contains(x.def.defName));
}
public static bool DislikesViolence(this Pawn pawn)
{
if (pawn.IsAnimal() || pawn.RaceProps.IsMechanoid)
{ return false; }
if (pawn?.story?.traits?.allTraits == null || pawn?.story?.traits?.allTraits.NullOrEmpty() == true)
{ return false; }
List<string> traits = new List<string>() { "Kind", "Wimp" };
return pawn.WorkTagIsDisabled(WorkTags.Violent) || pawn.story.traits.allTraits.Any(x => traits.Contains(x.def.defName));
}
public static bool HasTrait(this Pawn pawn, string trait)
{
if (pawn?.story?.traits?.allTraits == null || pawn.story.traits.allTraits.NullOrEmpty())
{ return false; }
TraitDef traitDef = DefDatabase<TraitDef>.GetNamedSilentFail(trait);
if (traitDef == null)
{ traitDef = DefDatabase<TraitDef>.GetNamedSilentFail(trait.ToLower()); }
return HasTrait(pawn, traitDef);
}
public static bool HasTrait(this Pawn pawn, TraitDef traitDef)
{
if (pawn?.story?.traits?.allTraits == null || pawn.story.traits.allTraits.NullOrEmpty())
{ return false; }
if (traitDef == null)
{ return false; }
return pawn.story.traits.HasTrait(traitDef);
}
public static bool UnworriedAboutHumanSex(this Pawn pawn)
{
return (pawn.Dead ||
pawn.AnimalOrWildMan() ||
pawn.RaceProps.IsMechanoid ||
pawn.Awake() == false ||
pawn.Suspended == false ||
(pawn.Faction != null && pawn.Faction.HostileTo(Faction.OfPlayer))) == false;
}
}
}

View File

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using Verse;
using Verse.AI;
using rjw;
namespace Privacy_Please
{
public class JobDriver_JoinInSex : JobDriver_SexBaseInitiator
{
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
return true;
}
protected override IEnumerable<Toil> MakeNewToils()
{
setup_ticks();
this.FailOnDespawnedNullOrForbidden(iTarget);
this.FailOn(() => !Partner.health.capacities.CanBeAwake);
this.FailOn(() => pawn.Drafted);
this.FailOn(() => Partner.Drafted);
Toil FollowToil = new Toil();
FollowToil.defaultCompleteMode = ToilCompleteMode.Delay;
FollowToil.socialMode = RandomSocialMode.Off;
FollowToil.defaultDuration = 1200;
FollowToil.tickAction = delegate
{
pawn.pather.StartPath(Partner, PathEndMode.Touch);
if (pawn.pather.Moving == false && Partner.pather.Moving == false && Partner.jobs.curDriver is JobDriver_SexBaseReciever)
{ ReadyForNextToil(); }
};
yield return FollowToil;
Toil SexToil = new Toil();
SexToil.socialMode = RandomSocialMode.Off;
SexToil.defaultDuration = duration;
SexToil.handlingFacing = true;
SexToil.FailOn(() => (Partner.jobs.curDriver is JobDriver_SexBaseReciever) == false);
SexToil.initAction = delegate
{
Start();
Sexprops.usedCondom = CondomUtility.TryUseCondom(pawn) || CondomUtility.TryUseCondom(Partner);
};
SexToil.AddPreTickAction(delegate
{
if (pawn.IsHashIntervalTick(ticks_between_hearts))
ThrowMetaIconF(pawn.Position, pawn.Map, FleckDefOf.Heart);
SexTick(pawn, Partner);
SexUtility.reduce_rest(pawn, 1);
if (ticks_left <= 0)
ReadyForNextToil();
});
SexToil.AddFinishAction(delegate
{
End();
});
yield return SexToil;
yield return new Toil
{
initAction = delegate { SexUtility.ProcessSex(Sexprops); },
defaultCompleteMode = ToilCompleteMode.Instant
};
}
}
}

View File

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using UnityEngine;
using Verse;
using Verse.AI;
using rjw;
using Rimworld_Animations;
namespace Privacy_Please
{
public class JobDriver_WatchSex : JobDriver_SexBaseInitiator
{
private int ticks_between_eyes = 120;
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
return true;
}
protected override IEnumerable<Toil> MakeNewToils()
{
this.FailOnDespawnedNullOrForbidden(iTarget);
this.FailOn(() => !Partner.health.capacities.CanBeAwake);
this.FailOn(() => pawn.Drafted);
this.FailOn(() => Partner.Drafted);
Toil WatchToil = new Toil();
WatchToil.defaultCompleteMode = ToilCompleteMode.Never;
WatchToil.socialMode = RandomSocialMode.Off;
WatchToil.FailOn(() => (Partner.jobs.curDriver is JobDriver_Sex) == false);
WatchToil.initAction = delegate
{
pawn.pather.StopDead();
};
WatchToil.AddPreTickAction(delegate
{
if (pawn.IsHashIntervalTick(ticks_between_eyes))
{ ThrowMetaIconF(pawn.Position, pawn.Map, ModFleckDefOf.Eye); }
if (pawn?.needs?.TryGetNeed<Need_Sex>() != null)
{ pawn.needs.TryGetNeed<Need_Sex>().CurLevel += 0.5f / 2500f; }
});
yield return WatchToil;
}
}
}

View File

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using HarmonyLib;
using System.Reflection;
using rjw;
namespace Privacy_Please
{
[StaticConstructorOnStartup]
public static class Harmony_PatchAll
{
static Harmony_PatchAll()
{
Harmony harmony = new Harmony("Rimworld_Animations_Patch");
harmony.PatchAll(Assembly.GetExecutingAssembly());
// Add quirks to game
Quirk voyeur = new Quirk("Voyeur", "VoyeurQuirk");
Quirk.All.AddDistinct(voyeur);
Quirk cuckold = new Quirk("Cuckold", "CuckoldQuirk");
Quirk.All.AddDistinct(cuckold);
}
}
}

View File

@ -0,0 +1,93 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using HarmonyLib;
using RimWorld;
using Verse;
using Verse.AI;
using rjw;
namespace Privacy_Please
{
[HarmonyPatch(typeof(JobDriver_Sex), "setup_ticks")]
public static class HarmonyPatch_JobDriver_Sex_setup_ticks
{
public static void Postfix(ref JobDriver_Sex __instance)
{
Pawn pawn = __instance.pawn;
// Invite another for a threesome?
if (RJWHookupSettings.QuickHookupsEnabled &&
__instance is JobDriver_SexBaseInitiator &&
pawn.GetAllSexParticipants().Count == 2 &&
(__instance is JobDriver_JoinInSex) == false &&
Random.value < BasicSettings.chanceForOtherToJoinInSex)
{
DebugMode.Message("Find another to join in sex");
List<Pawn> candidates = new List<Pawn>();
float radius = 4f;
foreach (Thing thing in GenRadial.RadialDistinctThingsAround(pawn.Position, pawn.Map, radius, true))
{
Pawn other = thing as Pawn;
ThoughtDef thoughtDef = SexInteractionUtility.GetThoughtsAboutSexAct(other, __instance, out Precept precept);
// Find candidates to invite
if (other != null && thoughtDef?.hediff == null && SexInteractionUtility.CouldInvitePasserbyForSex(other, pawn.GetAllSexParticipants()))
{
DebugMode.Message(other.NameShortColored + " is a potential candidate");
candidates.Add(other);
}
}
// Invite a random candidate (weighted by attraction)
if (candidates.Count > 0)
{
Pawn invitedPawn = candidates.RandomElementByWeight(x => SexAppraiser.would_fuck(pawn, x, false, false, true) + SexAppraiser.would_fuck(pawn.GetSexPartner(), x, false, false, true));
pawn.GetSexInitiator().IsInBed(out Building bed);
DebugMode.Message(invitedPawn.NameShortColored + " was invited to join in sex");
Job job = new Job(DefDatabase<JobDef>.GetNamed("JoinInSex", false), pawn.GetSexPartner(), bed);
invitedPawn.jobs.TryTakeOrderedJob(job);
}
}
}
}
[HarmonyPatch(typeof(JobDriver_Sex), "SexTick")]
public static class HarmonyPatch_JobDriver_Sex_SexTick
{
// If pawns don't have privacy, they'll stop having sex
public static void Postfix(ref JobDriver_Sex __instance, Pawn pawn)
{
if (pawn.IsHashIntervalTick(90))
{
if (pawn.IsMasturbating() && pawn.HasPrivacy(8f) == false)
{ pawn.jobs.EndCurrentJob(JobCondition.InterruptForced, false, false); }
else if (pawn.IsHavingSex())
{
bool havePrivacy = true;
List<Pawn> participants = pawn.GetAllSexParticipants();
foreach (Pawn participant in participants)
{
if (participant.HasPrivacy(8f) == false)
{ havePrivacy = false; }
}
if (__instance.Sexprops != null && (__instance.Sexprops.isRape || __instance.Sexprops.isWhoring))
{ return; }
if (havePrivacy == false)
{
foreach (Pawn participant in participants)
{ participant.jobs.EndCurrentJob(JobCondition.InterruptForced, false, false); }
}
}
}
}
}
}

View File

@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using Verse;
using HarmonyLib;
namespace Privacy_Please
{
[HarmonyPatch(typeof(ThoughtWorker_Precept_GroinChestHairOrFaceUncovered), "HasUncoveredGroinChestHairOrFace")]
public static class HarmonyPatch_ThoughtWorker_Precept_GroinChestHairOrFaceUncovered
{
public static void Postfix(ref bool __result, Pawn p)
{
if (__result == false) return;
Pawn pawn = p;
if (BasicSettings.underwearSufficentForIdeos == false) return;
if (pawn?.apparel == null)
{ __result = false; return; }
if (pawn.apparel.WornApparel.NullOrEmpty())
{ __result = true; return; }
bool fullHeadCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.FullHead));
bool groinCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Legs) || x.def.apparel.bodyPartGroups.Contains(ModBodyPartGroupDefOf.GenitalsBPG));
bool chestCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso) || x.def.apparel.bodyPartGroups.Contains(ModBodyPartGroupDefOf.ChestBPG));
bool faceCovered = fullHeadCovered || pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Eyes));
bool hairCovered = fullHeadCovered || pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.UpperHead));
__result = !(groinCovered && chestCovered && faceCovered && hairCovered);
}
}
[HarmonyPatch(typeof(ThoughtWorker_Precept_GroinChestOrHairUncovered), "HasUncoveredGroinChestOrHair")]
public static class HarmonyPatch_ThoughtWorker_Precept_GroinChestOrHairUncovered
{
public static void Postfix(ref bool __result, Pawn p)
{
if (__result == false) return;
Pawn pawn = p;
if (BasicSettings.underwearSufficentForIdeos == false) return;
if (pawn?.apparel == null)
{ __result = false; return; }
if (pawn.apparel.WornApparel.NullOrEmpty())
{ __result = true; return; }
bool fullHeadCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.FullHead));
bool groinCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Legs) || x.def.apparel.bodyPartGroups.Contains(ModBodyPartGroupDefOf.GenitalsBPG));
bool chestCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso) || x.def.apparel.bodyPartGroups.Contains(ModBodyPartGroupDefOf.ChestBPG));
bool hairCovered = fullHeadCovered || pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.UpperHead));
__result = !(groinCovered && chestCovered && hairCovered);
}
}
[HarmonyPatch(typeof(ThoughtWorker_Precept_GroinOrChestUncovered), "HasUncoveredGroinOrChest")]
public static class HarmonyPatch_ThoughtWorker_Precept_HasUncoveredGroinOrChest
{
public static void Postfix(ref bool __result, Pawn p)
{
if (__result == false) return;
Pawn pawn = p;
if (BasicSettings.underwearSufficentForIdeos == false) return;
if (pawn?.apparel == null)
{ __result = false; return; }
if (pawn.apparel.WornApparel.NullOrEmpty())
{ __result = true; return; }
bool groinCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Legs) || x.def.apparel.bodyPartGroups.Contains(ModBodyPartGroupDefOf.GenitalsBPG));
bool chestCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso) || x.def.apparel.bodyPartGroups.Contains(ModBodyPartGroupDefOf.ChestBPG));
__result = !(groinCovered && chestCovered);
}
}
[HarmonyPatch(typeof(ThoughtWorker_Precept_GroinUncovered), "HasUncoveredGroin")]
public static class HarmonyPatch_ThoughtWorker_Precept_GroinUncovered
{
public static void Postfix(ref bool __result, Pawn p)
{
if (__result == false) return;
Pawn pawn = p;
if (BasicSettings.underwearSufficentForIdeos == false) return;
if (pawn?.apparel == null)
{ __result = false; return; }
if (pawn.apparel.WornApparel.NullOrEmpty())
{ __result = true; return; }
bool groinCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Legs) || x.def.apparel.bodyPartGroups.Contains(ModBodyPartGroupDefOf.GenitalsBPG));
__result = !groinCovered;
}
}
}

View File

@ -0,0 +1,143 @@
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using Verse;
using RimWorld;
namespace Privacy_Please
{
public class BasicSettings : ModSettings
{
public static bool needPrivacy = true;
public static float chanceForOtherToJoinInSex = 0.25f;
public static bool debugMode = false;
public static bool worryAboutInfidelity = true;
public static bool worryAboutBeastiality = true;
public static bool worryAboutRape = true;
public static bool worryAboutNecro = true;
public static bool worryAboutXeno = true;
public static bool worryAboutMasturbation = true;
public static bool worryAboutIncest = true;
public static bool majorTabooCanStartFights = false;
public static bool ignoreRitualAndPartySex = true;
public static bool slavesIgnoreSex = false;
public static bool ignoreSlaveRape = false;
public static bool otherFactionsIgnoreSex = false;
public static bool underwearSufficentForIdeos = true;
public static bool exposedUnderwearMood = true;
public override void ExposeData()
{
base.ExposeData();
Scribe_Values.Look(ref needPrivacy, "needPrivacy", true);
Scribe_Values.Look(ref chanceForOtherToJoinInSex, "chanceForSexExtra", 0.25f);
Scribe_Values.Look(ref debugMode, "debugMode", false);
Scribe_Values.Look(ref worryAboutInfidelity, "worryAboutInfidelity", true);
Scribe_Values.Look(ref worryAboutBeastiality, "worryAboutBeastiality", true);
Scribe_Values.Look(ref worryAboutRape, "worryAboutRape", true);
Scribe_Values.Look(ref worryAboutNecro, "worryAboutNecro", true);
Scribe_Values.Look(ref worryAboutXeno, "worryAboutXeno", true);
Scribe_Values.Look(ref worryAboutMasturbation, "worryAboutMasturbation", true);
Scribe_Values.Look(ref worryAboutIncest, "worryAboutIncest", true);
Scribe_Values.Look(ref ignoreSlaveRape, "ignoreSlaveRape", false);
Scribe_Values.Look(ref majorTabooCanStartFights, "majorTabooCanStartFights", false);
Scribe_Values.Look(ref ignoreRitualAndPartySex, "ignoreRitualAndPartySex", false);
Scribe_Values.Look(ref slavesIgnoreSex, "slavesIgnoreSex", false);
Scribe_Values.Look(ref otherFactionsIgnoreSex, "otherFactionsIgnoreSex", false);
Scribe_Values.Look(ref underwearSufficentForIdeos, "underwearSufficentForIdeos", true);
Scribe_Values.Look(ref underwearSufficentForIdeos, "exposedUnderwearMood", true);
}
}
public class BasicSettingsDisplay : Mod
{
public BasicSettingsDisplay(ModContentPack content) : base(content)
{
GetSettings<BasicSettings>();
}
public override void WriteSettings()
{
base.WriteSettings();
ApplySettings();
}
// Update all humanlike pawn graphics when settings window is closed
public void ApplySettings()
{
if (Current.ProgramState == ProgramState.Playing)
{
foreach (Pawn pawn in Current.Game.CurrentMap.mapPawns.AllPawns)
{
if (pawn == null) continue;
pawn.Drawer?.renderer?.graphics?.ResolveAllGraphics();
PortraitsCache.SetDirty(pawn);
GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(pawn);
}
}
}
public override void DoSettingsWindowContents(Rect inRect)
{
Listing_Standard listingStandard;
listingStandard = new Listing_Standard();
listingStandard.Begin(inRect);
listingStandard.Gap(10f);
listingStandard.Label("privacy_please_general".Translate());
listingStandard.Gap(5f);
listingStandard.CheckboxLabeled("need_privacy".Translate(), ref BasicSettings.needPrivacy, "need_privacy_desc".Translate());
listingStandard.CheckboxLabeled("worry_about_masturbation".Translate(), ref BasicSettings.worryAboutMasturbation, "worry_about_masturbation_desc".Translate());
listingStandard.CheckboxLabeled("worry_about_infidelity".Translate(), ref BasicSettings.worryAboutInfidelity, "worry_about_infidelity_desc".Translate());
listingStandard.CheckboxLabeled("worry_about_beastiality".Translate(), ref BasicSettings.worryAboutBeastiality, "worry_about_beastiality_desc".Translate());
listingStandard.CheckboxLabeled("worry_about_rape".Translate(), ref BasicSettings.worryAboutRape, "worry_about_rape_desc".Translate());
if (BasicSettings.worryAboutRape)
{ listingStandard.CheckboxLabeled("ignore_slave_rape".Translate(), ref BasicSettings.ignoreSlaveRape); }
listingStandard.CheckboxLabeled("worry_about_necro".Translate(), ref BasicSettings.worryAboutNecro, "worry_about_necro_desc".Translate());
listingStandard.CheckboxLabeled("worry_about_xeno".Translate(), ref BasicSettings.worryAboutXeno, "worry_about_xeno_desc".Translate());
listingStandard.Gap(20f);
listingStandard.CheckboxLabeled("ignore_ritual_and_party_sex".Translate(), ref BasicSettings.ignoreRitualAndPartySex, "ignore_ritual_and_party_sex_desc".Translate());
listingStandard.CheckboxLabeled("slaves_ignore_sex".Translate(), ref BasicSettings.slavesIgnoreSex, "slaves_ignore_sex_desc".Translate());
listingStandard.CheckboxLabeled("other_factions_ignore_sex".Translate(), ref BasicSettings.otherFactionsIgnoreSex, "other_factions_ignore_sex_desc".Translate());
listingStandard.CheckboxLabeled("major_taboo_can_start_fights".Translate(), ref BasicSettings.majorTabooCanStartFights, "major_taboo_can_start_fights_desc".Translate());
listingStandard.Gap(20f);
listingStandard.Label("chance_for_other_to_join_in_sex".Translate() + ": " + BasicSettings.chanceForOtherToJoinInSex.ToString("F"), -1f, "chance_for_other_to_join_in_sex_desc".Translate());
BasicSettings.chanceForOtherToJoinInSex = listingStandard.Slider(BasicSettings.chanceForOtherToJoinInSex, 0f, 1f);
listingStandard.Gap(10f);
listingStandard.Label("privacy_please_clothing".Translate());
listingStandard.Gap(5f);
listingStandard.CheckboxLabeled("underwear_sufficent_for_ideos".Translate(), ref BasicSettings.underwearSufficentForIdeos, "underwear_sufficent_for_ideos_desc".Translate());
listingStandard.CheckboxLabeled("exposed_underwear_mood".Translate(), ref BasicSettings.exposedUnderwearMood, "exposed_underwear_mood_desc".Translate());
listingStandard.Gap(15f);
listingStandard.Label("privacy_please_debugging".Translate());
listingStandard.Gap(5f);
listingStandard.CheckboxLabeled("debug_mode".Translate(), ref BasicSettings.debugMode, "debug_mode_desc".Translate());
listingStandard.End();
base.DoSettingsWindowContents(inRect);
}
public sealed override string SettingsCategory()
{
return "privacy_please_basicsettings".Translate();
}
}
}

View File

@ -0,0 +1,38 @@
using System;
using RimWorld;
using Verse;
using rjw;
namespace Privacy_Please
{
public class ThoughtWorker_ExposedUnderwear : ThoughtWorker
{
public static ThoughtState CurrentThoughtState(Pawn pawn)
{
if (xxx.has_quirk(pawn, "Exhibitionist") || pawn?.ideo?.Ideo.HasPrecept(ModPreceptDefOf.Exhibitionism_Approved) == true)
{ return ThoughtState.ActiveAtStage(2); }
if (pawn?.ideo?.Ideo.HasPrecept(ModPreceptDefOf.Exhibitionism_Acceptable) == true)
{ return ThoughtState.ActiveAtStage(1); }
return ThoughtState.ActiveAtStage(0);
}
protected override ThoughtState CurrentStateInternal(Pawn pawn)
{
if (BasicSettings.exposedUnderwearMood == false) return false;
if (pawn?.apparel?.WornApparel == null || pawn.apparel.WornApparel.NullOrEmpty()) return false;
if (pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(ModBodyPartGroupDefOf.GenitalsBPG)) &&
pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Legs)) == false)
{ return CurrentThoughtState(pawn); }
if (pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(ModBodyPartGroupDefOf.ChestBPG)) &&
pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso)) == false)
{ return CurrentThoughtState(pawn); }
return ThoughtState.Inactive;
}
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using Verse;
using RimWorld;
namespace Privacy_Please
{
public static class DebugMode
{
public static void Message(string text)
{
if (BasicSettings.debugMode)
{ Log.Message("[DEBUG] " + text); }
}
}
}

View File

@ -0,0 +1,41 @@
using Verse;
using RimWorld;
using AlienRace;
namespace Privacy_Please
{
[DefOf]
public static class ModBodyPartGroupDefOf
{
public static BodyPartGroupDef GenitalsBPG;
public static BodyPartGroupDef AnusBPG;
public static BodyPartGroupDef ChestBPG;
}
[DefOf]
public static class ModThoughtDefOf
{
public static ThoughtDef SeenHavingSex;
public static ThoughtDef SeenHavingSexExhibitionist;
public static ThoughtDef SeenMasturbating;
public static ThoughtDef SeenMasturbatingExhibitionist;
public static ThoughtDef SawSex;
public static ThoughtDef SawSexVoyeur;
public static ThoughtDef SawMasturbation;
public static ThoughtDef SawMasturbationVoyeur;
public static ThoughtDef CaughtCheating;
}
[DefOf]
public static class ModPreceptDefOf
{
public static PreceptDef Exhibitionism_Acceptable;
public static PreceptDef Exhibitionism_Approved;
}
[DefOf]
public static class ModFleckDefOf
{
public static FleckDef Eye;
}
}

View File

@ -0,0 +1,303 @@
using System.Collections.Generic;
using System.Linq;
using Verse;
using Verse.AI;
using Verse.AI.Group;
using RimWorld;
using rjw;
using UnityEngine;
namespace Privacy_Please
{
public static class SexInteractionUtility
{
public static bool PawnCaughtLovinByWitness(Pawn pawn, Pawn witness)
{
if (witness == null ||
pawn == witness ||
(pawn.IsMasturbating() == false && pawn.IsHavingSex() == false) ||
witness.UnworriedAboutHumanSex() == false ||
witness.CanSee(pawn) == false)
{ return false; }
List<Pawn> sexParticipants = pawn.GetAllSexParticipants();
bool witnessIsApproachingSexParticipant = witness.jobs.curDriver is JobDriver_SexBaseInitiator && sexParticipants.Contains((witness.jobs.curDriver as JobDriver_SexBaseInitiator).Partner);
if (sexParticipants.Contains(witness) || witnessIsApproachingSexParticipant)
{ return false; }
return true;
}
public static bool PawnIsCheatingOnPartner(Pawn pawn, Pawn partner)
{
List<Pawn> spouses = pawn.GetSpouses(false);
if (BasicSettings.worryAboutInfidelity == false ||
partner.IsLoverOfOther(pawn) == false ||
pawn.HasTrait("Polygamous") ||
partner.HasTrait("Polygamous") ||
partner.IsMasturbating() ||
partner.IsHavingSex() == false ||
partner.GetSexPartner()?.Dead == true ||
partner.GetSexPartner()?.IsAnimal() == true ||
partner.GetAllSexParticipants().Contains(pawn) ||
(spouses.NullOrEmpty() == false && partner.GetAllSexParticipants().Any(x => spouses.Contains(x))))
{ return false; }
return true;
}
public static bool SexParticipantsIncludesACheatingPartner(Pawn pawn, List<Pawn> participants)
{
foreach (Pawn participant in participants)
{
if (PawnIsCheatingOnPartner(pawn, participant))
{ return true; }
}
return false;
}
public static bool CouldInvitePasserbyForSex(Pawn passerby, List<Pawn> participants)
{
if (passerby == null ||
participants.Contains(passerby) ||
passerby.UnworriedAboutHumanSex() == false ||
participants.All(x => x.CanSee(passerby) == false))
{ return false; }
if (participants.Count > 2 ||
participants.Any(x => x.IsForbidden(passerby) || x.HostileTo(passerby) || PawnIsCheatingOnPartner(x, passerby)) ||
CasualSex_Helper.CanHaveSex(passerby) == false ||
xxx.IsTargetPawnOkay(passerby) == false)
{ return false; }
if (passerby.MentalState != null ||
passerby.jobs.curDriver is JobDriver_Flee ||
passerby.jobs.curDriver is JobDriver_AttackMelee ||
passerby.jobs.curDriver is JobDriver_Vomit)
{ return false; }
if (SexUtility.ReadyForHookup(passerby) &&
(passerby?.jobs?.curJob == null || (passerby.jobs.curJob.playerForced == false && CasualSex_Helper.quickieAllowedJobs.Contains(passerby.jobs.curJob.def))) &&
participants.Any(x => SexAppraiser.would_fuck(x, passerby) > 0.1f && SexAppraiser.would_fuck(passerby, x) > 0.1f) &&
participants.All(x => SexAppraiser.would_fuck(x, passerby, false, false, true) > 0.1f && SexAppraiser.would_fuck(passerby, x, false, false, true) > 0.1f))
{
return true;
}
return false;
}
public static ThoughtDef GetThoughtsAboutSexAct(Pawn pawn, JobDriver_Sex jobDriver, out Precept precept)
{
ThoughtDef thoughtDef = null;
precept = null;
if (pawn == null || jobDriver == null) return null;
if (BasicSettings.slavesIgnoreSex && (pawn.IsPrisoner || pawn.IsSlave)) return null;
if (BasicSettings.otherFactionsIgnoreSex && pawn.Faction.IsPlayer == false) return null;
bool sexIsNecro = jobDriver.Partner != null && jobDriver.Partner.Dead;
bool sexIsBeastial = jobDriver.Partner != null && jobDriver.Partner.RaceProps.Animal;
bool sexIsRape = sexIsBeastial == false && sexIsNecro == false &&
(jobDriver is JobDriver_Rape || jobDriver is JobDriver_RapeEnemy || jobDriver is JobDriver_SexBaseRecieverRaped);
bool sexIsSlaveRape = sexIsRape && (jobDriver.Partner.IsPrisoner || jobDriver.Partner.IsSlave);
bool sexIsXeno = jobDriver.Partner != null && jobDriver.Partner.def.defName != jobDriver.pawn.def.defName;
bool isXenophobe = pawn.HasTrait("Xenophobia") && pawn.story.traits.DegreeOfTrait(DefDatabase<TraitDef>.GetNamedSilentFail("Xenophobia")) > 0;
bool isXenophile = pawn.HasTrait("Xenophobia") && pawn.story.traits.DegreeOfTrait(DefDatabase<TraitDef>.GetNamedSilentFail("Xenophobia")) < 0;
bool sexIsSolo = jobDriver.pawn.IsMasturbating();
bool sexIsIncest = jobDriver.Partner != null && jobDriver.pawn.GetRelations(jobDriver.Partner).Any(x => x.familyByBloodRelation);
if (BasicSettings.worryAboutNecro && sexIsNecro && xxx.is_necrophiliac(pawn) == false)
{
thoughtDef = xxx.is_necrophiliac(pawn) ? DefDatabase<ThoughtDef>.GetNamedSilentFail("SawNecrophilia_Honorable") :
pawn.HasPreceptForIssue("Necrophilia", out precept) ? DefDatabase<ThoughtDef>.GetNamedSilentFail("Saw" + precept.def.defName) :
DefDatabase<ThoughtDef>.GetNamedSilentFail("SawNecrophilia_Abhorrent");
}
else if (BasicSettings.worryAboutBeastiality && sexIsBeastial)
{
thoughtDef = xxx.is_zoophile(pawn) ? DefDatabase<ThoughtDef>.GetNamedSilentFail("SawBeastility_Honorable") :
pawn.HasPreceptForIssue("Beastility", out precept) ? DefDatabase<ThoughtDef>.GetNamedSilentFail("Saw" + precept.def.defName) :
DefDatabase<ThoughtDef>.GetNamedSilentFail("SawBeastility_Abhorrent");
}
else if (BasicSettings.worryAboutRape && BasicSettings.ignoreSlaveRape == false && sexIsSlaveRape)
{
thoughtDef = xxx.is_rapist(pawn) ? DefDatabase<ThoughtDef>.GetNamedSilentFail("SawRape_Honorable") :
pawn.HasPreceptForIssue("Rape", out precept) ? DefDatabase<ThoughtDef>.GetNamedSilentFail("Saw" + precept.def.defName) :
DefDatabase<ThoughtDef>.GetNamedSilentFail("SawRape_Abhorrent");
}
else if (BasicSettings.worryAboutRape && sexIsRape)
{
thoughtDef = xxx.is_rapist(pawn) ? DefDatabase<ThoughtDef>.GetNamedSilentFail("SawRape_Honorable") :
pawn.HasPreceptForIssue("Rape", out precept) ? DefDatabase<ThoughtDef>.GetNamedSilentFail("Saw" + precept.def.defName) :
DefDatabase<ThoughtDef>.GetNamedSilentFail("SawRape_Abhorrent");
}
else if (BasicSettings.worryAboutXeno && sexIsXeno)
{
thoughtDef = isXenophobe ? DefDatabase<ThoughtDef>.GetNamedSilentFail("SawHAR_AlienDating_Prohibited") :
isXenophile ? DefDatabase<ThoughtDef>.GetNamedSilentFail("SawHAR_AlienDating_Honorable") :
pawn.HasPreceptForIssue("HAR_AlienDating", out precept) ? DefDatabase<ThoughtDef>.GetNamedSilentFail("Saw" + precept.def.defName) :
DefDatabase<ThoughtDef>.GetNamedSilentFail("SawHAR_AlienDating_Acceptable");
}
else if (BasicSettings.worryAboutMasturbation && sexIsSolo)
{
thoughtDef = pawn.HasPreceptForIssue("Masturbation", out precept) ? DefDatabase<ThoughtDef>.GetNamedSilentFail("Saw" + precept.def.defName) :
DefDatabase<ThoughtDef>.GetNamedSilentFail("SawMasturbation_Disapproved");
}
else if (BasicSettings.worryAboutIncest && sexIsIncest)
{
}
DebugMode.Message("Sex job is: " + jobDriver + " Issue is: " + (precept?.def?.issue?.defName).ToStringSafe() + " Opinion is: " + (precept?.def?.defName).ToStringSafe() + " Thought is: " + (thoughtDef?.defName).ToStringSafe());
return thoughtDef;
}
public static bool InvitePasserbyForSex(Pawn pawn, Pawn witness, out bool brokeTaboo)
{
brokeTaboo = false;
bool witnessJoiningSex = Random.value < BasicSettings.chanceForOtherToJoinInSex && CouldInvitePasserbyForSex(witness, pawn.GetAllSexParticipants());
// Exit clauses
if (witness.UnworriedAboutHumanSex() == true)
{ return false; }
// Get basic thoughts
ThoughtDef pawnThoughtDef = BasicSettings.needPrivacy ? ModThoughtDefOf.SeenHavingSex : null;
ThoughtDef witnessThoughtDef = BasicSettings.needPrivacy ? ModThoughtDefOf.SawSex : null;
// Exhibitionist pawn (overrides needPrivacy)
if (xxx.has_quirk(pawn, "Exhibitionist") || pawn?.ideo?.Ideo.HasPrecept(ModPreceptDefOf.Exhibitionism_Approved) == true)
{ pawnThoughtDef = ModThoughtDefOf.SeenHavingSexExhibitionist; }
// Voyeuristic witness (overrides needPrivacy)
if (xxx.has_quirk(witness, "Voyeur"))
{ witnessThoughtDef = ModThoughtDefOf.SawSexVoyeur; }
// Mediating cirumstances
bool sexIsRitual = pawn.GetLord() != null && pawn.GetLord().LordJob is LordJob_Ritual && witness?.Ideo == pawn?.Ideo;
bool sexIsParty = pawn.GetLord() != null && pawn.GetLord().LordJob is LordJob_Joinable_Party;
bool pawnIsVictim = pawn.CurJob.def == xxx.gettin_raped || pawn.Dead;
bool mitigatingCirumstances = sexIsRitual || sexIsParty || pawnIsVictim;
bool pawnIsCheating = mitigatingCirumstances == false && PawnIsCheatingOnPartner(pawn, witness);
// Override thoughts if pawn is a victim
if (pawnIsVictim)
{
pawnThoughtDef = null;
witnessThoughtDef = null;
}
// Add thought if pawn is cheating
else if (pawnIsCheating)
{
if (pawn.needs.mood.thoughts.memories.GetFirstMemoryOfDef(ModThoughtDefOf.CaughtCheating) == null)
{ pawn.needs.mood.thoughts.memories.TryGainMemory(ModThoughtDefOf.CaughtCheating, witness); }
if (witness.needs.mood.thoughts.memories.GetFirstMemoryOfDef(ThoughtDefOf.CheatedOnMe) == null)
{ witness.needs.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.CheatedOnMe, pawn); }
witnessJoiningSex = false;
}
// Determine if there are any issues with the sex event and the witness' morals
ThoughtDef newWitnessThoughtDef = GetThoughtsAboutSexAct(witness, pawn.jobs.curDriver as JobDriver_Sex, out Precept precept);
// Update their thoughts if there are no migitating circumstances or the thought provides a positive morale boost larger than the original
if (newWitnessThoughtDef != null && (mitigatingCirumstances == false || (newWitnessThoughtDef.stages[0].baseMoodEffect > 0 && newWitnessThoughtDef.stages[0].baseMoodEffect > witnessThoughtDef.stages[0].baseMoodEffect)))
{ witnessThoughtDef = newWitnessThoughtDef; }
// Apply thoughts to witness
if (witnessThoughtDef != null)
{
witness.needs.mood.thoughts.memories.TryGainMemory(witnessThoughtDef, pawn, precept);
if (witnessThoughtDef.stages[0].baseMoodEffect < 0)
{ witness?.TryGetComp<CompPawnThoughtData>()?.TryToExclaim(); }
witnessJoiningSex = witnessThoughtDef.hediff != null ? false : witnessJoiningSex;
brokeTaboo = witnessThoughtDef.hediff != null;
// Trigger extreme reactions
if (witnessThoughtDef?.hediff != null)
{ TriggerReactionInWitness(witness, pawn, witnessThoughtDef.hediff.defName); }
else if (pawnIsCheating)
{ TriggerReactionInWitness(witness, pawn, "Indignant"); }
}
// Apply thoughts to pawn
if (pawnThoughtDef != null)
{
pawn.needs.mood.thoughts.memories.TryGainMemory(pawnThoughtDef, witness, null);
if (pawnThoughtDef.stages[0].baseMoodEffect < 0)
{ pawn?.TryGetComp<CompPawnThoughtData>()?.TryToExclaim(); }
}
return witnessJoiningSex;
}
public static void TriggerReactionInWitness(Pawn witness, Pawn otherPawn, string reaction)
{
if (BasicSettings.majorTabooCanStartFights == false || reaction.NullOrEmpty())
{ return; }
if (witness.MentalState != null ||
witness.jobs.curDriver is JobDriver_Flee ||
witness.jobs.curDriver is JobDriver_AttackMelee ||
witness.jobs.curDriver is JobDriver_Vomit)
{ return; }
// Panicked
if (reaction == "Panicked" || (reaction == "Indignant" && Random.value <= 0.5f))
{
// Fight
if (otherPawn.RaceProps.Humanlike && witness.RaceProps.Humanlike && witness.DislikesViolence() == false && (Random.value <= 0.2f || witness.EnjoysViolence()) && witness.HostileTo(otherPawn) == false && InteractionUtility.TryGetRandomVerbForSocialFight(witness, out Verb verbToUse))
{ witness.interactions.StartSocialFight(otherPawn, "MessageSocialFight"); }
// Flight
else
{
Job job = JobMaker.MakeJob(JobDefOf.FleeAndCower, CellFinderLoose.GetFleeDest(witness, new List<Thing>() { otherPawn }, 24f), otherPawn);
witness.jobs.EndCurrentJob(JobCondition.InterruptForced, false, false);
witness.jobs.StartJob(job);
}
}
// Vomit
else if (reaction == "Nauseated")
{
Job jobVomit = JobMaker.MakeJob(JobDefOf.Vomit);
Job jobFlee = JobMaker.MakeJob(JobDefOf.FleeAndCower, CellFinderLoose.GetFleeDest(witness, new List<Thing>() { otherPawn }, 24f), otherPawn);
witness.jobs.EndCurrentJob(JobCondition.InterruptForced, false, false);
if (Random.value <= 0.2f)
{
witness.jobs.StartJob(jobVomit);
witness.jobs.jobQueue.EnqueueFirst(jobFlee);
}
else
{ witness.jobs.StartJob(jobFlee); }
}
// Indignant
else if (reaction == "Indignant")
{
witness.mindState.mentalStateHandler.TryStartMentalState(DefDatabase<MentalStateDef>.GetNamedSilentFail("TargetedInsultingSpree"), null, true, false, null, true, false, false);
(witness.mindState.mentalStateHandler.CurState as MentalState_TargetedInsultingSpree).target = otherPawn;
}
}
}
}

View File

@ -0,0 +1 @@
8263062e6a99f43c12969425daafb3f9676b8c24

View File

@ -0,0 +1,6 @@
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\privacy-please-abscon\1.4\Assemblies\Privacy-Please.dll
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\privacy-please-abscon\1.4\Assemblies\Privacy-Please.pdb
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\privacy-please-abscon\Source\obj\Debug\AbsCon_PrivacyPlease.csprojAssemblyReference.cache
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\privacy-please-abscon\Source\obj\Debug\AbsCon_PrivacyPlease.csproj.CoreCompileInputs.cache
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\privacy-please-abscon\Source\obj\Debug\Privacy-Please.dll
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\privacy-please-abscon\Source\obj\Debug\Privacy-Please.pdb

View File

@ -0,0 +1 @@
8263062e6a99f43c12969425daafb3f9676b8c24

View File

@ -0,0 +1,8 @@
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\privacy-please-abscon\Source\obj\Debug\Privacy-Please.csprojAssemblyReference.cache
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\privacy-please-abscon\Source\obj\Debug\Privacy-Please.csproj.CoreCompileInputs.cache
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\privacy-please-abscon\1.3\Assemblies\Privacy-Please.dll
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\privacy-please-abscon\1.3\Assemblies\Privacy-Please.pdb
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\privacy-please-abscon\Source\obj\Debug\Privacy-Please.dll
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\privacy-please-abscon\Source\obj\Debug\Privacy-Please.pdb
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\privacy-please-abscon\1.4\Assemblies\Privacy-Please.dll
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\privacy-please-abscon\1.4\Assemblies\Privacy-Please.pdb

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Textures/UI/Flecks/Eye.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB