This commit is contained in:
AbstractConcept 2023-02-04 01:13:57 -06:00
parent fcf187c7dd
commit 38ec4f86c1
68 changed files with 846 additions and 1934 deletions

Binary file not shown.

Binary file not shown.

View File

@ -4,7 +4,7 @@
<name>Rimworld-Animation Patch</name>
<author>AbstractConcept</author>
<supportedVersions>
<li>1.3</li>
<li>1.4</li>
</supportedVersions>
<packageId>abscon.rimworld.animations.patch</packageId>
<modDependencies>
@ -38,20 +38,20 @@
<li>OTYOTY.NudePatchForRimNudeWorld.UnofficialUpdate</li>
</loadAfter>
<description>
This started as a patch for RimWorld-Animation, but has since grown to patch RJW and RimNudeWorld as well
A patch for RimWorld Animations and RJW, adding some additional functions and tweaks
There's no real theme here. It just fixes a few things, changes some others, as well as making some additions!
This mod requires both RimWorld Animations and RJW to function - RimNudeWorld isn't required, but it is recommended
This mod requires RJW and RimWorld-Animation to function. RimNudeWorld isn't required, but is recommended. Let me know if you encounter any bugs
Here's a brief overview of whats included in this mod
Here's a brief overview of what's included in this mod
- 12 animations for casual sex
- 7 animations for solo masturbation
- 2 animations for group sex
- Animated hands for certain animations
- A need for privacy during sex
- Pawns will react differently to the different types of sex that they witness - their reaction depends on their trait and ideology
- A range of tweaks to how body parts are displayed, particularly when wearing different types of apparel
- The option to have pawns in varying states of dress during sex (ranging from fully nude to almost entirely clothed)
- Apparel can be masked so that the bottom halves of pawns are visible when not wearing pants
- The option to hide the names of pawns while they have sex
- Automatic position scaling, to improve animations involving alien races which are larger or smaller than normal
- A GUI for customizing how RimNude body parts should be displayed when wearing different types of apparel, as well as toggling what apparel should be worn while having sex
A full list of changes can be found in the main discussion thread on the forum
@ -60,8 +60,8 @@ Known issues
- If you plan to use this mod's apparel cropping feature and the Sized Apparel mod, you must turn off texture caching or graphical glitches will occur (this can be done by adding Vanilla Expanded Framework to your mod list and enabling its 'Disable Texture Caching' setting)
- Using Dubs Apparel Tweaks or the Show Hair mod may result in hair rendering over hats during animations
- To avoid certain graphical issues, Dubs Apparel Tweaks should be loaded before this mod while Babies and Children should be loaded after (if you choose to use them). This will mean that you will not be able to run this mod with Dubs Apparel Tweaks and Babies and Children running at the same time
- Using Speak Up and Dirty Talk results in warning messages being posted in the log. This does not seem to be causing problems in their function, however. This issue will be monitored
- This mod tweaks pretty much every animation involving humans, so it isn't currently compatible with the Tory's VoicePatch mod (unsupported animations will have no voices played)
- Using Speak Up and Dirty Talk results in warning messages being posted in the log, however, this does not seem to be causing any problems. This issue will be monitored
- This mod isn't compatible with Tory's VoicePatch mod
- This mod will result in graphical errors when using Pawnmorpher's 'Pawn scaling' setting
</description>
</ModMetaData>

View File

@ -1,135 +0,0 @@
Change log v 1.2.4
- Fix: Fixed an issue with body addons and portraits while pawns are sleeping
- Fix: Fixed an error which occurred when the RJW events mod was not installed
- Change: Added additional support for the Babies for Children mod. This means that you will need to place BnC below the patch in order for it to work correctly. It also means you can run BnC and Dubs apparel tweaks together now if you wish
Change log v 1.2.3
- Fix: Fixed a bug which would cause body parts to vanish while a pawn is in a biosculpter pod
- Fix: Fixed a bug which would cause body parts to show while sleeping in a bed
- Fix: Fixed a bug which where body parts would not be hidden after sex was finished
- Fix: Added additional safeguards to help prevent rare errors when equipping certain apparel and when closing the settings menu while in game
Change log v 1.2.2
- Fix: Fix for portraits appearing blank when using the 'crop apparel' feature
- Fix: Underwear counts as covering private parts when determining basic nudity
- Fix: A pawn won't think that they are being cheated on if the catch their partner having sex with an animal or corpse
- Fix: Animals, wild men, mechanoids and factions that are hostile to you no longer have opinions about witnessed sex
- Fix: Fixed an issue which was causing pawns attending orgies to get stuck
- Fix: Fixed an issue where some animations without an orgasm event included would result in an error occurring
- Fix: Pawns no longer have missing body parts while showering
- Fix: Penises no longer not show while wearing pants (unless a pawn is wearing nothing else)
- Change: Significant performance optimisations have been made. You can now host orgies involving 50 or more people. Disable animated hands to further improve performance
- Change: Individualized moodlets are now applied for witnessing different sex acts (currently supports rape, beastiality, xenophilia, necrophilia)
- Change: Pawns might run away and vomit up their lunch if they witness necrophilia
- Change: Pawns who witness a cheating partner or xenophilia might go on an insulting spree
- Addition: Added a setting that allows you toggle whether wearing underwear alone is sufficient to satisfy an ideological need for modesty
- Addition: Added moodlets for pawns that have their underwear showing. These moodlets can be toggled on or off in the settings
- Addition: Added a new threesome animation for one male and two females ('the sandwich')
Change log v 1.2.1
- Change: Optimisation of the body part rendering code - there should be much better frame rates now. Just avoid hosting orgies involving 50 or more people...
- Addition: Added option to the basic settings menu to toggle hair redrawing for portraits (helps make sure that body parts are properly covered by long hair)
Change log v 1.2.0
- Fix: Fixed bug where married pawns could be accused of cheating when having sex with another spouse
- Fix: Fixed bug where some animations would not result in an orgasm occuring when they should be occuring
- Fix: Fixed bug where animations would end too quickly when quick sex was enabled, leaving pawns to finish with the default animation provided by RJW
- Fix: Fixed bug where enlarged bellies where being rendered behind pawns
- Fix: Fixed a RJW bug which resulted in all clothing being worn when the prefered clothing level was set to headgear only
- Fix: Fixed issue which resulted in strangely moving body parts when using Yayo's Animations
- Fix: Fixed a layering issue for anuses when using OTY Nude
- Change: This mod must be loaded after the following mods (if you plan on using them) - RimNudeWorld, OTY Nude, Babies and Children
- Change: This mod now requires that you use RimWorld Animations v 1.2.8 or later
- Change: Sex animations have been increased across the board and now last about 35-40 seconds - quick animations will take about 20-25 seconds to finish
- Removal: Fix for eye implants and head wound placement has been removed (a fix for this bug is included in RimWorld Animations as of v 1.2.8)
- Addition: Added option to crop the bottoms of torso covering apparel (e.g., shirts) when not wearing pants - this feature is intended to be used alongside other mods that draw leg covering apparel on pawns (e.g., the Visible Pants mod). If you plan on using this feature and the Sized Apparel mod, you must turn off texture caching or graphical glitches will occur (this can be done by adding Vanilla Expanded Framework to your modlist and enabling its 'Disable Texture Caching' setting)
- Addition: Added a configuration menu which allows the user to customise apparel to either hide / reveal the groin, belly and / or breasts of pawns, plus an option to mark apparel as 'sex-wear' (these items of clothing will always be worn during sex animations)
- Addition: Added option to configure the amount of clothing that should be worn when having a quickie out of bed (pawns can be nude, wear headgear only, or be fully clothed)
- Addition: Individual items of clothing will be hidden if they cover a body part that is needed for a sex animation (e.g., pants will be removed for vaginal or anal sex, but not for oral) - this will not affect apparel marked as sex-wear
Change log v 1.1.1
- Fix: Fixed issue with the violation of corpses
- Fix: Fixed issue with xenophobes not reacting to xenophilic sex
- Fix: Fixed issue with not being able to toggle off reactions to cheating
- Change: Changed how the 'require privacy' toggle in the settings works - disabling this toggle now only stops pawns from feeling shame when being caught having / seeing non-taboo sex
- Removal: Removed unnecessary xpath patch which added a null pregnancy belly graphic to RimNudeWorld
- Addition: Added toggle to the settings which allows pawns to ignore indecent activities against prisoners and slaves
Change log v 1.1.0
- Addition: The reactions of pawns to encountering sex is now more nuanced. A pawn's reaction will now depend on 1) the sex act witnessed and 2) their traits and ideology (the Sexperience Ideology mod is recommended for this but is not required). Pawns can now have specific opinions on
- Rape
- Beastiality
- Necrophilia
- Xenophilia
Specific reactions can be individually toggled on/off. Work on this feature is on going - at the moment, these acts will either treated as a vanilla sex act, as taboo, or as a major taboo. More tailored thoughts are planned to be added
- Addition: Pawns can have extreme reactions to encountered sex acts. If a major taboo is witnessed the pawn will flee in horror, or may even start a fight the perpetrator! This feature can be toggled on/off
Change log v 1.0.5
- Fix: Missing text for the voyeur quirk has been fixed
- Change: Dubs Apparel Tweaks must now be loaded after this mod
- Removal: Test theesome animation removed
Change log v 1.0.4
- Fix: Fixed an issue when masturbating with a dildo
- Fix: Fixed an issue with masturbation animation selection
- Addition: Translation tags have been set up for the settings page - still only available in English however
Change log v 1.0.3
- Fix: fixed incompatibility issue with Vanilla Factions Expanded Ancients
- Fix: non-consensual / paid for sex acts won't be interrupted by people passing by anymore
Change log v 1.0.2
- Fix: fixed an issue with the animation anchors for sex activities outside of bed - pawns should not longer be placed oddly far apart or close together
- Fix: fixed an incompatibility issue with Dub's Apparel Tweaks
- Fix: fixed several body part layering issues for a number of alien races
- Fix: fixed an issue with the sex job driver failing for mechanoids
- Fix: sex animations should now only be played once for non-consensual / paid for sex acts
- Fix: a pawn's age is now considered when sending out an invitation to join in sex
- Fix: pawns won't worry about privacy or infidelity while taking part in a ritual
- Fix: fixed an issue where pawns invited to join a threesome were causing it to stop
Change log v 1.0.1
- Fix: Fixed body parts on animals not being rendered while this mod is active
- Fix: Fixed bug that lead to repeated mating with animals
- Addition: Added a toggle to the settings which will allow the player to choose whether pawns worry about infidelity
Change log v 1.0.0
- Fix: eye implants and head wounds should now line up correctly with a pawn's head during sex animations
- Fix: penis movement has been added back to sex animations (must be enabled under RimWorld-Animations settings)
- Fix: a number of body part layering issues have been fixed for RimNudeWorld
- Fix: the timing of orgasms should now sync up with how they are depicted in sex animations
- Fix: fixed some issues with sex overdrive, the sex override meter, and how sex animations play out
- Fix: fixed issue with animations continuing if a pawn transitions straight from one sex act to another
- Fix: when masturbating in their own bed, pawns will position themselves in their sleeping spot rather than the middle of the bed
- Fix: RimNudeWorld's belly graphics will not appear until a third of the way through a pregnancy and will now be hidden under apparel that covers the torso
- Change: if a pawn doesn't appear to be actively using their own genitals during a sex animation (e.g., giving someone else a handjob) then they will not reach orgasm
- Change: genitals now count as being covered / protected by leg-covering apparel instead than torso-covering apparel
- Change: the scantier underwear from Underwhere and S16's extension mods now only cover / protect the genitals and chest instead of the legs and torso
- Change: added some variety to the log entries / job descriptions for different sex acts
- Change: if sex overdrive is turned on, the next sex act to take place will be chosen at random
- Change: pawns now have a chance to start a second sex animation after the first one ends, depending on how horny the participants still are
- Change: tweaked the lengths of the original animations by c0ffee - animations will now generally finish within 25-30 seconds (~ 40 mins of in game time)
- Addition: included animations for the following sex acts (updated versions of the ones I originally posted on the forum)
- butterfly
- breast job
- hand job
- fisting
- rimming
- sixty-nine
- fingering
- cunnilingus while standing
- reverse cowgirl
- face sitting
- foot job
- mutual masturbation
- Addition: included some new animations!
- kissing / making out (based on an animation originally made by Tory)
- solo masturbation while standing up and lying in a bed (includes separate animations for playing with genitals, breasts, anus and bed humping)
- a threesome with one male and two females ('the cowgirls')
- Addition: certain animations have had animated hands added to them - these include hand jobs, fisting, fingering, solo masturbation and mutual masturbation (can be toggled on or off). This feature requires RimNudeWorld to be active
- Addition: pawn / sleep slot name tags can be hidden during animations so they don't cover up the action (can be toggled on or off)
- Addition: the distance between pawns during sex animations can be set to be scaled depending on the body sizes of the pawns involved (can be toggled on or off)
- Addition: clothing that is not worn during an animation will now appear in a nearby pile on the floor (can be toggled on or off)
- Addition: pawns now have a desire for privacy while having sex / masturbating, and they'll be unhappy and stop what they are doing if they get caught in the act (can be toggled on or off). Exhibitionists won't mind though
- Addition: threesomes can triggered via two new ways - 1) when a pawn sets off to bed their partner a passerby might be invited to follow, and 2) if a pawn stumbles upon a couple having sex, they may just be invited to join in (the chance of a threesome occuring can be configured). In both cases, those involved must have a good opinion of each other and the invited pawn mustn't be doing an important job at the time
- Addition: a voyeur quirk has been added - these pawns get a rush out of catching people in the act

View File

@ -0,0 +1,2 @@
Change log v 2.0.0
- Initial re-release (for RimWorld 1.4)

View File

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

View File

@ -7,6 +7,7 @@
<sexTypes>
<li>Vaginal</li>
<li>Anal</li>
<li>DoublePenetration</li>
</sexTypes>
<interactionDefTypes>
<li>AnalSex</li>

View File

@ -1014,7 +1014,7 @@
</li>
<li>
<tickDuration>30</tickDuration>
<bodyAngle></bodyAngle>
<bodyAngle>0</bodyAngle>
<headAngle>0</headAngle>
<bodyOffsetX>0</bodyOffsetX>
<bodyOffsetZ>-0.23</bodyOffsetZ>
@ -1759,7 +1759,7 @@
<bodyAngle>0</bodyAngle>
<bodyOffsetX>0.2</bodyOffsetX>
<bodyOffsetZ>0.390</bodyOffsetZ>
<bodyFacing>0.2</bodyFacing>
<bodyFacing>0</bodyFacing>
<headFacing>3</headFacing>
<headBob>-0.003</headBob>
</li>
@ -2647,7 +2647,7 @@
<li>
<soundEffect>Suck</soundEffect>
<tickDuration>59</tickDuration>
<bodyAngle></bodyAngle>
<bodyAngle>0</bodyAngle>
<headAngle>6</headAngle>
<bodyOffsetX>0</bodyOffsetX>
<bodyOffsetZ>-0.33</bodyOffsetZ>
@ -2679,7 +2679,7 @@
<li>
<soundEffect>Suck</soundEffect>
<tickDuration>59</tickDuration>
<bodyAngle></bodyAngle>
<bodyAngle>0</bodyAngle>
<headAngle>6</headAngle>
<bodyOffsetX>0</bodyOffsetX>
<bodyOffsetZ>-0.33</bodyOffsetZ>
@ -3268,7 +3268,7 @@
<li>
<soundEffect>Suck</soundEffect>
<tickDuration>59</tickDuration>
<bodyAngle></bodyAngle>
<bodyAngle>0</bodyAngle>
<headAngle>6</headAngle>
<bodyOffsetX>0</bodyOffsetX>
<bodyOffsetZ>-0.33</bodyOffsetZ>

View File

@ -3,14 +3,14 @@
<Rimworld_Animations_Patch.HandAnimationDef>
<defName>Handjob_HandDef</defName>
<animationDefName>Handjob</animationDefName>
<animationDef>Handjob</animationDef>
<handAnimationData>
<li>
<stageID>0</stageID>
<actorID>1</actorID>
<touchingActorID>0</touchingActorID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS</motion>
<cycleTime>30</cycleTime>
</li>
<li>
@ -18,7 +18,7 @@
<actorID>1</actorID>
<touchingActorID>0</touchingActorID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS</motion>
<cycleTime>15</cycleTime>
</li>
<li>
@ -26,7 +26,7 @@
<actorID>1</actorID>
<touchingActorID>0</touchingActorID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS</motion>
<cycleTime>15</cycleTime>
</li>
</handAnimationData>
@ -34,14 +34,14 @@
<Rimworld_Animations_Patch.HandAnimationDef>
<defName>Fisting_HandDef</defName>
<animationDefName>Fisting</animationDefName>
<animationDef>Fisting</animationDef>
<handAnimationData>
<li>
<stageID>0</stageID>
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDownShort_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS</motion>
<cycleTime>60</cycleTime>
</li>
<li>
@ -49,7 +49,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDownShort_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS</motion>
<cycleTime>15</cycleTime>
</li>
<li>
@ -57,7 +57,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDownShort_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS</motion>
<cycleTime>15</cycleTime>
</li>
@ -66,7 +66,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDownShort_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS</motion>
<cycleTime>60</cycleTime>
</li>
<li>
@ -74,7 +74,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDownShort_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS</motion>
<cycleTime>15</cycleTime>
</li>
<li>
@ -82,7 +82,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDownShort_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS</motion>
<cycleTime>15</cycleTime>
</li>
</handAnimationData>
@ -90,14 +90,14 @@
<Rimworld_Animations_Patch.HandAnimationDef>
<defName>Fingering_HandDef</defName>
<animationDefName>Fingering</animationDefName>
<animationDef>Fingering</animationDef>
<handAnimationData>
<li>
<stageID>0</stageID>
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDownShort_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS</motion>
<cycleTime>60</cycleTime>
</li>
<li>
@ -105,7 +105,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDownShort_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS</motion>
<cycleTime>15</cycleTime>
</li>
<li>
@ -113,7 +113,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDownShort_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS</motion>
<cycleTime>15</cycleTime>
</li>
</handAnimationData>

View File

@ -3,24 +3,24 @@
<Rimworld_Animations_Patch.HandAnimationDef>
<defName>MasturbationWithPenis_Standing_HandDef</defName>
<animationDefName>MasturbationWithPenis_Standing</animationDefName>
<animationDef>MasturbationWithPenis_Standing</animationDef>
<handAnimationData>
<li>
<stageID>0</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingEW</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW</motion>
<cycleTime>31</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingEW</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW</motion>
<cycleTime>16</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingEW</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW</motion>
<cycleTime>16</cycleTime>
</li>
</handAnimationData>
@ -28,24 +28,24 @@
<Rimworld_Animations_Patch.HandAnimationDef>
<defName>MasturbationWithPenis_InBed_HandDef</defName>
<animationDefName>MasturbationWithPenis_InBed</animationDefName>
<animationDef>MasturbationWithPenis_InBed</animationDef>
<handAnimationData>
<li>
<stageID>0</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS</motion>
<cycleTime>31</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS</motion>
<cycleTime>16</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS</motion>
<cycleTime>16</cycleTime>
</li>
</handAnimationData>
@ -53,24 +53,24 @@
<Rimworld_Animations_Patch.HandAnimationDef>
<defName>MasturbationWithVagina_Standing_HandDef</defName>
<animationDefName>MasturbationWithVagina_Standing</animationDefName>
<animationDef>MasturbationWithVagina_Standing</animationDef>
<handAnimationData>
<li>
<stageID>0</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingEW</motion>
<cycleTime>31</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingEW</motion>
<cycleTime>16</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingEW</motion>
<cycleTime>16</cycleTime>
</li>
</handAnimationData>
@ -78,24 +78,24 @@
<Rimworld_Animations_Patch.HandAnimationDef>
<defName>MasturbationWithVagina_InBed_HandDef</defName>
<animationDefName>MasturbationWithVagina_InBed</animationDefName>
<animationDef>MasturbationWithVagina_InBed</animationDef>
<handAnimationData>
<li>
<stageID>0</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>62</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>32</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>32</cycleTime>
</li>
</handAnimationData>
@ -103,43 +103,43 @@
<Rimworld_Animations_Patch.HandAnimationDef>
<defName>MasturbationWithAnus_Standing_HandDef</defName>
<animationDefName>MasturbationWithAnus_Standing</animationDefName>
<animationDef>MasturbationWithAnus_Standing</animationDef>
<handAnimationData>
<li>
<stageID>0</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>31</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>16</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>16</cycleTime>
</li>
<li>
<stageID>0</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>31</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>16</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>16</cycleTime>
</li>
</handAnimationData>
@ -147,43 +147,43 @@
<Rimworld_Animations_Patch.HandAnimationDef>
<defName>MasturbationWithAnus_InBed_HandDef</defName>
<animationDefName>MasturbationWithAnus_InBed</animationDefName>
<animationDef>MasturbationWithAnus_InBed</animationDef>
<handAnimationData>
<li>
<stageID>0</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>31</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>16</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>16</cycleTime>
</li>
<li>
<stageID>0</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>31</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>16</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>16</cycleTime>
</li>
</handAnimationData>
@ -191,39 +191,39 @@
<Rimworld_Animations_Patch.HandAnimationDef>
<defName>MasturbationWithBreasts_Standing_HandDef</defName>
<animationDefName>MasturbationWithBreasts_Standing</animationDefName>
<animationDef>MasturbationWithBreasts_Standing</animationDef>
<handAnimationData>
<li>
<stageID>0</stageID>
<targetBodyPart>Breasts</targetBodyPart>
<bodySide>left</bodySide>
<motion>Motion_RubBreasts_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubBreasts_FacingEW</motion>
<cycleTime>93</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Breasts</targetBodyPart>
<bodySide>left</bodySide>
<motion>Motion_RubBreasts_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubBreasts_FacingEW</motion>
<cycleTime>64</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingEW</motion>
<cycleTime>32</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Breasts</targetBodyPart>
<bodySide>left</bodySide>
<motion>Motion_RubBreasts_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubBreasts_FacingEW</motion>
<cycleTime>64</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingEW</motion>
<cycleTime>32</cycleTime>
</li>
</handAnimationData>
@ -231,13 +231,13 @@
<Rimworld_Animations_Patch.HandAnimationDef>
<defName>MasturbationWithBreasts_InBed_HandDef</defName>
<animationDefName>MasturbationWithBreasts_InBed</animationDefName>
<animationDef>MasturbationWithBreasts_InBed</animationDef>
<handAnimationData>
<li>
<stageID>0</stageID>
<targetBodyPart>Breasts</targetBodyPart>
<bodySide>left</bodySide>
<motion>Motion_RubBreasts_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubBreasts_FacingNS</motion>
<cycleTime>93</cycleTime>
</li>
<li>
@ -245,33 +245,33 @@
<targetBodyPart>Breasts</targetBodyPart>
<bodySide>right</bodySide>
<mirror>true</mirror>
<motion>Motion_RubBreasts_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubBreasts_FacingNS</motion>
<cycleTime>93</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Breasts</targetBodyPart>
<bodySide>left</bodySide>
<motion>Motion_RubBreasts_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubBreasts_FacingNS</motion>
<cycleTime>64</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>32</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Breasts</targetBodyPart>
<bodySide>left</bodySide>
<motion>Motion_RubBreasts_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubBreasts_FacingNS</motion>
<cycleTime>64</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingNS</motion>
<cycleTime>32</cycleTime>
</li>
</handAnimationData>
@ -279,39 +279,39 @@
<Rimworld_Animations_Patch.HandAnimationDef>
<defName>MasturbationWithBreastsPlusPenis_Standing_HandDef</defName>
<animationDefName>MasturbationWithBreastsPlusPenis_Standing</animationDefName>
<animationDef>MasturbationWithBreastsPlusPenis_Standing</animationDef>
<handAnimationData>
<li>
<stageID>0</stageID>
<targetBodyPart>Breasts</targetBodyPart>
<bodySide>left</bodySide>
<motion>Motion_RubBreasts_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubBreasts_FacingEW</motion>
<cycleTime>93</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Breasts</targetBodyPart>
<bodySide>left</bodySide>
<motion>Motion_RubBreasts_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubBreasts_FacingEW</motion>
<cycleTime>64</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingEW</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW</motion>
<cycleTime>16</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Breasts</targetBodyPart>
<bodySide>left</bodySide>
<motion>Motion_RubBreasts_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubBreasts_FacingEW</motion>
<cycleTime>64</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingEW</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW</motion>
<cycleTime>16</cycleTime>
</li>
</handAnimationData>
@ -319,13 +319,13 @@
<Rimworld_Animations_Patch.HandAnimationDef>
<defName>MasturbationWithBreastsPlusPenis_InBed_HandDef</defName>
<animationDefName>MasturbationWithBreastsPlusPenis_InBed</animationDefName>
<animationDef>MasturbationWithBreastsPlusPenis_InBed</animationDef>
<handAnimationData>
<li>
<stageID>0</stageID>
<targetBodyPart>Breasts</targetBodyPart>
<bodySide>left</bodySide>
<motion>Motion_RubBreasts_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubBreasts_FacingNS</motion>
<cycleTime>93</cycleTime>
</li>
<li>
@ -333,33 +333,33 @@
<targetBodyPart>Breasts</targetBodyPart>
<bodySide>right</bodySide>
<mirror>true</mirror>
<motion>Motion_RubBreasts_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubBreasts_FacingNS</motion>
<cycleTime>93</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Breasts</targetBodyPart>
<bodySide>left</bodySide>
<motion>Motion_RubBreasts_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubBreasts_FacingNS</motion>
<cycleTime>64</cycleTime>
</li>
<li>
<stageID>1</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS</motion>
<cycleTime>16</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Breasts</targetBodyPart>
<bodySide>left</bodySide>
<motion>Motion_RubBreasts_FacingNS</motion>
<motion>Rimworld_Animations_Patch.RubBreasts_FacingNS</motion>
<cycleTime>64</cycleTime>
</li>
<li>
<stageID>2</stageID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingNS</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS</motion>
<cycleTime>16</cycleTime>
</li>
</handAnimationData>
@ -367,7 +367,7 @@
<Rimworld_Animations_Patch.HandAnimationDef>
<defName>MutualMasturbation_HandDef</defName>
<animationDefName>MutualMasturbation</animationDefName>
<animationDef>MutualMasturbation</animationDef>
<handAnimationData>
<!-- Actor 0 (which has penis) -->
@ -376,7 +376,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingEW</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW</motion>
<cycleTime>25</cycleTime>
</li>
<li>
@ -384,7 +384,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingEW</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW</motion>
<cycleTime>30</cycleTime>
</li>
<li>
@ -392,7 +392,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingEW</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW</motion>
<cycleTime>15</cycleTime>
</li>
<li>
@ -400,7 +400,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingEW</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW</motion>
<cycleTime>15</cycleTime>
</li>
@ -410,7 +410,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingEW</motion>
<cycleTime>25</cycleTime>
</li>
<li>
@ -418,7 +418,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingEW</motion>
<cycleTime>30</cycleTime>
</li>
<li>
@ -426,7 +426,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingEW</motion>
<cycleTime>15</cycleTime>
</li>
<li>
@ -434,7 +434,7 @@
<actorID>0</actorID>
<touchingActorID>1</touchingActorID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingEW</motion>
<cycleTime>15</cycleTime>
</li>
@ -444,7 +444,7 @@
<actorID>1</actorID>
<touchingActorID>0</touchingActorID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingEW</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW</motion>
<cycleTime>25</cycleTime>
</li>
<li>
@ -452,7 +452,7 @@
<actorID>1</actorID>
<touchingActorID>0</touchingActorID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingEW</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW</motion>
<cycleTime>30</cycleTime>
</li>
<li>
@ -460,7 +460,7 @@
<actorID>1</actorID>
<touchingActorID>0</touchingActorID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingEW</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW</motion>
<cycleTime>15</cycleTime>
</li>
<li>
@ -468,7 +468,7 @@
<actorID>1</actorID>
<touchingActorID>0</touchingActorID>
<targetBodyPart>Penis</targetBodyPart>
<motion>Motion_StrokeGenitalsUpAndDown_FacingEW</motion>
<motion>Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW</motion>
<cycleTime>15</cycleTime>
</li>
@ -478,7 +478,7 @@
<actorID>1</actorID>
<touchingActorID>0</touchingActorID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingEW</motion>
<cycleTime>25</cycleTime>
</li>
<li>
@ -486,7 +486,7 @@
<actorID>1</actorID>
<touchingActorID>0</touchingActorID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingEW</motion>
<cycleTime>30</cycleTime>
</li>
<li>
@ -494,7 +494,7 @@
<actorID>1</actorID>
<touchingActorID>0</touchingActorID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingEW</motion>
<cycleTime>15</cycleTime>
</li>
<li>
@ -502,7 +502,7 @@
<actorID>1</actorID>
<touchingActorID>0</touchingActorID>
<targetBodyPart>Vagina</targetBodyPart>
<motion>Motion_RubGenitals_FacingEW</motion>
<motion>Rimworld_Animations_Patch.RubGenitals_FacingEW</motion>
<cycleTime>15</cycleTime>
</li>
</handAnimationData>

View File

@ -1,53 +0,0 @@
<?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>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<JobDef>
<defName>JoinInSex</defName>
<driverClass>Rimworld_Animations_Patch.JobDriver_JoinInSex</driverClass>
<reportString>joining in on some fun.</reportString>
<casualInterruptible>false</casualInterruptible>
</JobDef>
</Defs>

View File

@ -1,196 +0,0 @@
<?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>
</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>
</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>
</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>
</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

@ -1,90 +0,0 @@
<?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>
</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

@ -1,87 +0,0 @@
<?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>
</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

@ -1,87 +0,0 @@
<?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>
</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

@ -1,77 +0,0 @@
<?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>
</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

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<ThoughtDef>
<defName>ExposeUnderwear</defName>
<workerClass>Rimworld_Animations_Patch.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>exhibitionist flashing underwear</label>
<description>People can see my underwear. It's a bit thrilling, to be honest!</description>
<baseMoodEffect>1</baseMoodEffect>
</li>
</stages>
</ThoughtDef>
</Defs>

View File

@ -7,22 +7,30 @@
<rimworld_animation_patch_general>General Options</rimworld_animation_patch_general>
<need_privacy> People require privacy for lovin'</need_privacy>
<need_privacy_desc>If someone encounters another engaged in lovin' related activities, both individuals will feel embarrassed, depending on their traits and ideology.</need_privacy_desc>
<need_privacy> People have opinions about having sex in front of others</need_privacy>
<need_privacy_desc>Their reaction will depend on their Exhibitionist precept and whether the Exhibitionist or Voyeur quirk. Embarrassed colonist will stop any lovin' related activities they are doing.\n\nUnconventional sex acts and those that break taboo may provoke a stronger reaction. People will turn a blind eye to these transgressions, however, if they take place during a ritual or party.</need_privacy_desc>
<worry_about_infidelity> People will react if they encounter their partner cheating</worry_about_infidelity>
<worry_about_infidelity_desc>Their reaction depends on their traits and ideology. This is not considered committing taboo by default.</worry_about_infidelity_desc>
<worry_about_infidelity_desc>Their reaction will depend on their Lovin' precept, whether they have the Polygamous trait, and whether the copulating couple are married. Cheating is considered a major taboo by default.</worry_about_infidelity_desc>
<worry_about_beastiality> People will react to beastiality</worry_about_beastiality>
<worry_about_beastiality_desc>Their reaction depends on their traits and ideology. This is considered committing a major taboo by default.</worry_about_beastiality_desc>
<worry_about_beastiality_desc>Their reaction will depend on their Bestiality precept (Sexperience - Ideology) and whether they are a Zoophile. Beastiality is considered a major taboo by default.</worry_about_beastiality_desc>
<worry_about_rape> People will react to rape</worry_about_rape>
<worry_about_rape_desc>Their reaction depends on their traits and ideology. This is considered committing a major taboo by default.</worry_about_rape_desc>
<ignore_slave_rape> People will ignore rape if the victim is a prisoner or slave</ignore_slave_rape>
<worry_about_rape_desc>Their reaction will depend on their Rape precept (Sexperience - Ideology) and whether they have the Rapist trait. Rape is considered a major taboo by default.</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 depends on their traits and ideology. This is considered committing a major taboo by default.</worry_about_necro_desc>
<worry_about_necro_desc>Their reaction will depend on their Necrophilia precept (Sexperience - Ideology) and whether they have the Necrophile trait. Necrophilia is considered a major taboo by default.</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 depends on their traits and ideology. This is not considered committing taboo by default.</worry_about_xeno_desc>
<worry_about_xeno_desc>Their reaction will depend on their Alien Dating precept (Humanoid Alien Races) and whether they are Xenophile or Xenophobe traits. Xenophilia is acceptable by default.</worry_about_xeno_desc>
<worry_about_masturbation> People will react to necrophilia</worry_about_masturbation>
<worry_about_masturbation_desc>Their reaction will depend on their Necrophilia precept (Sexperience - Ideology) and whether they have the Necrophile trait. Necrophilia is considered a major taboo by default.</worry_about_masturbation_desc>
<worry_about_incest> People will react to incest</worry_about_incest>
<worry_about_incest_desc>Their reaction will depend on their Incest precept (Sexperience - Ideology). Incest is disapproved of by default.</worry_about_incest_desc>
<major_taboo_can_start_fights> Witnessing a major taboo will result in an extreme reaction</major_taboo_can_start_fights>
<major_taboo_can_start_fights_desc>Individuals who witness something that seriously upsets them will cause them to flee, or even possibly attack the offender.</major_taboo_can_start_fights_desc>
<slaves_ignore_sex> Prisoners and slaves ignore sex</slaves_ignore_sex>
<slaves_ignore_sex_desc>Prisoners and slaves have learnt it is better to simply ignore any sexual acts occurring around them.</slaves_ignore_sex_desc>
<other_factions_ignore_sex> People belong to other factions will ignore sex</other_factions_ignore_sex>
<other_factions_ignore_sex_desc>The other factions will turn a blind eye to any sexual acts occurring around them.</other_factions_ignore_sex_desc>
<chance_for_other_to_join_in_sex> People who are lovin' have a chance to invite passersby 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 just maximises the chance of an invitation being made. All individuals involved must be attracted to / have a good opinion of each other, and the activity must not violate their traits or ideology. Set this value to zero to prevent these events from happening.</chance_for_other_to_join_in_sex_desc>
<hide_names_for_sex> Hide names when getting some lovin'</hide_names_for_sex>
@ -34,11 +42,13 @@
<autoscale_delta_pos> Auto-scale animation offsets based on body size</autoscale_delta_pos>
<autoscale_delta_pos_desc>Turning this setting on may help when using alien races which are much larger or smaller than regular humans.</autoscale_delta_pos_desc>
<show_hands> Add animated hands to animations</show_hands>
<show_hands_desc>Requires RimNudeWorld. This feature can be performance intense. If you have large colonies (50+ colonist), you may wish to turn this off.</show_hands_desc>
<redraw_hair> Redraw hair in pawn portraits</redraw_hair>
<redraw_hair_desc>Helps prevent bodyparts from rendering over long hair in portraits. Disable this feature if you find two sets of hair appearing on your pawns or hair is being rendered over headgear.</redraw_hair_desc>
<use_legacy_animation_system> Patch RimWorld Animation System</use_legacy_animation_system>
<use_legacy_animation_system_desc>Having this setting turned on patches C0ffee's RimWorld Animation framework with tweaks and visual improvements. This patching can cause conflict with other mods, however. If you are running into graphical issues with animation, try turning this setting off.</use_legacy_animation_system_desc>
<show_hands> Add animated hands to animations</show_hands>
<show_hands_desc>Requires RimNudeWorld. This feature can be performance intense. If you have large colonies (50+ colonist), you may wish to turn this off.</show_hands_desc>
<rimworld_animation_patch_clothing>Clothing options</rimworld_animation_patch_clothing>
<crop_apparel> Crop the bottoms of worn shirts, tank tops, etc. when not wearing pants or a skirt</crop_apparel>
<crop_apparel_desc>Only applies to torso covering apparel that lies directly on the skin and that does not cover the legs. Best used with mods that draw pants graphics, like the Visible Pants mod.\n\nRequires that the game to be reset when toggled off.</crop_apparel_desc>

View File

@ -1,32 +0,0 @@
<?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

@ -1,23 +0,0 @@
<?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

@ -19,7 +19,7 @@
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\1.3\Assemblies\</OutputPath>
<OutputPath>..\1.4\Assemblies\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
@ -42,7 +42,7 @@
<Private>False</Private>
</Reference>
<Reference Include="AlienRace">
<HintPath>..\..\..\..\..\workshop\content\294100\839005762\1.3\Assemblies\AlienRace.dll</HintPath>
<HintPath>..\..\..\..\..\workshop\content\294100\839005762\1.4\Assemblies\AlienRace.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Assembly-CSharp">
@ -66,34 +66,25 @@
<Private>False</Private>
</Reference>
<Reference Include="RimNudeWorld">
<HintPath>..\..\rimnude-unofficial-master\1.3 Assembly\Assemblies\RimNudeWorld.dll</HintPath>
<HintPath>..\..\rimnude-unofficial-master\Assembly Folders\1.4 Assembly\Assemblies\RimNudeWorld.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Rimworld-Animations, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\rimworld-animations-master\1.3\Assemblies\Rimworld-Animations.dll</HintPath>
<Reference Include="Rimworld-Animations">
<HintPath>..\..\rimworld-animations-master\1.4\Assemblies\Rimworld-Animations.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="RJW, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\rjw-master\1.3\Assemblies\RJW.dll</HintPath>
<Reference Include="RJW">
<HintPath>..\..\RJW\1.4\Assemblies\RJW.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="RJW-Events">
<HintPath>..\..\rjw-events-master\1.3\Assemblies\RJW-Events.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="RJW-ToysAndMasturbation">
<HintPath>..\..\rjw-toys-and-masturbation-master\Assemblies\RJW-ToysAndMasturbation.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="RJWSexperience.Ideology">
<HintPath>..\..\rjw-sexperience-ideology-master\1.3\Assemblies\RJWSexperience.Ideology.dll</HintPath>
<HintPath>..\..\rjw-events-master\1.4\Assemblies\RJW-Events.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xml" />
<Reference Include="UnityEngine">
<HintPath>..\..\..\RimWorldWin64_Data\Managed\UnityEngine.dll</HintPath>
<Private>False</Private>
@ -117,20 +108,32 @@
<Compile Include="Scripts\Comps\CompProperties_ApparelVisibility.cs" />
<Compile Include="Scripts\Comps\CompApparelVisibility.cs" />
<Compile Include="Scripts\Comps\CompPawnSexData.cs" />
<Compile Include="Scripts\Defs\ActorAddon.cs" />
<Compile Include="Scripts\Defs\ActorAddonDef.cs" />
<Compile Include="Scripts\Defs\ActorAnimationData.cs" />
<Compile Include="Scripts\Defs\AddonKeyframe.cs" />
<Compile Include="Scripts\Defs\BodyAddonData.cs" />
<Compile Include="Scripts\Defs\HandAnimationDef.cs" />
<Compile Include="Scripts\Extensions\StringExtension.cs" />
<Compile Include="Scripts\HandMotions\HandMotion.cs" />
<Compile Include="Scripts\HandMotions\RubBreasts_FacingEW.cs" />
<Compile Include="Scripts\HandMotions\RubGenitals_FacingEW.cs" />
<Compile Include="Scripts\HandMotions\StrokeGenitalsUpAndDown_FacingEW.cs" />
<Compile Include="Scripts\HandMotions\RubGenitals_FacingNS.cs" />
<Compile Include="Scripts\HandMotions\RubBreasts_FacingNS.cs" />
<Compile Include="Scripts\HandMotions\StrokeGenitalsUpAndDown_FacingNS.cs" />
<Compile Include="Scripts\HandMotions\StrokeGenitalsUpAndDownShort_FacingNS.cs" />
<Compile Include="Scripts\Extensions\PawnAnimationClipExt.cs" />
<Compile Include="Scripts\Defs\RimNudeData.cs" />
<Compile Include="Scripts\Enums.cs" />
<Compile Include="Scripts\Extensions\PawnKeyframeExt.cs" />
<Compile Include="Scripts\Patches\HarmonyPatch_ApparelGraphicRecordGetter.cs" />
<Compile Include="Scripts\Patches\HarmonyPatch_BabiesAndChildren.cs" />
<Compile Include="Scripts\Patches\HarmonyPatch_Pawn_ApparelTracker.cs" />
<Compile Include="Scripts\Patches\HarmonyPatch_DrawGUIOverlay.cs" />
<Compile Include="Scripts\Patches\HarmonyPatch_JobDriver.cs" />
<Compile Include="Scripts\Patches\HarmonyPatch_RJWEvents.cs" />
<Compile Include="Scripts\Patches\HarmonyPatch_ThoughtWorkers.cs" />
<Compile Include="Scripts\Settings\ApparelSettings.cs" />
<Compile Include="Scripts\ThoughtWorkers\ThoughtWorker_ExposedUnderwear.cs" />
<Compile Include="Scripts\Utilities\ApparelAnimationUtility.cs" />
<Compile Include="Scripts\Utilities\ApparelSettingsUtility.cs" />
<Compile Include="Scripts\Utilities\DebugMode.cs" />
@ -149,7 +152,6 @@
<Compile Include="Scripts\Settings\BasicSettings.cs" />
<Compile Include="Scripts\Utilities\GraphicMaskingUtility.cs" />
<Compile Include="Scripts\Utilities\MathUtility.cs" />
<Compile Include="Scripts\Utilities\SexInteractionUtility.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -32,6 +32,7 @@ namespace Rimworld_Animations_Patch
Scribe_Values.Look(ref cellPosition, "cellPosition", default);
}
// Used to find a place to have clothes thrown onto the floor
public void GenerateFloorPosition(IntVec3 apparelCell, Vector2 apparelOffset = default)
{
Pawn pawn = apparel.Wearer;

View File

@ -16,12 +16,13 @@ namespace Rimworld_Animations_Patch
public Graphic handGraphic = null;
public List<BodyPartRecord> hands = new List<BodyPartRecord>();
public float sizeOfPenis = 0f;
public float sizeOfBreasts = 0f;
public Dictionary<AlienPartGenerator.BodyAddon, BodyAddonData> bodyAddonData = new Dictionary<AlienPartGenerator.BodyAddon, BodyAddonData>();
public Dictionary<AlienPartGenerator.BodyAddon, BodyAddonData> bodyAddonDataPortraits = new Dictionary<AlienPartGenerator.BodyAddon, BodyAddonData>();
private Pawn pawn;
private int lastExclaimationTick = -1;
private int exclaimationCoolDown = 90;
public BodyAddonData GetBodyAddonData(AlienPartGenerator.BodyAddon bodyAddon, bool isPortrait)
{
@ -62,25 +63,22 @@ namespace Rimworld_Animations_Patch
{ kvp.Value?.UpdateVisibility(); }
}
public void UpdateHands()
public void UpdateBodyPartCountAndSize()
{
hands = pawn?.health?.hediffSet?.GetNotMissingParts()?.Where(x => x.def.tags.Contains(BodyPartTagDefOf.ManipulationLimbCore))?.ToList();
Hediff hediffPenis = pawn?.health?.hediffSet?.hediffs?.FirstOrDefault(x => x.def.defName.Contains("penis") == true || x.def.defName.Contains("Penis"));
sizeOfPenis = hediffPenis != null ? hediffPenis.Severity : 0f;
Hediff hediffBreasts = pawn?.health?.hediffSet?.hediffs?.FirstOrDefault(x => x.def.defName.Contains("breasts") == true || x.def.defName.Contains("Breasts") == true);
sizeOfBreasts = hediffBreasts != null ? hediffBreasts.Severity : 0f;
}
public int GetNumberOfHands()
{
if (hands.NullOrEmpty()) return 0;
if (hands.Any() == false) return 0;
return hands.Count;
}
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,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
namespace Rimworld_Animations_Patch
{
public class ActorAddon
{
// Data to/from animationDef
public string addonName;
public int? anchoringActor;
public string anchorName;
public string layer = "Pawn";
public GraphicData graphicData;
public bool? render;
// Data helper functions
public string AddonName
{
get { return addonName; }
set { addonName = value; }
}
public int AnchoringActor
{
get { return anchoringActor.HasValue ? anchoringActor.Value : 0; }
set { anchoringActor = value; }
}
public string AnchorName
{
get { return anchorName; }
set { anchorName = value; }
}
public string Layer
{
get { return layer; }
set { layer = value; }
}
public GraphicData GraphicData
{
get { return graphicData; }
set { graphicData = value; }
}
public bool Render
{
get { return render == true; }
set { render = value; }
}
// Simple curves
public SimpleCurve PosX = new SimpleCurve();
public SimpleCurve PosZ = new SimpleCurve();
public SimpleCurve Rotation = new SimpleCurve();
// Constructors
public ActorAddon() { }
public ActorAddon(ActorAddonDef actorAddonDef)
{
this.GraphicData = actorAddonDef.graphicData;
}
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
namespace Rimworld_Animations_Patch
{
public class ActorAddonDef : Def
{
public float scale = 1f;
public GraphicData graphicData;
}
}

View File

@ -16,14 +16,16 @@ namespace Rimworld_Animations_Patch
public int currentStage = 0;
public int stageTicks = 0;
public Rot4 actorFacing = Rot4.South;
public bool isMirrored;
public ActorAnimationData(AnimationDef animationDef, int actorID, int currentStage, int stageTicks, Rot4 actorFacing)
public ActorAnimationData(AnimationDef animationDef, int actorID, int currentStage, int stageTicks, Rot4 actorFacing, bool isMirrored)
{
this.animationDef = animationDef;
this.actorID = actorID;
this.currentStage = currentStage;
this.stageTicks = stageTicks;
this.actorFacing = actorFacing;
this.isMirrored = isMirrored;
}
}
}

View File

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Rimworld_Animations_Patch
{
public class AddonKeyframe
{
// Data to/from animationDef
public string addonName;
public float? posX;
public float? posZ;
public float? rotation;
// Data serialization control
public bool ShouldSerializeposX() { return posX.HasValue; }
public bool ShouldSerializeposZ() { return posZ.HasValue; }
public bool ShouldSerializerotation() { return rotation.HasValue; }
// Data helper functions
public string AddonName
{
get { return addonName; }
set { addonName = value; }
}
public float PosX
{
get { return posX.HasValue ? posX.Value : 0f; }
set { posX = value; }
}
public float PosZ
{
get { return posZ.HasValue ? posZ.Value : 0f; }
set { posZ = value; }
}
public float Rotation
{
get { return rotation.HasValue ? rotation.Value : 0f; }
set { rotation = value; }
}
// Constructors
public AddonKeyframe() { }
public AddonKeyframe(string addonName)
{
this.AddonName = addonName;
}
}
}

View File

@ -16,7 +16,7 @@ namespace Rimworld_Animations_Patch
public BodyPartRecord bodyPartRecord;
public List<Vector3> bodyAddonOffsets = new List<Vector3>();
public bool alignsWithHead = false;
private Pawn pawn;
private string bodyType;
private PawnRenderFlags renderFlags;
@ -31,7 +31,7 @@ namespace Rimworld_Animations_Patch
if (isPortrait)
{ renderFlags |= PawnRenderFlags.Portrait; }
bodyPartRecord = pawn.def?.race?.body?.AllParts?.FirstOrDefault(x => x.def.defName == bodyAddon?.bodyPart || x.customLabel == bodyAddon?.bodyPart);
bodyPartRecord = pawn.def?.race?.body?.AllParts?.FirstOrDefault(x => x.def == bodyAddon?.bodyPart);
alignsWithHead = bodyAddon.alignWithHead || (bodyPartRecord != null && bodyPartRecord.IsInGroup(BodyPartGroupDefOf.FullHead));
GenerateOffsets();
@ -43,7 +43,7 @@ namespace Rimworld_Animations_Patch
bodyType = pawn.story.bodyType.defName;
bodyAddonOffsets.Clear();
int bodyAddonIndex = (pawn.def as ThingDef_AlienRace).alienRace.generalSettings.alienPartGenerator.bodyAddons.ToList().IndexOf(bodyAddon);
int bodyAddonIndex = (pawn.def as ThingDef_AlienRace).alienRace.generalSettings.alienPartGenerator.bodyAddons.IndexOf(bodyAddon);
AlienPartGenerator.AlienComp alienComp = pawn.GetComp<AlienPartGenerator.AlienComp>();
Graphic addonGraphic = alienComp.addonGraphics[bodyAddonIndex];
@ -53,20 +53,20 @@ namespace Rimworld_Animations_Patch
// Get basic offset for body addon
AlienPartGenerator.RotationOffset defaultOffsets = bodyAddon.defaultOffsets.GetOffset(apparentRotation);
Vector3 bodyTypeOffset = (defaultOffsets != null) ? defaultOffsets.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, alienComp.crownType) : Vector3.zero;
Vector3 bodyTypeOffset = (defaultOffsets != null) ? defaultOffsets.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, pawn.story.headType) : Vector3.zero;
AlienPartGenerator.RotationOffset rotationOffsets = bodyAddon.offsets.GetOffset(apparentRotation);
Vector3 bodyAddonOffset = bodyTypeOffset + ((rotationOffsets != null) ? rotationOffsets.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, alienComp.crownType) : Vector3.zero);
Vector3 bodyAddonOffset = bodyTypeOffset + ((rotationOffsets != null) ? rotationOffsets.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, pawn.story.headType) : Vector3.zero);
// Offset private parts so that they render over tattoos but under apparel (rendering under tatoos looks weird)
if (bodyAddon.bodyPart == "Genitals" || bodyAddon.bodyPart == "Chest" || bodyAddon.bodyPart == "Anus" || addonGraphic.path.ToLower().Contains("belly"))
if (bodyAddon.bodyPart == PatchBodyPartDefOf.Genitals || bodyAddon.bodyPart == PatchBodyPartDefOf.Chest || bodyAddon.bodyPart == PatchBodyPartDefOf.Anus || addonGraphic.path.Contains("belly") || addonGraphic.path.Contains("Belly"))
{
bodyAddonOffset.y = (bodyAddonOffset.y + 0.40f) / 1000f + 0.012f;
// Erected penises should be drawn over apparel
if (pawn.RaceProps.Humanlike &&
addonGraphic.path.ToLower().Contains("penis") &&
addonGraphic.path.ToLower().Contains("flaccid") == false &&
(addonGraphic.path.Contains("penis") || addonGraphic.path.Contains("Penis")) &&
(addonGraphic.path.Contains("flaccid") == false && addonGraphic.path.Contains("Flaccid") == false) &&
apparentRotation == Rot4.South)
{ bodyAddonOffset.y += 0.010f; }
}
@ -121,7 +121,7 @@ namespace Rimworld_Animations_Patch
if (renderFlags.FlagSet(PawnRenderFlags.Portrait) == false && (pawn.GetPosture() == PawnPosture.LayingOnGroundNormal || pawn.GetPosture() == PawnPosture.LayingOnGroundFaceUp) && bodyAddon.drawnOnGround == false)
{ return false; }
if (bodyAddon.backstoryRequirement.NullOrEmpty() == false && pawn.story?.AllBackstories?.Any((Backstory x) => x.identifier == bodyAddon.backstoryRequirement) == false)
if (bodyAddon.backstoryRequirement != null && pawn.story?.AllBackstories?.Any((BackstoryDef x) => x == bodyAddon.backstoryRequirement) == false)
{ return false; }
if (bodyAddon.drawnDesiccated == false && pawn.Corpse?.GetRotStage() == RotStage.Dessicated)
@ -130,7 +130,7 @@ namespace Rimworld_Animations_Patch
if (pawn.gender == Gender.Female && bodyAddon.drawForFemale == false || pawn.gender == Gender.Male && bodyAddon.drawForMale == false)
{ return false; }
if (bodyAddon.bodyTypeRequirement.NullOrEmpty() == false && pawn.story?.bodyType.ToString() != bodyAddon.bodyTypeRequirement)
if (bodyAddon.bodyTypeRequirement != null && pawn.story?.bodyType != bodyAddon.bodyTypeRequirement)
{ return false; }
return true;
@ -139,7 +139,6 @@ namespace Rimworld_Animations_Patch
public void UpdateVisibility()
{
if (pawn == null || bodyAddon == null || bodyPartRecord == null) return;
canDraw = true;
if (pawn.health?.hediffSet?.GetNotMissingParts()?.Contains(bodyPartRecord) == false)
@ -156,15 +155,18 @@ namespace Rimworld_Animations_Patch
if (comp.isBeingWorn == false) continue;
if (bodyAddon.bodyPart == "Genitals" || bodyAddon.bodyPart == "Anus" || bodyAddon.bodyPart == "Chest" || bodyAddon.hediffGraphics?.Any(x => x.path.NullOrEmpty() == false && x.path.ToLower().Contains("belly")) == true)
if (bodyAddon.bodyPart == PatchBodyPartDefOf.Genitals ||
bodyAddon.bodyPart == PatchBodyPartDefOf.Anus ||
bodyAddon.bodyPart == PatchBodyPartDefOf.Chest ||
bodyAddon.hediffGraphics?.Any(x => x.path.NullOrEmpty() == false && (x.path.Contains("belly") || x.path.Contains("Belly"))) == true)
{
if ((bodyAddon.bodyPart == "Genitals" || bodyAddon.bodyPart == "Anus") && comp.coversGroin)
if ((bodyAddon.bodyPart == PatchBodyPartDefOf.Genitals || bodyAddon.bodyPart == PatchBodyPartDefOf.Anus) && comp.coversGroin)
{ canDraw = false; return; };
if (bodyAddon.bodyPart == "Chest" && comp.coversChest)
if (bodyAddon.bodyPart == PatchBodyPartDefOf.Chest && comp.coversChest)
{ canDraw = false; return; };
if (bodyAddon.hediffGraphics?.Any(x => x.path.NullOrEmpty() == false && x.path.ToLower().Contains("belly")) == true && comp.coversBelly)
if (bodyAddon.hediffGraphics?.Any(x => x.path.NullOrEmpty() == false && (x.path.Contains("belly") || x.path.Contains("Belly"))) == true && comp.coversBelly)
{ canDraw = false; return; }
}

View File

@ -1,6 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using Verse;
using Rimworld_Animations;
@ -8,8 +12,7 @@ namespace Rimworld_Animations_Patch
{
public class HandAnimationDef : Def
{
public string animationDefName;
public AnimationDef animationDef;
public List<HandAnimationData> handAnimationData = new List<HandAnimationData>();
}
@ -24,5 +27,23 @@ namespace Rimworld_Animations_Patch
public string motion;
public int cycleTime = 0;
public bool mirror = false;
private HandMotion _motion;
public HandMotion Motion
{
get
{
if (_motion == null)
{
if (Type.GetType(motion) == null)
{ DebugMode.Message("ERROR: Hand motion " + motion + " does not exist!"); return null; }
_motion = (HandMotion)Activator.CreateInstance(Type.GetType(motion));
}
return _motion;
}
}
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Rimworld_Animations;
namespace Rimworld_Animations_Patch
{
public class PawnAnimationClipExt : PawnAnimationClip
{
public List<ActorAddon> addons = new List<ActorAddon>();
public override void buildSimpleCurves()
{
base.buildSimpleCurves();
int keyframePosition = 0;
for (int i = 0; i < keyframes.Count; i++)
{
PawnKeyframeExt keyframe = keyframes[i] as PawnKeyframeExt;
if (keyframe.atTick.HasValue)
{
foreach (ActorAddon addon in addons)
{
if (keyframe.addonKeyframes.Any(x => x.AddonName == addon.AddonName) == false)
{ keyframe.addonKeyframes.Add(new AddonKeyframe(addon.AddonName)); }
addon.PosX.Add((float)keyframe.atTick / (float)duration, keyframe.GetAddonKeyframe(addon.AddonName).PosX, true);
addon.PosZ.Add((float)keyframe.atTick / (float)duration, keyframe.GetAddonKeyframe(addon.AddonName).PosZ, true);
addon.Rotation.Add((float)keyframe.atTick / (float)duration, keyframe.GetAddonKeyframe(addon.AddonName).Rotation, true);
}
}
else
{
foreach (ActorAddon addon in addons)
{
if (keyframe.addonKeyframes.Any(x => x.AddonName == addon.AddonName) == false)
{ keyframe.addonKeyframes.Add(new AddonKeyframe(addon.AddonName)); }
addon.PosX.Add((float)keyframePosition / (float)duration, keyframe.GetAddonKeyframe(addon.AddonName).PosX, true);
addon.PosZ.Add((float)keyframePosition / (float)duration, keyframe.GetAddonKeyframe(addon.AddonName).PosZ, true);
addon.Rotation.Add((float)keyframePosition / (float)duration, keyframe.GetAddonKeyframe(addon.AddonName).Rotation, true);
}
keyframePosition += keyframe.tickDuration;
}
}
}
}
}

View File

@ -85,14 +85,14 @@ namespace Rimworld_Animations_Patch
if (pawn.GetSexReceiver() != null)
{
List<Pawn> partners = (pawn.GetSexReceiver().jobs.curDriver as JobDriver_SexBaseReciever).parteners.ToList();
List<Pawn> partners = (pawn.GetSexReceiver().jobs.curDriver as JobDriver_SexBaseReciever).parteners;
if (partners != null)
{
foreach (Pawn partner in partners)
{
if (partner != null)
{ participants = partners; }
{ participants = partners; break; }
}
}
}
@ -111,77 +111,6 @@ namespace Rimworld_Animations_Patch
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.AnimalOrWildMan() || pawn.RaceProps.Humanlike == false)
{ return true; }
if (pawn.IsHavingSex() == false && pawn.IsMasturbating() == false)
{ return true; }
if (pawn.GetLord() != null && pawn.GetLord().LordJob is LordJob_Ritual)
{ return true; }
if (pawn.GetLord() != null && pawn.GetLord().LordJob is LordJob_Joinable_Party)
{ return true; }
bool hasPrivacy = true;
bool isExhibitionist = xxx.has_quirk(pawn, "Exhibitionist");
pawn.IsInBed(out Building bed);
foreach (Thing thing in GenRadial.RadialDistinctThingsAround(pawn.Position, pawn.Map, radius, true))
{
Pawn witness = thing as Pawn;
// Caught having sex
if (SexInteractionUtility.PawnCaughtLovinByWitness(pawn, witness))
{
SexInteractionUtility.ResolveThoughtsForWhenSexIsWitnessed(pawn, witness, out bool witnessJoiningSex);
// Try to invite intruder to join in
if (witnessJoiningSex)
{
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);
}
}
// The invitation failed
else
{ hasPrivacy = false; }
}
}
return hasPrivacy || isExhibitionist || BasicSettings.needPrivacy == false;
}
public static ActorAnimationData GetAnimationData(this Pawn pawn)
{
if (pawn.TryGetComp<CompBodyAnimator>() == null) return null;
@ -192,82 +121,9 @@ namespace Rimworld_Animations_Patch
int currentStage = (int)AccessTools.Field(typeof(CompBodyAnimator), "curStage").GetValue(pawn.TryGetComp<CompBodyAnimator>());
int stageTicks = (int)AccessTools.Field(typeof(CompBodyAnimator), "stageTicks").GetValue(pawn.TryGetComp<CompBodyAnimator>());
Rot4 actorFacing = (Rot4)AccessTools.Field(typeof(CompBodyAnimator), "bodyFacing").GetValue(pawn.TryGetComp<CompBodyAnimator>());
bool isMirrored = pawn.TryGetComp<CompBodyAnimator>().Mirror;
return new ActorAnimationData(animationDef, actorID, currentStage, stageTicks, actorFacing);
}
public static List<BodyPartRecord> GetHands(this Pawn pawn)
{
return pawn.health.hediffSet.GetNotMissingParts().Where(x => x.def == PatchBodyPartDefOf.Hand)?.ToList();
}
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);
return new ActorAnimationData(animationDef, actorID, currentStage, stageTicks, actorFacing, isMirrored);
}
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Rimworld_Animations;
namespace Rimworld_Animations_Patch
{
public class PawnKeyframeExt : PawnKeyframe
{
public List<AddonKeyframe> addonKeyframes;
public AddonKeyframe GetAddonKeyframe(string addonName)
{
return addonKeyframes.FirstOrDefault(x => x.AddonName == addonName);
}
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Rimworld_Animations_Patch
{
public static class StringExtension
{
public static bool Contains(this string fullString, string subString, StringComparison comparer)
{
return fullString?.IndexOf(subString, comparer) >= 0;
}
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Verse;
namespace Rimworld_Animations_Patch
{
public abstract class HandMotion
{
public abstract Vector3 GetHandPosition(Pawn pawn, HandAnimationData handAnimationData, float baseAngle);
}
}

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Globalization;
using System.IO;
using System.Xml;
using UnityEngine;
using Verse;
namespace Rimworld_Animations_Patch
{
public class RubBreasts_FacingEW : HandMotion
{
public override Vector3 GetHandPosition(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float a = ((float)data.stageTicks % (float)handAnimationData.cycleTime) / (float)handAnimationData.cycleTime * 360f;
float m = (data.actorFacing == Rot4.West ? 1f : -1f) * (handAnimationData.mirror ? -1f : 1f);
float size = HandAnimationUtility.GetGenitalSize(pawn, "breasts");
handPosition.x = (Mathf.Sin(a / 180f * Mathf.PI) * 0.005f - size * 0.25f) * m;
handPosition.z = Mathf.Cos(a / 180f * Mathf.PI) * 0.015f - size * 0.125f;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Globalization;
using System.IO;
using System.Xml;
using UnityEngine;
using Verse;
using Rimworld_Animations;
namespace Rimworld_Animations_Patch
{
public class RubBreasts_FacingNS : HandMotion
{
public override Vector3 GetHandPosition(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float a = ((float)data.stageTicks % (float)handAnimationData.cycleTime) / (float)handAnimationData.cycleTime * 360f;
float m = (data.actorFacing == Rot4.North ? -1f : 1f) * (handAnimationData.mirror ? -1f : 1f) * (data.isMirrored ? -1f : 1f);
float size = HandAnimationUtility.GetGenitalSize(pawn, "breasts");
handPosition.x = (Mathf.Sin(a / 180f * Mathf.PI) * 0.05f * size - size * 0.25f) * m;
handPosition.z = Mathf.Cos(a / 180f * Mathf.PI) * 0.015f - size * 0.125f;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Globalization;
using System.IO;
using System.Xml;
using UnityEngine;
using Verse;
using Rimworld_Animations;
namespace Rimworld_Animations_Patch
{
public class RubGenitals_FacingEW : HandMotion
{
public override Vector3 GetHandPosition(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float a = ((float)data.stageTicks % (float)handAnimationData.cycleTime) / (float)handAnimationData.cycleTime * 360f;
float m = (data.actorFacing == Rot4.West ? 1f : -1f) * (handAnimationData.mirror ? -1f : 1f);
handPosition.x = (Mathf.Sin(a / 180f * Mathf.PI) * 0.005f - 0.05f) * m;
handPosition.z = Mathf.Cos(a / 180f * Mathf.PI) * 0.015f;
//handPosition.y = -0.1f;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
}
}

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Globalization;
using System.IO;
using System.Xml;
using UnityEngine;
using Verse;
using Rimworld_Animations;
namespace Rimworld_Animations_Patch
{
public class RubGenitals_FacingNS : HandMotion
{
public override Vector3 GetHandPosition(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float a = ((float)data.stageTicks % (float)handAnimationData.cycleTime) / (float)handAnimationData.cycleTime * 360f;
float m = (data.actorFacing == Rot4.North ? 1f : -1f) * (handAnimationData.mirror ? -1f : 1f) * (data.isMirrored ? -1f : 1f);
handPosition.x = (Mathf.Sin(a / 180f * Mathf.PI) * 0.05f - 0.025f) * m;
handPosition.z = Mathf.Cos(a / 180f * Mathf.PI) * 0.015f + 0.03f;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Globalization;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using UnityEngine;
using Verse;
using RimWorld;
namespace Rimworld_Animations_Patch
{
public class StrokeGenitalsUpAndDownShort_FacingNS : HandMotion
{
public override Vector3 GetHandPosition(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float p = (Mathf.PingPong(data.stageTicks, handAnimationData.cycleTime) / handAnimationData.cycleTime);
float length = 0.035f;
handPosition.x = 0;
handPosition.z = length * p;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
}
}

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Globalization;
using System.IO;
using System.Xml;
using UnityEngine;
using Verse;
namespace Rimworld_Animations_Patch
{
public class StrokeGenitalsUpAndDown_FacingEW : HandMotion
{
public override Vector3 GetHandPosition(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float p = Mathf.PingPong(data.stageTicks, handAnimationData.cycleTime) / handAnimationData.cycleTime;
float size = HandAnimationUtility.GetGenitalSize(pawn, handAnimationData.targetBodyPart) * 0.2f;
float m = (data.actorFacing == Rot4.West ? -1f : 1f) * (handAnimationData.mirror ? -1f : 1f);
handPosition.x = Mathf.Sin(m * (baseAngle + 45f) / 180f * Mathf.PI) * size * p;
handPosition.z = Mathf.Cos(m * (baseAngle + 45f) / 180f * Mathf.PI) * size * p;
return handPosition;
}
}
}

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Globalization;
using System.IO;
using System.Xml;
using UnityEngine;
using Verse;
namespace Rimworld_Animations_Patch
{
public class Motion_StrokeGenitalsUpAndDown_FacingNS : HandMotion
{
public override Vector3 GetHandPosition(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float p = (Mathf.PingPong(data.stageTicks, handAnimationData.cycleTime) / handAnimationData.cycleTime);
float size = HandAnimationUtility.GetGenitalSize(pawn, handAnimationData.targetBodyPart) * 0.2f;
float m = (data.actorFacing == Rot4.North ? -1f : 1f) * (handAnimationData.mirror ? -1f : 1f) * (data.isMirrored ? -1f : 1f);
handPosition.x = 0.025f * m;
handPosition.z = size * p;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
}
}

View File

@ -29,7 +29,7 @@ namespace Rimworld_Animations_Patch
}))();
}
catch (TypeLoadException ex) { }
catch (TypeLoadException) { }
}
public static bool Prefix_ShouldNotDrawAddonsForPawn(ref bool __result, Pawn pawn)

View File

@ -23,9 +23,9 @@ namespace Rimworld_Animations_Patch
LocalTargetInfo b = jobdriver.job.targetB.IsValid ? jobdriver.job.targetB : jobdriver.job.targetQueueB.FirstValid();
LocalTargetInfo targetC = jobdriver.job.targetC;
__result = JobUtility.GetResolvedJobReport(jobdriver.pawn.GetAnimationData().animationDef.label, a, b, targetC);
//__result = JobUtility.GetResolvedJobReport(jobdriver.pawn.GetAnimationData().animationDef.label, a, b, targetC);
return false;
//return false;
}
return true;

View File

@ -17,11 +17,6 @@ namespace Rimworld_Animations_Patch
{
Harmony harmony = new Harmony("Rimworld_Animations_Patch");
harmony.PatchAll(Assembly.GetExecutingAssembly());
Quirk voyeur = new Quirk("Voyeur", "VoyeurQuirk", null, null);
if (Quirk.All.Contains(voyeur) == false)
{ Quirk.All.Add(voyeur); }
}
}
}

View File

@ -12,67 +12,11 @@ using rjw;
namespace Rimworld_Animations_Patch
{
/*[StaticConstructorOnStartup]
[HarmonyPatch(typeof(PawnRenderer), "RenderPawnInternal", new Type[]
{
typeof(Vector3),
typeof(float),
typeof(bool),
typeof(Rot4),
typeof(RotDrawMode),
typeof(PawnRenderFlags)
}
)]
public static class HarmonyPatch_PawnRenderer_RenderPawnInternal
{
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> ins = instructions.ToList();
for (int i = 0; i < instructions.Count(); i++)
{
bool runIns = true;
// Replaces the rotation that gets passed to DrawHeadHair with one that is based the current 'true' head orientation
if (i + 8 < instructions.Count() && ins[i + 8].opcode == OpCodes.Call && ins[i + 8].operand != null && ins[i + 8].OperandIs(AccessTools.DeclaredMethod(typeof(PawnRenderer), "DrawHeadHair")))
{
// Get the true head rotation
yield return new CodeInstruction(OpCodes.Ldarg_0);
yield return new CodeInstruction(OpCodes.Ldfld, AccessTools.DeclaredField(typeof(PawnRenderer), "pawn"));
yield return new CodeInstruction(OpCodes.Ldloc, (object)7); // local body facing
yield return new CodeInstruction(OpCodes.Ldarg_S, (object)6); // renderer flags
yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(AnimationPatchUtility), "PawnHeadRotInAnimation"));
yield return new CodeInstruction(OpCodes.Stloc_S, (object)7); // set local body facing to true head facing
// Pass this head rotation to a new DrawHeadHair call
yield return new CodeInstruction(OpCodes.Ldarg_0);
yield return new CodeInstruction(OpCodes.Ldarg_1);
yield return new CodeInstruction(OpCodes.Ldloc_S, (object)6);
yield return new CodeInstruction(OpCodes.Ldarg_2);
yield return new CodeInstruction(OpCodes.Ldloc_S, (object)7); // local true head facing
yield return new CodeInstruction(OpCodes.Ldloc_S, (object)7); // local true head facing
yield return new CodeInstruction(OpCodes.Ldarg_S, (object)5); // bodyDrawType
yield return new CodeInstruction(OpCodes.Ldarg_S, (object)6); // renderer flags
yield return new CodeInstruction(OpCodes.Call, AccessTools.DeclaredMethod(typeof(PawnRenderer), "DrawHeadHair"));
// Skip the original call to DrawHeadHair
i = i + 8;
runIns = false;
}
if (runIns)
{
yield return ins[i];
}
}
}
}*/
[StaticConstructorOnStartup]
[HarmonyPatch(typeof(PawnGraphicSet), "ResolveAllGraphics")]
public static class HarmonyPatch_PawnGraphicSet_ResolveAllGraphics
{
// Update whether body parts are visible after resolving graphics
public static void Postfix(PawnGraphicSet __instance)
{
if (__instance?.pawn?.apparel == null)

View File

@ -7,7 +7,6 @@ using Verse;
using Verse.AI;
using rjw;
using Rimworld_Animations;
using RJW_ToysAndMasturbation;
namespace Rimworld_Animations_Patch
{
@ -16,48 +15,8 @@ namespace Rimworld_Animations_Patch
{
public static void Postfix(ref JobDriver_Sex __instance)
{
Pawn pawn = __instance.pawn;
// Sets ticks so that the orgasm meter starts empty, plus stop any running animations
HarmonyPatch_JobDriver_Masturbate_setup_ticks.Postfix(ref __instance);
// 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.InvitePasserbyForSex(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);
}
}
}
}
@ -117,10 +76,10 @@ namespace Rimworld_Animations_Patch
SexProps sexProps = new SexProps();
sexProps.pawn = __instance.pawn;
sexProps.partner = __instance.pawn;
sexProps.partner = null;
sexProps.sexType = xxx.rjwSextype.Masturbation;
List<InteractionDef> interactionDefs = DefDatabase<InteractionDef>.AllDefs.Where(x => x.HasModExtension<InteractionExtension>()).ToList();
IEnumerable<InteractionDef> interactionDefs = DefDatabase<InteractionDef>.AllDefs.Where(x => x.HasModExtension<InteractionExtension>());
Dictionary<rjw.Modules.Interactions.Objects.InteractionWithExtension, float> interactionsPlusWeights = new Dictionary<rjw.Modules.Interactions.Objects.InteractionWithExtension, float>();
foreach (InteractionDef interactionDef in interactionDefs)
@ -161,7 +120,6 @@ namespace Rimworld_Animations_Patch
{ return; }
// Get animation data
AnimationDef anim = __instance.pawn.GetAnimationData()?.animationDef;
List<Pawn> pawnsToAnimate = __instance.pawn.GetAllSexParticipants();
// Sync animations across participants
@ -276,8 +234,8 @@ namespace Rimworld_Animations_Patch
if (sexProps.sexType != xxx.rjwSextype.Oral || pawnsToAnimate.Count != 2)
{ return; }
List<AnimationDef> kissingAnims = DefDatabase<AnimationDef>.AllDefs.Where(x => x.defName.Contains("Kiss")).ToList();
AnimationDef anim = kissingAnims[Random.Range(0, kissingAnims.Count)];
IEnumerable<AnimationDef> kissingAnims = DefDatabase<AnimationDef>.AllDefs.Where(x => x.defName.Contains("Kiss"));
AnimationDef anim = kissingAnims.ElementAt(Random.Range(0, kissingAnims.Count()));
if (anim == null)
{ DebugMode.Message("No animation found"); return; }
@ -299,41 +257,6 @@ namespace Rimworld_Animations_Patch
}
}
[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); }
}
}
}
}
}
[HarmonyPatch(typeof(JobDriver_Sex), "Orgasm")]
public static class HarmonyPatch_JobDriver_Sex_Orgasm
{
@ -346,7 +269,8 @@ namespace Rimworld_Animations_Patch
return true;
}
public static bool ParticipantsDesireMoreSex(JobDriver_Sex jobdriver)
// Causes too much trouble...
/*public static bool ParticipantsDesireMoreSex(JobDriver_Sex jobdriver)
{
List<Pawn> participants = jobdriver.pawn.GetAllSexParticipants();
@ -387,7 +311,7 @@ namespace Rimworld_Animations_Patch
participants[1].jobs.StartJob(job, JobCondition.Succeeded);
}
}
}
}*/
}
[HarmonyPatch(typeof(JobDriver_SexBaseInitiator), "End")]
@ -398,7 +322,7 @@ namespace Rimworld_Animations_Patch
{
if (__instance.Partner != null && __instance?.Partner?.jobs?.curDriver != null && __instance.Partner.Dead == false && __instance.Partner?.jobs.curDriver is JobDriver_SexBaseReciever)
{
foreach (Pawn participant in (__instance.Partner?.jobs.curDriver as JobDriver_SexBaseReciever).parteners.ToList())
foreach (Pawn participant in (__instance.Partner?.jobs.curDriver as JobDriver_SexBaseReciever).parteners)
{ participant.jobs.EndCurrentJob(JobCondition.Succeeded, false, true); }
(__instance.Partner?.jobs.curDriver as JobDriver_SexBaseReciever).parteners.Clear();
@ -426,7 +350,7 @@ namespace Rimworld_Animations_Patch
// Fixes mouth check
public static bool Prefix(ref bool __result, Pawn pawn)
{
__result = pawn.health.hediffSet.GetNotMissingParts().Any(x => x.def.defName.ToLower().ContainsAny("mouth", "teeth", "jaw", "beak"));
__result = pawn.health.hediffSet.GetNotMissingParts().Any(x => x.def.defName.ContainsAny("mouth", "teeth", "jaw", "beak", "Mouth", "Teeth", "Jaw", "Beak"));
return false;
}

View File

@ -26,7 +26,7 @@ namespace Rimworld_Animations_Patch
}))();
}
catch (TypeLoadException ex) { }
catch (TypeLoadException) { }
}
public static bool Postfix_ThinkNode_ConditionalNude_Satisfied(ref bool __result, Pawn pawn)
@ -34,7 +34,7 @@ namespace Rimworld_Animations_Patch
if (__result == false && pawn?.apparel?.WornApparel != null)
{
// If 'isBeingWorn' has a value, the apparel has already been checked if it should be discarded
if (pawn.apparel.WornApparel.Any(x => x.TryGetComp<CompApparelVisibility>() != null && x.TryGetComp<CompApparelVisibility>().isBeingWorn.HasValue))
if (pawn.apparel.WornApparel.NullOrEmpty() || pawn.apparel.WornApparel.Any(x => x.TryGetComp<CompApparelVisibility>() != null && x.TryGetComp<CompApparelVisibility>().isBeingWorn.HasValue))
{ __result = true; }
}

View File

@ -9,7 +9,7 @@ using RimNudeWorld;
namespace Rimworld_Animations_Patch
{
[StaticConstructorOnStartup]
/*[StaticConstructorOnStartup]
public static class HarmonyPatch_RimNudeWorld
{
static HarmonyPatch_RimNudeWorld()
@ -33,5 +33,5 @@ namespace Rimworld_Animations_Patch
{
return false;
}
}
}*/
}

View File

@ -38,7 +38,7 @@ namespace Rimworld_Animations_Patch
CompPawnSexData comp = participant.TryGetComp<CompPawnSexData>();
if (comp == null) return;
comp.UpdateHands();
comp.UpdateBodyPartCountAndSize();
}
}
@ -48,7 +48,7 @@ namespace Rimworld_Animations_Patch
CompPawnSexData comp = __instance.pawn.TryGetComp<CompPawnSexData>();
if (comp == null) return;
comp.handAnimationDef = DefDatabase<HandAnimationDef>.AllDefs.FirstOrDefault(x => x.animationDefName == __instance.pawn?.GetAnimationData()?.animationDef?.defName);
comp.handAnimationDef = DefDatabase<HandAnimationDef>.AllDefs.FirstOrDefault(x => x.animationDef == __instance.pawn?.GetAnimationData()?.animationDef);
}
// Extend the animation selector's body part check to include hands and whether the pawn is in bed or not
@ -108,32 +108,32 @@ namespace Rimworld_Animations_Patch
public static bool Prefix_DrawAddons(PawnRenderFlags renderFlags, Vector3 vector, Vector3 headOffset, Pawn pawn, Quaternion quat, Rot4 rotation)
{
if (!(pawn.def is ThingDef_AlienRace alienProps) || renderFlags.FlagSet(PawnRenderFlags.Invisible)) return false;
if (AnimationPatchUtility.ShouldNotDrawAddonsForPawn(pawn))
{ return false; }
// Get actor components and body addons
List<AlienPartGenerator.BodyAddon> bodyAddons = alienProps.alienRace.generalSettings.alienPartGenerator.bodyAddons;
AlienPartGenerator.AlienComp alienComp = pawn.GetComp<AlienPartGenerator.AlienComp>();
CompBodyAnimator animatorComp = pawn.TryGetComp<CompBodyAnimator>();
CompPawnSexData sexDataComp = pawn.TryGetComp<CompPawnSexData>();
ActorAnimationData pawnAnimationData = pawn?.GetAnimationData();
// Try to draw apparel thrown on ground
if (ApparelSettings.clothesThrownOnGround)
{ ApparelAnimationUtility.TryToDrawApparelOnFloor(pawn); }
// Get actor components and body addons
List<AlienPartGenerator.BodyAddon> bodyAddons = alienProps.alienRace.generalSettings.alienPartGenerator.bodyAddons.ToList();
AlienPartGenerator.AlienComp alienComp = pawn.GetComp<AlienPartGenerator.AlienComp>();
CompBodyAnimator animatorComp = pawn.TryGetComp<CompBodyAnimator>();
CompPawnSexData sexDataComp = pawn.TryGetComp<CompPawnSexData>();
if (sexDataComp == null) return true;
// Exit clauses
if (BasicSettings.useLegacyAnimationSystem || AnimationPatchUtility.ShouldNotDrawAddonsForPawn(pawn) || sexDataComp == null)
{ return true; }
// Get available hands
int handsAvailableCount = sexDataComp.GetNumberOfHands();
// Sort addons by their layer offset, otherwise body parts will actualy be layered according to their position in the list
// Note that sorting the addons directly seems to mess up relations between lists need by AlienRace
var sortedBodyAddons = bodyAddons.Select((x, i) => new KeyValuePair<AlienPartGenerator.BodyAddon, int>(x, i)).OrderBy(x => x.Key.offsets.GetOffset(rotation).layerOffset).ToList();
List<int> idxBodyAddons = sortedBodyAddons.Select(x => x.Value).ToList();
var sortedBodyAddons = bodyAddons.Select((x, i) => new KeyValuePair<AlienPartGenerator.BodyAddon, int>(x, i)).OrderBy(x => x.Key.offsets.GetOffset(rotation).layerOffset);
IEnumerable<int> idxBodyAddons = sortedBodyAddons.Select(x => x.Value);
for (int idx = 0; idx < idxBodyAddons.Count; idx++)
foreach(int i in idxBodyAddons)
{
int i = idxBodyAddons[idx];
// Get body addon components
AlienPartGenerator.BodyAddon bodyAddon = bodyAddons[i];
Graphic addonGraphic = alienComp.addonGraphics[i];
@ -141,33 +141,33 @@ namespace Rimworld_Animations_Patch
if (bodyAddonDatum == null) continue;
// Can draw?
bool canDraw = addonGraphic.path.ToLower().Contains("featureless") == false && bodyAddonDatum.CanDraw();
bool canDraw = addonGraphic.path.Contains("featureless") == false && addonGraphic.path.Contains("Featureless") == false && bodyAddonDatum.CanDraw();
bool drawHand = BasicSettings.showHands && handsAvailableCount > 0 && renderFlags.FlagSet(PawnRenderFlags.Portrait) == false;
if (canDraw == false && drawHand == false)
{ continue; }
// Get body angle
float bodyAngle = animatorComp?.isAnimating == true && renderFlags.FlagSet(PawnRenderFlags.Portrait) == false ? animatorComp.bodyAngle : quat.eulerAngles.y;
bodyAngle = bodyAngle < 0f ? 360f + (bodyAngle % 360f) : bodyAngle % 360f;
bodyAngle = MathUtility.ClampAngle(bodyAngle);
// Get the apparent rotation and body addon angle
Rot4 apparentRotation = rotation;
float bodyAddonAngle = bodyAddon.angle;
float bodyAddonAngle = MathUtility.ClampAngle(bodyAddon.angle);
if (renderFlags.FlagSet(PawnRenderFlags.Portrait) == false && animatorComp?.isAnimating == true)
{
apparentRotation = bodyAddonDatum.alignsWithHead ? animatorComp.headFacing : animatorComp.bodyFacing;
if (animatorComp.controlGenitalAngle && addonGraphic.path.ToLower().Contains("penis"))
{ bodyAddonAngle += AnimationSettings.controlGenitalRotation ? animatorComp.genitalAngle : 0f; }
if (bodyAddonDatum.alignsWithHead)
{ bodyAngle = animatorComp.headAngle; }
{ bodyAngle = MathUtility.ClampAngle(animatorComp.headAngle); }
if (animatorComp.controlGenitalAngle && (addonGraphic.path.Contains("penis") || addonGraphic.path.Contains("Penis")))
{ bodyAddonAngle = MathUtility.ClampAngle(bodyAddonAngle + (AnimationSettings.controlGenitalRotation ? MathUtility.ClampAngle(animatorComp.genitalAngle) : 0f)); }
}
bodyAddonAngle = bodyAddonAngle < 0f ? 360f - (bodyAddonAngle % 360) : bodyAddonAngle % 360f;
float combinedAngle = (bodyAngle + bodyAddonAngle) < 0f ? 360f + ((bodyAngle + bodyAddonAngle) % 360) : (bodyAngle + bodyAddonAngle) % 360f;
float combinedAngle = MathUtility.ClampAngle(bodyAngle + bodyAddonAngle);
Vector3 vector_ = vector;
Vector3 headOffset_ = bodyAddonDatum.alignsWithHead ? headOffset : Vector3.zero;
@ -190,21 +190,45 @@ namespace Rimworld_Animations_Patch
{
GenDraw.DrawMeshNowOrLater(mesh: addonGraphic.MeshAt(rot: apparentRotation),
loc: bodyAddonPosition,
quat: Mathf.Approximately(combinedAngle, 0f) ? quat : Quaternion.AngleAxis(angle: combinedAngle, axis: Vector3.up),
quat: Quaternion.AngleAxis(angle: combinedAngle, axis: Vector3.up),
mat: addonGraphic.MatAt(rot: apparentRotation),
drawNow: renderFlags.FlagSet(PawnRenderFlags.DrawNow));
}
// Draw hand over the body part if required
if (drawHand)
{
float finalAngle = 0;
if (HandAnimationUtility.TryToDrawHand(pawn, addonGraphic.path, bodyAddonPosition, finalAngle, rotation, renderFlags))
if (HandAnimationUtility.TryToDrawHand(pawn, pawnAnimationData, addonGraphic.path, bodyAddonPosition, finalAngle, rotation, renderFlags))
{ handsAvailableCount--; }
}
}
// Add-ons
if (animatorComp?.isAnimating == true)
{
//ActorAnimationData actorData = pawn.GetAnimationData();
//PawnAnimationClipExt clip = actorData.animationDef.animationStages[actorData.currentStage].animationClips[actorData.actorID] as PawnAnimationClipExt;
/*foreach (ActorAddon addon in clip.Addons)
{
actorBodypart = actorBody.GetActorBodyPart(addon.AddonName);
if (actorBodypart == null) continue;
ActorBody anchoringActorBody = actorBodies.GetComponentsInChildren<ActorBody>()?.FirstOrDefault(x => x.actorID == addon.AnchoringActor);
Vector3 anchor = PawnUtility.GetBodyPartAnchor(anchoringActorBody, addon.anchorName);
actorBodypart.transform.position = anchor + new Vector3(addon.PosX.Evaluate(clipPercent), addon.PosZ.Evaluate(clipPercent), 0);
actorBodypart.transform.eulerAngles = new Vector3(0, 0, -addon.Rotation.Evaluate(clipPercent));
actorBodypart.bodyPartRenderer.sortingLayerName = addon.Layer;
//actorBodypart.bodyPartRenderer.sprite
actorBodypart.gameObject.SetActive(addon.Render);
}*/
}
// Body addons are sometimes are not appropriately concealed by long hair in portraits, so re-draw the pawn's hair here
if (pawn.Drawer.renderer.graphics.headGraphic != null && renderFlags.FlagSet(PawnRenderFlags.Portrait) && BasicSettings.redrawHair)
{
@ -214,10 +238,10 @@ namespace Rimworld_Animations_Patch
float headAngle = animatorComp != null && animatorComp.isAnimating && !renderFlags.FlagSet(PawnRenderFlags.Portrait) ? animatorComp.headAngle : quat.eulerAngles.y;
RotDrawMode rotDrawMode = (RotDrawMode)AccessTools.Property(typeof(PawnRenderer), "CurRotDrawMode").GetValue(pawn.Drawer.renderer);
methodInfo.Invoke(pawn.Drawer.renderer, new object[] { vector + new Vector3(0f, YOffset_Head, 0f), headOffset, headAngle, headFacing, headFacing, rotDrawMode, renderFlags });
methodInfo.Invoke(pawn.Drawer.renderer, new object[] { vector + new Vector3(0f, YOffset_Head, 0f), headOffset, headAngle, headFacing, headFacing, rotDrawMode, renderFlags, true });
}
return false;
return false;
}
// List of potentially useful layer offsets

View File

@ -1,107 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;
using HarmonyLib;
namespace Rimworld_Animations_Patch
{
[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 (ApparelSettings.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(PatchBodyPartGroupDefOf.GenitalsBPG));
bool chestCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso) || x.def.apparel.bodyPartGroups.Contains(PatchBodyPartGroupDefOf.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 (ApparelSettings.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(PatchBodyPartGroupDefOf.GenitalsBPG));
bool chestCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso) || x.def.apparel.bodyPartGroups.Contains(PatchBodyPartGroupDefOf.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 (ApparelSettings.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(PatchBodyPartGroupDefOf.GenitalsBPG));
bool chestCovered = pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso) || x.def.apparel.bodyPartGroups.Contains(PatchBodyPartGroupDefOf.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 (ApparelSettings.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(PatchBodyPartGroupDefOf.GenitalsBPG));
__result = !groinCovered;
}
}
}

View File

@ -15,8 +15,6 @@ namespace Rimworld_Animations_Patch
public static bool cropApparel = false;
public static bool clothesThrownOnGround = true;
public static RJWPreferenceSettings.Clothing apparelWornForQuickies = RJWPreferenceSettings.Clothing.Clothed;
public static bool underwearSufficentForIdeos = true;
public static bool exposedUnderwearMood = true;
public override void ExposeData()
{
@ -25,8 +23,6 @@ namespace Rimworld_Animations_Patch
Scribe_Values.Look(ref cropApparel, "cropApparel", false);
Scribe_Values.Look(ref clothesThrownOnGround, "clothesThrownOnGround", true);
Scribe_Values.Look(ref apparelWornForQuickies, "apparelWornForQuickies", RJWPreferenceSettings.Clothing.Clothed);
Scribe_Values.Look(ref underwearSufficentForIdeos, "underwearSufficentForIdeos", true);
Scribe_Values.Look(ref underwearSufficentForIdeos, "exposedUnderwearMood", true);
}
public static RimNudeData GetRimNudeData(Apparel apparel)
@ -46,8 +42,8 @@ namespace Rimworld_Animations_Patch
public class ApparelSettingsDisplay : Mod
{
private const float windowY = 280f;
private const float windowHeight = 330f;
private const float windowY = 290f;
private const float windowHeight = 320f;
private Vector2 scrollPosition;
private const float scrollBarWidthMargin = 18f;
@ -66,7 +62,11 @@ namespace Rimworld_Animations_Patch
private const float singleColumnWidth = 100f;
private const float doubleColumnWidth = 180f;
private static List<ThingDef> thingDefs = new List<ThingDef>();
private IEnumerable<ThingDef> shortListedApparelDefs = new List<ThingDef>();
private IEnumerable<ThingDef> allApparelDefs = new List<ThingDef>();
private IEnumerable<ModContentPack> relevantModContentPacks = new List<ModContentPack>();
private ModContentPack currentModContentPack;
public ApparelSettingsDisplay(ModContentPack content) : base(content)
{
@ -146,8 +146,6 @@ namespace Rimworld_Animations_Patch
listingStandard.CheckboxLabeled("clothes_thrown_on_ground".Translate(), ref ApparelSettings.clothesThrownOnGround, "clothes_thrown_on_ground_desc".Translate());
listingStandard.CheckboxLabeled("crop_apparel".Translate(), ref ApparelSettings.cropApparel, "crop_apparel_desc".Translate());
listingStandard.CheckboxLabeled("underwear_sufficent_for_ideos".Translate(), ref ApparelSettings.underwearSufficentForIdeos, "underwear_sufficent_for_ideos_desc".Translate());
listingStandard.CheckboxLabeled("exposed_underwear_mood".Translate(), ref ApparelSettings.exposedUnderwearMood, "exposed_underwear_mood_desc".Translate());
listingStandard.End();
base.DoSettingsWindowContents(inRect);
@ -162,9 +160,20 @@ namespace Rimworld_Animations_Patch
bool isEnabled = false;
// Get a list of apparel of interest
if (thingDefs.NullOrEmpty())
{ thingDefs = ApparelSettingsUtility.GetApparelOfInterest(); }
// Get a list of apparel and mods of interest
if (allApparelDefs.Any() == false)
{
allApparelDefs = ApparelSettingsUtility.GetApparelOfInterest();
foreach (ThingDef thingDef in allApparelDefs)
{
if (relevantModContentPacks.Contains(thingDef.modContentPack) == false)
{ relevantModContentPacks.Append(thingDef.modContentPack); }
}
currentModContentPack = relevantModContentPacks.First();
shortListedApparelDefs = allApparelDefs.Where(x => x.modContentPack == currentModContentPack);
}
// Ensure that all apparel has associated RimNudeData
if (ApparelSettings.rimNudeData.NullOrEmpty())
@ -173,6 +182,28 @@ namespace Rimworld_Animations_Patch
// Add buttons to the top of the main window
innerX = halfColumnWidth;
// Mod selection button
if (Widgets.ButtonText(new Rect(innerX + SettingsUtility.Align(labelWidth, doubleColumnWidth), windowY - 2 * headerHeight - 5, 2 * doubleColumnWidth + 10, headerHeight), currentModContentPack.Name))
{
List<FloatMenuOption> options = new List<FloatMenuOption> { };
foreach (ModContentPack modContentPack in relevantModContentPacks)
{
FloatMenuOption option = new FloatMenuOption(modContentPack.Name, delegate ()
{
currentModContentPack = modContentPack;
shortListedApparelDefs = allApparelDefs.Where(x => x.modContentPack == currentModContentPack);
},
MenuOptionPriority.Default, null, null, 0f, null, null, true, 0);
options.Add(option);
}
Find.WindowStack.Add(new FloatMenu(options));
}
if (shortListedApparelDefs.Any() == false) return;
// Apparel
tempRect = new Rect(innerX + SettingsUtility.Align(labelWidth, doubleColumnWidth), windowY - headerHeight - 5, labelWidth, headerHeight);
Widgets.DrawHighlightIfMouseover(tempRect);
@ -183,10 +214,10 @@ namespace Rimworld_Animations_Patch
List<FloatMenuOption> options = new List<FloatMenuOption>
{
new FloatMenuOption("Sort by name", delegate()
{ thingDefs = thingDefs.OrderBy(x => x.label).ToList();
{ shortListedApparelDefs = shortListedApparelDefs.OrderBy(x => x.label);
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
new FloatMenuOption("Sort by mod", delegate()
{ thingDefs = ApparelSettingsUtility.GetApparelOfInterest();
{ shortListedApparelDefs = ApparelSettingsUtility.GetApparelOfInterest();
}, MenuOptionPriority.Default, null, null, 0f, null, null, true, 0),
}; Find.WindowStack.Add(new FloatMenu(options));
}; innerX += doubleColumnWidth;
@ -272,7 +303,7 @@ namespace Rimworld_Animations_Patch
{ ApparelSettingsUtility.ResetRimNudeData(ApparelSettings.rimNudeData); }; innerX += singleColumnWidth + scrollBarWidthMargin;
// Determine the height of the scrollable area
int apparelCount = thingDefs.Count;
int apparelCount = shortListedApparelDefs.Count();
float totalContentHeight = rowHeight * (float)apparelCount;
// Create a rect for the scroll window
@ -288,7 +319,7 @@ namespace Rimworld_Animations_Patch
Widgets.DrawHighlight(contentRect);
Widgets.BeginScrollView(contentRect, ref scrollPosition, scrollViewTotal);
foreach (ThingDef thingDef in thingDefs)
foreach (ThingDef thingDef in shortListedApparelDefs)
{
isEnabled = false;

View File

@ -9,23 +9,12 @@ namespace Rimworld_Animations_Patch
{
public class BasicSettings : ModSettings
{
public static bool autoscaleDeltaPos = true;
public static bool linkChanges = false;
public static bool needPrivacy = true;
public static float chanceForOtherToJoinInSex = 0.25f;
public static bool autoscaleDeltaPos = true;
public static bool hideNamesForSex = false;
public static bool debugMode = false;
public static bool showHands = true;
public static bool redrawHair = true;
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 ignoreSlaveRape = false;
public static bool majorTabooCanStartFights = false;
public static bool useLegacyAnimationSystem = false;
public static float genitalMasturbationChance = 1.0f;
public static float analMasturbationChance = 0.25f;
@ -40,21 +29,10 @@ namespace Rimworld_Animations_Patch
base.ExposeData();
Scribe_Values.Look(ref autoscaleDeltaPos, "autoscaleDeltaPos", true);
Scribe_Values.Look(ref linkChanges, "linkChanges", false);
Scribe_Values.Look(ref needPrivacy, "needPrivacy", true);
Scribe_Values.Look(ref chanceForOtherToJoinInSex, "chanceForSexExtra", 0.25f);
Scribe_Values.Look(ref hideNamesForSex, "hideNamesForSex", false);
Scribe_Values.Look(ref debugMode, "debugMode", false);
Scribe_Values.Look(ref showHands, "showHands", true);
Scribe_Values.Look(ref redrawHair, "redrawHair", true);
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 ignoreSlaveRape, "ignoreSlaveRape", false);
Scribe_Values.Look(ref majorTabooCanStartFights, "majorTabooCanStartFights", false);
}
}
@ -98,23 +76,6 @@ namespace Rimworld_Animations_Patch
listingStandard.Label("rimworld_animation_patch_general".Translate());
listingStandard.Gap(5f);
listingStandard.CheckboxLabeled("need_privacy".Translate(), ref BasicSettings.needPrivacy, "need_privacy_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.CheckboxLabeled("major_taboo_can_start_fights".Translate(), ref BasicSettings.majorTabooCanStartFights, "major_taboo_can_start_fights_desc".Translate());
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.Label("test slide: " + BasicSettings.sliderValue.ToString("F"), -1f);
//BasicSettings.sliderValue = listingStandard.Slider(BasicSettings.sliderValue, -2f, 2f);
@ -125,10 +86,11 @@ namespace Rimworld_Animations_Patch
listingStandard.Label("rimworld_animation_patch_animation".Translate());
listingStandard.Gap(5f);
listingStandard.CheckboxLabeled("autoscale_delta_pos".Translate(), ref BasicSettings.autoscaleDeltaPos, "autoscale_delta_pos_desc".Translate());
listingStandard.CheckboxLabeled("show_hands".Translate(), ref BasicSettings.showHands, "show_hands_desc".Translate());
listingStandard.CheckboxLabeled("autoscale_delta_pos".Translate(), ref BasicSettings.autoscaleDeltaPos, "autoscale_delta_pos_desc".Translate());
listingStandard.CheckboxLabeled("redraw_hair".Translate(), ref BasicSettings.redrawHair, "redraw_hair_desc".Translate());
listingStandard.CheckboxLabeled("show_hands".Translate(), ref BasicSettings.showHands, "show_hands_desc".Translate());
listingStandard.End();
base.DoSettingsWindowContents(inRect);
}

View File

@ -1,37 +0,0 @@
using System;
using RimWorld;
using Verse;
using rjw;
namespace Rimworld_Animations_Patch
{
public class ThoughtWorker_ExposedUnderwear : ThoughtWorker
{
public static ThoughtState CurrentThoughtState(Pawn pawn)
{
if (xxx.has_quirk(pawn, "Exhibitionist"))
{
return ThoughtState.ActiveAtStage(1);
}
return ThoughtState.ActiveAtStage(0);
}
protected override ThoughtState CurrentStateInternal(Pawn pawn)
{
if (ApparelSettings.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(PatchBodyPartGroupDefOf.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(PatchBodyPartGroupDefOf.ChestBPG)) &&
pawn.apparel.WornApparel.Any(x => x.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.Torso)) == false)
{ return CurrentThoughtState(pawn); }
return ThoughtState.Inactive;
}
}
}

View File

@ -60,7 +60,7 @@ namespace Rimworld_Animations_Patch
if (orgasmTick > ticks)
{
// Safeguard for penial, vaginal and anal sex
if (anim.actors[actorId].isFucked || anim.actors[actorId].isFucking || (anim.actors[actorId].requiredGenitals.NullOrEmpty() == false && anim.actors[actorId].requiredGenitals.Any(x => x.ToLower().ContainsAny("penis", "vagina", "anus"))))
if (anim.actors[actorId].isFucked || anim.actors[actorId].isFucking || (anim.actors[actorId].requiredGenitals.NullOrEmpty() == false && anim.actors[actorId].requiredGenitals.Any(x => x.ContainsAny("penis", "vagina", "anus", "Penis", "Vagina", "Anus"))))
{ orgasmTick = Mathf.Clamp(ticks - 5, 0, int.MaxValue); }
// Actor does not orgasm
@ -187,16 +187,17 @@ namespace Rimworld_Animations_Patch
{
{ "Alien_Orassan", new Vector3(1.4f, 1.4f, 1.4f) },
{ "Alien_Cutebold", new Vector3(1.2f, 1f, 1f) },
{ "Rabbie", new Vector3(-0.5f, 1f, 1f) },
};
public static Vector2 GetRaceSpecificOffsetMultipliers(Pawn pawn, string bodypart)
public static Vector2 GetRaceSpecificOffsetMultipliers(Pawn pawn, BodyPartDef bodypart)
{
Vector2 multiplierVector = new Vector2();
if (GetBodySize(pawn) == 1f || raceSpecifocChildMultipliers.TryGetValue(pawn.def.defName, out Vector3 raceVector) == false)
{ raceVector = new Vector3(1f, 1f, 1f); }
if (bodypart?.ToLower() == "tail")
if (bodypart?.defName == "tail" || bodypart?.defName == "Tail")
{
multiplierVector.x = raceVector.z;
multiplierVector.y = raceVector.x;

View File

@ -153,7 +153,7 @@ namespace Rimworld_Animations_Patch
{ bodyPartCovered = bodyPartCovered || PrivatePartCoveredByApparel(apparel, "Chest"); }
if (requiredGenitals.Contains("Mouth"))
{ bodyPartCovered = bodyPartCovered || apparel.def.apparel.CoversBodyPart(bodyParts.FirstOrDefault(x => x.def.defName.ToLower().ContainsAny("mouth", "teeth", "jaw", "beak"))); }
{ bodyPartCovered = bodyPartCovered || apparel.def.apparel.CoversBodyPart(bodyParts.FirstOrDefault(x => x.def.defName.ContainsAny("mouth", "teeth", "jaw", "beak", "Mouth", "Teeth", "Jaw", "Beak"))); }
return bodyPartCovered;
}

View File

@ -13,27 +13,21 @@ namespace Rimworld_Animations_Patch
{
public static BodyPartDef handDef;
public static bool BodyPartIsBeingTouched(Pawn pawn, string bodypartFilePath, out List<HandAnimationData> handAnimationData)
public static bool BodyPartIsBeingTouched(Pawn pawn, ActorAnimationData actorAnimationData, string bodypartFilePath, out List<HandAnimationData> handAnimationData)
{
handAnimationData = new List<HandAnimationData>();
HandAnimationDef handAnimationDef = pawn?.TryGetComp<CompPawnSexData>()?.handAnimationDef;
ActorAnimationData actorAnimationData = pawn?.GetAnimationData();
if (handAnimationDef == null || actorAnimationData == null || bodypartFilePath.NullOrEmpty())
{ return false; }
foreach (HandAnimationData datum in handAnimationDef.handAnimationData)
{
if (datum.stageID != actorAnimationData.currentStage || datum.actorID != actorAnimationData.actorID)
{ continue; }
if (datum.stageID != actorAnimationData.currentStage || datum.actorID != actorAnimationData.actorID) continue;
if (datum.bodySide.NullOrEmpty() == false && bodypartFilePath.Contains(datum.bodySide, StringComparison.OrdinalIgnoreCase) == false) continue;
if (datum.bodySide.NullOrEmpty() == false && bodypartFilePath.ToLower().Contains(datum.bodySide) == false)
{ continue; }
if (datum.targetBodyPart.NullOrEmpty() == false && bodypartFilePath.ToLower().Contains(datum.targetBodyPart.ToLower()))
{ handAnimationData.Add(datum); }
else if (datum.targetBodyParts.Any(x => bodypartFilePath.ToLower().Contains(x.ToLower())))
if ((datum.targetBodyPart.NullOrEmpty() == false && bodypartFilePath.Contains(datum.targetBodyPart, StringComparison.OrdinalIgnoreCase)) ||
datum.targetBodyParts.Any(x => bodypartFilePath.Contains(x, StringComparison.OrdinalIgnoreCase)))
{ handAnimationData.Add(datum); }
}
@ -42,147 +36,26 @@ namespace Rimworld_Animations_Patch
public static Vector3 GetHandPosition(Pawn pawn, HandAnimationData handAnimationData, Vector3 basePosition, float baseAngle)
{
var methodInfo = AccessTools.Method(typeof(HandAnimationUtility), handAnimationData.motion, null, null);
if (methodInfo == null)
{
Debug.LogWarning("Hand animation motion '" + handAnimationData.motion + "' was not found");
return default;
}
Vector3 handPosition = (Vector3)methodInfo.Invoke(null, new object[] { pawn, handAnimationData, baseAngle });
Vector3 handPosition = handAnimationData.Motion.GetHandPosition(pawn, handAnimationData, baseAngle);
return handPosition * pawn.RaceProps.baseBodySize + basePosition + new Vector3(0f, 0.3f, 0f);
}
public static float GetGenitalSize(Pawn pawn, string genitalName)
{
switch(genitalName.ToLower())
CompPawnSexData data = pawn?.TryGetComp<CompPawnSexData>();
if (data == null) return 0f;
switch (genitalName)
{
case "penis": return pawn.health.hediffSet.hediffs.First(x => x.def.defName.ToLower().Contains("penis")).Severity;
case "breasts": return pawn.health.hediffSet.hediffs.First(x => x.def.defName.ToLower().Contains("breasts")).Severity;
case "vagina": return 0.1f;
case "anus": return 0.1f;
case "penis": return data.sizeOfPenis;
case "breasts": return data.sizeOfBreasts;
case "Penis": return data.sizeOfPenis;
case "Breasts": return data.sizeOfBreasts;
}
return 0.1f;
}
public static Vector3 Motion_StrokeGenitalsUpAndDownShort_FacingNS(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float p = (Mathf.PingPong(data.stageTicks, handAnimationData.cycleTime) / handAnimationData.cycleTime);
float length = 0.035f;
handPosition.x = 0;
handPosition.z = length * p;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
public static Vector3 Motion_StrokeGenitalsUpAndDown_FacingNS(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float p = (Mathf.PingPong(data.stageTicks, handAnimationData.cycleTime) / handAnimationData.cycleTime);
float size = GetGenitalSize(pawn, handAnimationData.targetBodyPart) * 0.2f;
float m = (data.actorFacing == Rot4.North ? -1f : 1f) * (handAnimationData.mirror ? -1f : 1f) * (pawn.TryGetComp<CompBodyAnimator>().Mirror ? -1f : 1f);
handPosition.x = 0.025f * m;
handPosition.z = size * p;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
public static Vector3 Motion_StrokeGenitalsUpAndDown_FacingEW(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float p = Mathf.PingPong(data.stageTicks, handAnimationData.cycleTime) / handAnimationData.cycleTime;
float size = GetGenitalSize(pawn, handAnimationData.targetBodyPart) * 0.2f;
float m = (data.actorFacing == Rot4.West ? -1f : 1f) * (handAnimationData.mirror ? -1f : 1f);
handPosition.x = Mathf.Sin(m * (baseAngle + 45f) / 180f * Mathf.PI) * size * p;
handPosition.z = Mathf.Cos(m * (baseAngle + 45f) / 180f * Mathf.PI) * size * p;
return handPosition;
}
public static Vector3 Motion_RubGenitals_FacingNS(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float a = ((float)data.stageTicks % (float)handAnimationData.cycleTime) / (float)handAnimationData.cycleTime * 360f;
float m = (data.actorFacing == Rot4.North ? 1f : -1f) * (handAnimationData.mirror ? -1f : 1f) * (pawn.TryGetComp<CompBodyAnimator>().Mirror ? -1f : 1f);
handPosition.x = (Mathf.Sin(a / 180f * Mathf.PI) * 0.05f - 0.025f) * m;
handPosition.z = Mathf.Cos(a / 180f * Mathf.PI) * 0.015f + 0.03f;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
public static Vector3 Motion_RubGenitals_FacingEW(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float a = ((float)data.stageTicks % (float)handAnimationData.cycleTime) / (float)handAnimationData.cycleTime * 360f;
float m = (data.actorFacing == Rot4.West ? 1f : -1f) * (handAnimationData.mirror ? -1f : 1f);
handPosition.x = (Mathf.Sin(a / 180f * Mathf.PI) * 0.005f - 0.05f) * m;
handPosition.z = Mathf.Cos(a / 180f * Mathf.PI) * 0.015f;
//handPosition.y = -0.1f;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
public static Vector3 Motion_RubBreasts_FacingNS(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float a = ((float)data.stageTicks % (float)handAnimationData.cycleTime) / (float)handAnimationData.cycleTime * 360f;
float m = (data.actorFacing == Rot4.North ? -1f : 1f) * (handAnimationData.mirror ? -1f : 1f) * (pawn.TryGetComp<CompBodyAnimator>().Mirror ? -1f : 1f);
float size = GetGenitalSize(pawn, "breasts");
handPosition.x = (Mathf.Sin(a / 180f * Mathf.PI) * 0.05f * size - size * 0.25f) * m;
handPosition.z = Mathf.Cos(a / 180f * Mathf.PI) * 0.015f - size * 0.125f;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
public static Vector3 Motion_RubBreasts_FacingEW(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float a = ((float)data.stageTicks % (float)handAnimationData.cycleTime) / (float)handAnimationData.cycleTime * 360f;
float m = (data.actorFacing == Rot4.West ? 1f : -1f) * (handAnimationData.mirror ? -1f : 1f);
float size = GetGenitalSize(pawn, "breasts");
handPosition.x = (Mathf.Sin(a / 180f * Mathf.PI) * 0.005f - size * 0.25f) * m;
handPosition.z = Mathf.Cos(a / 180f * Mathf.PI) * 0.015f - size * 0.125f;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
public static Graphic GetHandGraphic(Pawn touchingPawn)
{
CompPawnSexData comp = touchingPawn?.TryGetComp<CompPawnSexData>();
@ -198,9 +71,9 @@ namespace Rimworld_Animations_Patch
return comp.handGraphic;
}
public static bool TryToDrawHand(Pawn pawn, string bodyAddonName, Vector3 bodyAddonPosition, float bodyAddonAngle, Rot4 bodyAddonRotation, PawnRenderFlags renderFlags)
public static bool TryToDrawHand(Pawn pawn, ActorAnimationData pawnAnimationData, string bodyAddonName, Vector3 bodyAddonPosition, float bodyAddonAngle, Rot4 bodyAddonRotation, PawnRenderFlags renderFlags)
{
if (BodyPartIsBeingTouched(pawn, bodyAddonName, out List<HandAnimationData> handAnimationData))
if (BodyPartIsBeingTouched(pawn, pawnAnimationData, bodyAddonName, out List<HandAnimationData> handAnimationData))
{
foreach (HandAnimationData datum in handAnimationData)
{

View File

@ -33,14 +33,19 @@ namespace Rimworld_Animations_Patch
{
for (int radius = 1; radius < maxRadius; radius++)
{
List<IntVec3> cells = GenRadial.RadialCellsAround(pawn.Position, radius + 0.75f, false).Where(x => x.Standable(pawn.Map) && x.GetRoom(pawn.Map) == pawn.GetRoom())?.ToList();
IEnumerable<IntVec3> cells = GenRadial.RadialCellsAround(pawn.Position, radius + 0.75f, false).Where(x => x.Standable(pawn.Map) && x.GetRoom(pawn.Map) == pawn.GetRoom());
if (cells.NullOrEmpty() == false && cells.Count > 0)
if (cells.Any() == true && cells.Count() > 0)
{ return cells.RandomElement(); }
}
}
return GenAdj.RandomAdjacentCellCardinal(pawn);
}
public static float ClampAngle(float angle)
{
return angle < 0f ? 360f - (angle % 360) : angle % 360f;
}
}
}

View File

@ -16,5 +16,8 @@ namespace Rimworld_Animations_Patch
public static class PatchBodyPartDefOf
{
public static BodyPartDef Hand;
public static BodyPartDef Genitals;
public static BodyPartDef Anus;
public static BodyPartDef Chest;
}
}

View File

@ -1,266 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Verse;
using Verse.AI;
using Verse.AI.Group;
using RimWorld;
using rjw;
using RJWSexperience.Ideology;
using UnityEngine;
namespace Rimworld_Animations_Patch
{
public static class SexInteractionUtility
{
public static bool PawnCaughtLovinByWitness(Pawn pawn, Pawn witness)
{
if (witness == null || pawn == witness || witness.AnimalOrWildMan() || witness.RaceProps.IsMechanoid || witness.Awake() == false || witness.CanSee(pawn) == false)
{ return false; }
if (pawn.IsHavingSex() == false && pawn.IsMasturbating() == false)
{ return false; }
List<Pawn> sexParticipants = pawn.GetAllSexParticipants();
bool witnessIsCourtingSexParticipant = witness.jobs.curDriver is JobDriver_SexBaseInitiator && sexParticipants.Contains((witness.jobs.curDriver as JobDriver_SexBaseInitiator).Partner);
if (sexParticipants.Contains(witness) || witnessIsCourtingSexParticipant)
{ return false; }
return true;
}
public static bool PawnIsCheatingOnPartner(Pawn pawn, Pawn partner)
{
if (BasicSettings.worryAboutInfidelity == false || pawn.IsMasturbating() || pawn.IsHavingSex() == false || pawn.GetAllSexParticipants().Contains(partner))
{ return false; }
if (pawn.GetAllSexParticipants().Any(x => pawn.GetSpouseCount(false) > 0 && pawn.GetSpouses(false).Contains(x)))
{ return false; }
if (pawn.GetSexPartner().Dead || pawn.GetSexPartner().IsAnimal())
{ return false; }
return partner.IsLoverOfOther(pawn) && pawn.HasTrait("Polygamist") == false && partner.HasTrait("Polygamist") == false;
}
public static bool InvitePasserbyForSex(Pawn passerby, List<Pawn> participants)
{
if (passerby == null || participants.NullOrEmpty() || participants.Contains(passerby) || passerby.AnimalOrWildMan() || passerby.RaceProps.IsMechanoid || passerby.Awake() == false || participants.All(x => x.CanSee(passerby) == false))
{ return false; }
if (participants.Any(x => x.IsForbidden(passerby) || x.HostileTo(passerby) || PawnIsCheatingOnPartner(x, passerby)) || CasualSex_Helper.CanHaveSex(passerby) == false || xxx.IsTargetPawnOkay(passerby) == false || participants.Count > 2)
{ 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; }
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;
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");
}
//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 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;
}
}
public static bool ResolveThoughtsForWhenSexIsWitnessed(Pawn pawn, Pawn witness, out bool witnessJoiningSex)
{
witnessJoiningSex = Random.value < BasicSettings.chanceForOtherToJoinInSex && InvitePasserbyForSex(witness, pawn.GetAllSexParticipants());
// Exit clauses
if (witness.AnimalOrWildMan() || witness.RaceProps.IsMechanoid || witness.Dead || witness.Faction == null || witness.Faction.HostileTo(Faction.OfPlayer))
{ return false; }
// Get basic thoughts
string pawnThoughtDefName = pawn.IsMasturbating() ? "SeenMasturbating" : "SeenHavingSex";
string witnessThoughtDefName = pawn.IsMasturbating() ? "SawMasturbation" : "SawSex";
ThoughtDef pawnThoughtDef = BasicSettings.needPrivacy ? DefDatabase<ThoughtDef>.GetNamedSilentFail(pawnThoughtDefName) : null;
ThoughtDef witnessThoughtDef = BasicSettings.needPrivacy ? DefDatabase<ThoughtDef>.GetNamedSilentFail(witnessThoughtDefName) : null;
// Exhibitionist pawn
if (xxx.has_quirk(pawn, "Exhibitionist"))
{ pawnThoughtDef = DefDatabase<ThoughtDef>.GetNamedSilentFail(pawnThoughtDefName + "Exhibitionist"); }
// Voyeuristic witness
if (xxx.has_quirk(witness, "Voyeur"))
{ witnessThoughtDef = DefDatabase<ThoughtDef>.GetNamedSilentFail(witnessThoughtDefName + "Voyeur"); }
// 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 pawnIsCheating = sexIsRitual == false && sexIsParty == false && pawnIsVictim == false && PawnIsCheatingOnPartner(pawn, witness);
// Wipe thoughts if pawn is a victim
if (pawnIsVictim)
{
pawnThoughtDef = null;
witnessThoughtDef = null;
}
// Add thought if pawn is cheating
if (pawnIsCheating)
{
if (pawn.needs.mood.thoughts.memories.GetFirstMemoryOfDef(DefDatabase<ThoughtDef>.GetNamedSilentFail("CaughtCheating")) == null)
{ pawn.needs.mood.thoughts.memories.TryGainMemory(DefDatabase<ThoughtDef>.GetNamedSilentFail("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
Precept precept = null;
if (sexIsRitual == false && sexIsParty == false && pawnIsVictim == false)
{ witnessThoughtDef = GetThoughtsAboutSexAct(witness, pawn.jobs.curDriver as JobDriver_Sex, out precept); }
// Apply thoughts to witness
if (witnessThoughtDef != null)
{
witness.needs.mood.thoughts.memories.TryGainMemory(witnessThoughtDef, pawn, precept);
if (witnessThoughtDef.stages[0].baseMoodEffect < 0)
{ witness?.TryGetComp<CompPawnSexData>()?.TryToExclaim(); }
witnessJoiningSex = witnessThoughtDef.hediff != null ? false : witnessJoiningSex;
}
// Extreme reaction
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<CompPawnSexData>()?.TryToExclaim(); }
}
return witnessJoiningSex;
}
}
}

View File

@ -1 +1 @@
80ac53cd1937a7f3bc413d1816a7df030fc583c6
0035486d66161d603d82d58abd89b02b042a2e0c

View File

@ -4,3 +4,5 @@ C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\rimworld-animations-
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\rimworld-animations-patch-abscon\Source\obj\Debug\Rimworld-Animations-Patch.dll
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\rimworld-animations-patch-abscon\Source\obj\Debug\Rimworld-Animations-Patch.pdb
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\rimworld-animations-patch-abscon\Source\obj\Debug\Rimworld-Animations-Patch.csprojAssemblyReference.cache
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\rimworld-animations-patch-abscon\1.4\Assemblies\Rimworld-Animations-Patch.dll
C:\Program Files (x86)\Steam\SteamApps\common\RimWorld\Mods\rimworld-animations-patch-abscon\1.4\Assemblies\Rimworld-Animations-Patch.pdb