diff --git a/1.3/Assemblies/Rimworld-Animations-Patch.dll b/1.3/Assemblies/Rimworld-Animations-Patch.dll deleted file mode 100644 index 1c13061..0000000 Binary files a/1.3/Assemblies/Rimworld-Animations-Patch.dll and /dev/null differ diff --git a/1.4/Assemblies/Rimworld-Animations-Patch.dll b/1.4/Assemblies/Rimworld-Animations-Patch.dll new file mode 100644 index 0000000..41cfc9f Binary files /dev/null and b/1.4/Assemblies/Rimworld-Animations-Patch.dll differ diff --git a/1.4/Assemblies/Rimworld-Animations-Patch.pdb b/1.4/Assemblies/Rimworld-Animations-Patch.pdb new file mode 100644 index 0000000..8a81570 Binary files /dev/null and b/1.4/Assemblies/Rimworld-Animations-Patch.pdb differ diff --git a/About/About.xml b/About/About.xml index 4f8d5e5..0f850c8 100644 --- a/About/About.xml +++ b/About/About.xml @@ -4,7 +4,7 @@ Rimworld-Animation Patch AbstractConcept -
  • 1.3
  • +
  • 1.4
  • abscon.rimworld.animations.patch @@ -38,20 +38,20 @@
  • OTYOTY.NudePatchForRimNudeWorld.UnofficialUpdate
  • -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 diff --git a/About/Changelog_v1.2.4.txt b/About/Changelog_v1.2.4.txt deleted file mode 100644 index 04f8c72..0000000 --- a/About/Changelog_v1.2.4.txt +++ /dev/null @@ -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 \ No newline at end of file diff --git a/About/Changelog_v2.0.0.txt b/About/Changelog_v2.0.0.txt new file mode 100644 index 0000000..ecaa6bf --- /dev/null +++ b/About/Changelog_v2.0.0.txt @@ -0,0 +1,2 @@ +Change log v 2.0.0 +- Initial re-release (for RimWorld 1.4) \ No newline at end of file diff --git a/About/Manifest.xml b/About/Manifest.xml index 36c3b5a..c1dba00 100644 --- a/About/Manifest.xml +++ b/About/Manifest.xml @@ -1,5 +1,5 @@ - 1.2.2 + 2.0.0 https://gitgud.io/AbstractConcept/rimworld-animations-patch \ No newline at end of file diff --git a/Defs/AnimationDefs/Animation_threesome_sandwich.xml b/Defs/AnimationDefs/Animation_threesome_sandwich.xml index cbc7917..6506470 100644 --- a/Defs/AnimationDefs/Animation_threesome_sandwich.xml +++ b/Defs/AnimationDefs/Animation_threesome_sandwich.xml @@ -7,6 +7,7 @@
  • Vaginal
  • Anal
  • +
  • DoublePenetration
  • AnalSex
  • diff --git a/Defs/AnimationDefs/Animations_extension.xml b/Defs/AnimationDefs/Animations_extension.xml index 09bc8fc..2960efb 100644 --- a/Defs/AnimationDefs/Animations_extension.xml +++ b/Defs/AnimationDefs/Animations_extension.xml @@ -1014,7 +1014,7 @@
  • 30 - + 0 0 0 -0.23 @@ -1759,7 +1759,7 @@ 0 0.2 0.390 - 0.2 + 0 3 -0.003
  • @@ -2647,7 +2647,7 @@
  • Suck 59 - + 0 6 0 -0.33 @@ -2679,7 +2679,7 @@
  • Suck 59 - + 0 6 0 -0.33 @@ -3268,7 +3268,7 @@
  • Suck 59 - + 0 6 0 -0.33 diff --git a/Defs/AnimationDefs/Animations_extension_hand.xml b/Defs/AnimationDefs/Animations_extension_hand.xml index 58f5544..9ec026c 100644 --- a/Defs/AnimationDefs/Animations_extension_hand.xml +++ b/Defs/AnimationDefs/Animations_extension_hand.xml @@ -3,14 +3,14 @@ Handjob_HandDef - Handjob + Handjob
  • 0 1 0 Penis - Motion_StrokeGenitalsUpAndDown_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS 30
  • @@ -18,7 +18,7 @@ 1 0 Penis - Motion_StrokeGenitalsUpAndDown_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS 15
  • @@ -26,7 +26,7 @@ 1 0 Penis - Motion_StrokeGenitalsUpAndDown_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS 15
  • @@ -34,14 +34,14 @@ Fisting_HandDef - Fisting + Fisting
  • 0 0 1 Penis - Motion_StrokeGenitalsUpAndDownShort_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS 60
  • @@ -49,7 +49,7 @@ 0 1 Penis - Motion_StrokeGenitalsUpAndDownShort_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS 15
  • @@ -57,7 +57,7 @@ 0 1 Penis - Motion_StrokeGenitalsUpAndDownShort_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS 15
  • @@ -66,7 +66,7 @@ 0 1 Vagina - Motion_StrokeGenitalsUpAndDownShort_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS 60
  • @@ -74,7 +74,7 @@ 0 1 Vagina - Motion_StrokeGenitalsUpAndDownShort_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS 15
  • @@ -82,7 +82,7 @@ 0 1 Vagina - Motion_StrokeGenitalsUpAndDownShort_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS 15
  • @@ -90,14 +90,14 @@ Fingering_HandDef - Fingering + Fingering
  • 0 0 1 Vagina - Motion_StrokeGenitalsUpAndDownShort_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS 60
  • @@ -105,7 +105,7 @@ 0 1 Vagina - Motion_StrokeGenitalsUpAndDownShort_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS 15
  • @@ -113,7 +113,7 @@ 0 1 Vagina - Motion_StrokeGenitalsUpAndDownShort_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDownShort_FacingNS 15
  • diff --git a/Defs/AnimationDefs/Animations_solo_hand.xml b/Defs/AnimationDefs/Animations_solo_hand.xml index 0e0267e..9044078 100644 --- a/Defs/AnimationDefs/Animations_solo_hand.xml +++ b/Defs/AnimationDefs/Animations_solo_hand.xml @@ -3,24 +3,24 @@ MasturbationWithPenis_Standing_HandDef - MasturbationWithPenis_Standing + MasturbationWithPenis_Standing
  • 0 Penis - Motion_StrokeGenitalsUpAndDown_FacingEW + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW 31
  • 1 Penis - Motion_StrokeGenitalsUpAndDown_FacingEW + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW 16
  • 2 Penis - Motion_StrokeGenitalsUpAndDown_FacingEW + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW 16
  • @@ -28,24 +28,24 @@ MasturbationWithPenis_InBed_HandDef - MasturbationWithPenis_InBed + MasturbationWithPenis_InBed
  • 0 Penis - Motion_StrokeGenitalsUpAndDown_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS 31
  • 1 Penis - Motion_StrokeGenitalsUpAndDown_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS 16
  • 2 Penis - Motion_StrokeGenitalsUpAndDown_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS 16
  • @@ -53,24 +53,24 @@ MasturbationWithVagina_Standing_HandDef - MasturbationWithVagina_Standing + MasturbationWithVagina_Standing
  • 0 Vagina - Motion_RubGenitals_FacingEW + Rimworld_Animations_Patch.RubGenitals_FacingEW 31
  • 1 Vagina - Motion_RubGenitals_FacingEW + Rimworld_Animations_Patch.RubGenitals_FacingEW 16
  • 2 Vagina - Motion_RubGenitals_FacingEW + Rimworld_Animations_Patch.RubGenitals_FacingEW 16
  • @@ -78,24 +78,24 @@ MasturbationWithVagina_InBed_HandDef - MasturbationWithVagina_InBed + MasturbationWithVagina_InBed
  • 0 Vagina - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 62
  • 1 Vagina - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 32
  • 2 Vagina - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 32
  • @@ -103,43 +103,43 @@ MasturbationWithAnus_Standing_HandDef - MasturbationWithAnus_Standing + MasturbationWithAnus_Standing
  • 0 Penis - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 31
  • 1 Penis - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 16
  • 2 Penis - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 16
  • 0 Vagina - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 31
  • 1 Vagina - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 16
  • 2 Vagina - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 16
  • @@ -147,43 +147,43 @@ MasturbationWithAnus_InBed_HandDef - MasturbationWithAnus_InBed + MasturbationWithAnus_InBed
  • 0 Penis - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 31
  • 1 Penis - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 16
  • 2 Penis - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 16
  • 0 Vagina - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 31
  • 1 Vagina - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 16
  • 2 Vagina - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 16
  • @@ -191,39 +191,39 @@ MasturbationWithBreasts_Standing_HandDef - MasturbationWithBreasts_Standing + MasturbationWithBreasts_Standing
  • 0 Breasts left - Motion_RubBreasts_FacingEW + Rimworld_Animations_Patch.RubBreasts_FacingEW 93
  • 1 Breasts left - Motion_RubBreasts_FacingEW + Rimworld_Animations_Patch.RubBreasts_FacingEW 64
  • 1 Vagina - Motion_RubGenitals_FacingEW + Rimworld_Animations_Patch.RubGenitals_FacingEW 32
  • 2 Breasts left - Motion_RubBreasts_FacingEW + Rimworld_Animations_Patch.RubBreasts_FacingEW 64
  • 2 Vagina - Motion_RubGenitals_FacingEW + Rimworld_Animations_Patch.RubGenitals_FacingEW 32
  • @@ -231,13 +231,13 @@ MasturbationWithBreasts_InBed_HandDef - MasturbationWithBreasts_InBed + MasturbationWithBreasts_InBed
  • 0 Breasts left - Motion_RubBreasts_FacingNS + Rimworld_Animations_Patch.RubBreasts_FacingNS 93
  • @@ -245,33 +245,33 @@ Breasts right true - Motion_RubBreasts_FacingNS + Rimworld_Animations_Patch.RubBreasts_FacingNS 93
  • 1 Breasts left - Motion_RubBreasts_FacingNS + Rimworld_Animations_Patch.RubBreasts_FacingNS 64
  • 1 Vagina - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 32
  • 2 Breasts left - Motion_RubBreasts_FacingNS + Rimworld_Animations_Patch.RubBreasts_FacingNS 64
  • 2 Vagina - Motion_RubGenitals_FacingNS + Rimworld_Animations_Patch.RubGenitals_FacingNS 32
  • @@ -279,39 +279,39 @@ MasturbationWithBreastsPlusPenis_Standing_HandDef - MasturbationWithBreastsPlusPenis_Standing + MasturbationWithBreastsPlusPenis_Standing
  • 0 Breasts left - Motion_RubBreasts_FacingEW + Rimworld_Animations_Patch.RubBreasts_FacingEW 93
  • 1 Breasts left - Motion_RubBreasts_FacingEW + Rimworld_Animations_Patch.RubBreasts_FacingEW 64
  • 1 Penis - Motion_StrokeGenitalsUpAndDown_FacingEW + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW 16
  • 2 Breasts left - Motion_RubBreasts_FacingEW + Rimworld_Animations_Patch.RubBreasts_FacingEW 64
  • 2 Penis - Motion_StrokeGenitalsUpAndDown_FacingEW + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW 16
  • @@ -319,13 +319,13 @@ MasturbationWithBreastsPlusPenis_InBed_HandDef - MasturbationWithBreastsPlusPenis_InBed + MasturbationWithBreastsPlusPenis_InBed
  • 0 Breasts left - Motion_RubBreasts_FacingNS + Rimworld_Animations_Patch.RubBreasts_FacingNS 93
  • @@ -333,33 +333,33 @@ Breasts right true - Motion_RubBreasts_FacingNS + Rimworld_Animations_Patch.RubBreasts_FacingNS 93
  • 1 Breasts left - Motion_RubBreasts_FacingNS + Rimworld_Animations_Patch.RubBreasts_FacingNS 64
  • 1 Penis - Motion_StrokeGenitalsUpAndDown_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS 16
  • 2 Breasts left - Motion_RubBreasts_FacingNS + Rimworld_Animations_Patch.RubBreasts_FacingNS 64
  • 2 Penis - Motion_StrokeGenitalsUpAndDown_FacingNS + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingNS 16
  • @@ -367,7 +367,7 @@ MutualMasturbation_HandDef - MutualMasturbation + MutualMasturbation @@ -376,7 +376,7 @@ 0 1 Penis - Motion_StrokeGenitalsUpAndDown_FacingEW + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW 25
  • @@ -384,7 +384,7 @@ 0 1 Penis - Motion_StrokeGenitalsUpAndDown_FacingEW + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW 30
  • @@ -392,7 +392,7 @@ 0 1 Penis - Motion_StrokeGenitalsUpAndDown_FacingEW + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW 15
  • @@ -400,7 +400,7 @@ 0 1 Penis - Motion_StrokeGenitalsUpAndDown_FacingEW + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW 15
  • @@ -410,7 +410,7 @@ 0 1 Vagina - Motion_RubGenitals_FacingEW + Rimworld_Animations_Patch.RubGenitals_FacingEW 25
  • @@ -418,7 +418,7 @@ 0 1 Vagina - Motion_RubGenitals_FacingEW + Rimworld_Animations_Patch.RubGenitals_FacingEW 30
  • @@ -426,7 +426,7 @@ 0 1 Vagina - Motion_RubGenitals_FacingEW + Rimworld_Animations_Patch.RubGenitals_FacingEW 15
  • @@ -434,7 +434,7 @@ 0 1 Vagina - Motion_RubGenitals_FacingEW + Rimworld_Animations_Patch.RubGenitals_FacingEW 15
  • @@ -444,7 +444,7 @@ 1 0 Penis - Motion_StrokeGenitalsUpAndDown_FacingEW + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW 25
  • @@ -452,7 +452,7 @@ 1 0 Penis - Motion_StrokeGenitalsUpAndDown_FacingEW + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW 30
  • @@ -460,7 +460,7 @@ 1 0 Penis - Motion_StrokeGenitalsUpAndDown_FacingEW + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW 15
  • @@ -468,7 +468,7 @@ 1 0 Penis - Motion_StrokeGenitalsUpAndDown_FacingEW + Rimworld_Animations_Patch.StrokeGenitalsUpAndDown_FacingEW 15
  • @@ -478,7 +478,7 @@ 1 0 Vagina - Motion_RubGenitals_FacingEW + Rimworld_Animations_Patch.RubGenitals_FacingEW 25
  • @@ -486,7 +486,7 @@ 1 0 Vagina - Motion_RubGenitals_FacingEW + Rimworld_Animations_Patch.RubGenitals_FacingEW 30
  • @@ -494,7 +494,7 @@ 1 0 Vagina - Motion_RubGenitals_FacingEW + Rimworld_Animations_Patch.RubGenitals_FacingEW 15
  • @@ -502,7 +502,7 @@ 1 0 Vagina - Motion_RubGenitals_FacingEW + Rimworld_Animations_Patch.RubGenitals_FacingEW 15
  • diff --git a/Defs/HediffDefs.xml b/Defs/HediffDefs.xml deleted file mode 100644 index 6d1f207..0000000 --- a/Defs/HediffDefs.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - Disquiet - - This person saw something that upset them and it's weighting on their thoughts. - -
  • - - false -
  • -
    -
    - - - Panicked - - This person saw something that has shaked them to their core. Will they run or fight? - -
  • - - false -
  • -
    -
    - - - Nauseated - - This poor soul saw something something so utterly foul that they just might be sick from the thought. - -
  • - - false -
  • -
    -
    - - - Indignant - - This person witnessed something quite distasteful and is going to give the offender a piece of their mind. - -
  • - - false -
  • -
    -
    - -
    diff --git a/Defs/JobDefs.xml b/Defs/JobDefs.xml deleted file mode 100644 index 2f09523..0000000 --- a/Defs/JobDefs.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - JoinInSex - Rimworld_Animations_Patch.JobDriver_JoinInSex - joining in on some fun. - false - - - \ No newline at end of file diff --git a/Defs/ThoughtDefs.xml b/Defs/ThoughtDefs.xml deleted file mode 100644 index 406dff9..0000000 --- a/Defs/ThoughtDefs.xml +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - SeenMasturbating - Thought_Memory - 1.0 - 3 - 0.5 - -
  • - - I'm so embarrassed! - -12 -
  • -
    -
    - - - SeenHavingSex - Thought_Memory - 1.0 - 3 - 0.5 - -
  • - - Well, that was awkward! - -8 -
  • -
    -
    - - - SeenMasturbatingExhibitionist - Thought_Memory - 1.0 - 1 - -
  • - - It's OK, come and have a closer look... - 4 -
  • -
    -
    - - - SeenHavingSexExhibitionist - Thought_Memory - 1.0 - 1 - -
  • - - Heheh, hope they enjoyed the show! - 6 -
  • -
    -
    - - - SawMasturbation - Thought_Memory - 1.0 - 1 - 0.5 - -
  • - - Argh! I'm so sorry! - -6 -
  • -
    -
    - - - SawSex - Thought_Memory - 1.0 - 1 - 0.5 - -
  • - - Jeez! Get a room! - -4 -
  • -
    -
    - - - SawMasturbationVoyeur - Thought_Memory - 1.0 - 1 - -
  • - - I think that awoke something in me... - 4 -
  • -
    -
    - - - SawSexVoyeur - Thought_Memory - 1.0 - 1 - -
  • - - Damn. So hot! - 6 -
  • -
    -
    - - - CaughtCheating - Thought_Memory - 10.0 - 300 - 1 - -
  • - - What have I done? {1}, please forgive me... - -10 -
  • -
    -
    - - - SeenCommittingTaboo - Thought_Memory - 2.0 - 1 - 0.5 - -
  • - - I'm so ashamed. - -15 -
  • -
    -
    - - - SeenCommittingMajorTaboo - Thought_Memory - 3.0 - 1 - 0.5 - -
  • - - How can I face the world after this? - -20 -
  • -
    -
    - - - SawTaboo - Thought_Memory - 2.0 - 1 - 0.5 - -
  • - - What vile degeneracy! - -10 -
  • -
    -
    - - - SawMajorTaboo - Thought_Memory - 3.0 - 1 - 0.5 - -
  • - - Disgusting vermin! You'll get yours! - -15 -
  • -
    -
    - -
    diff --git a/Defs/ThoughtDefs/ThoughtDefsBeastiality.xml b/Defs/ThoughtDefs/ThoughtDefsBeastiality.xml deleted file mode 100644 index bd913cd..0000000 --- a/Defs/ThoughtDefs/ThoughtDefsBeastiality.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - SawBestiality_Abhorrent - 3 - 3 - -
  • Zoophile
  • -
    - Panicked - 1 - -
  • - - How could that violate that poor animal like that?! - -20 -
  • -
    -
    - - - SawBestiality_Horrible - 3 - 3 - -
  • Zoophile
  • -
    - Disquiet - 1 - -
  • - - Get away from that poor creature! - -15 -
  • -
    -
    - - - SawBestiality_Disapproved - 3 - 3 - -
  • Zoophile
  • -
    - Disquiet - 1 - -
  • - - Ew. Just. Ew. - -10 -
  • -
    -
    - - - SawBestiality_Acceptable - 3 - 3 - -
  • Zoophile
  • -
    - 1 - -
  • - - Um, does your 'friend' want some kibble? - -4 -
  • -
    -
    - - - SawBestiality_Honorable - 3 - 3 - 1 - -
  • - - The bond between us and our animals is strong. - +2 -
  • -
    -
    - -
    diff --git a/Defs/ThoughtDefs/ThoughtDefsNecrophilia.xml b/Defs/ThoughtDefs/ThoughtDefsNecrophilia.xml deleted file mode 100644 index 4ba6c68..0000000 --- a/Defs/ThoughtDefs/ThoughtDefsNecrophilia.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - SawNecrophilia_Abhorrent - 3 - 3 - -
  • Necrophiliac
  • -
    - Nauseated - 1 - -
  • - - *Urp* I'm gunna hurl! - -20 -
  • -
    -
    - - - SawNecrophilia_Horrible - 3 - 3 - -
  • Necrophiliac
  • -
    - Disquiet - 1 - -
  • - - What were they thinking?! - -15 -
  • -
    -
    - - - SawNecrophilia_Disapproved - 3 - 3 - -
  • Necrophiliac
  • -
    - Disquiet - 1 - -
  • - - Even the dead get no rest here. - -10 -
  • -
    -
    - - - SawNecrophilia_Acceptable - 3 - 3 - 1 - -
  • - - I just hope they bury it when they're done. - -4 -
  • -
    -
    - - - SawNecrophilia_Honorable - 3 - 3 - 1 - -
  • - - Passion transcends the grave. - +2 -
  • -
    -
    - -
    diff --git a/Defs/ThoughtDefs/ThoughtDefsRape.xml b/Defs/ThoughtDefs/ThoughtDefsRape.xml deleted file mode 100644 index 2800c98..0000000 --- a/Defs/ThoughtDefs/ThoughtDefsRape.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - SawRape_Abhorrent - 3 - 3 - -
  • Rapist
  • -
    - Panicked - 1 - -
  • - - Someone please help that poor soul! - -20 -
  • -
    -
    - - - SawRape_Horrible - 3 - 3 - -
  • Rapist
  • -
    - Disquiet - 1 - -
  • - - I feel all shaky. - -15 -
  • -
    -
    - - - SawRape_Disapproved - 3 - 3 - -
  • Rapist
  • -
    - Disquiet - 1 - -
  • - - Is this what life is going to be here? - -10 -
  • -
    -
    - - - SawRape_Acceptable - 3 - 3 - 1 - -
  • - - Ah. Um, carry on... - -4 -
  • -
    -
    - - - SawRape_Honorable - 3 - 3 - 1 - -
  • - - The strong claim their due from the weak. - +2 -
  • -
    -
    - -
    diff --git a/Defs/ThoughtDefs/ThoughtDefsXenophilia.xml b/Defs/ThoughtDefs/ThoughtDefsXenophilia.xml deleted file mode 100644 index a36e49e..0000000 --- a/Defs/ThoughtDefs/ThoughtDefsXenophilia.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - SawHAR_AlienDating_Prohibited - 3 - 3 - Indignant - 1 - -
  • - - Filthy degenerates! - -15 -
  • -
    -
    - - - SawHAR_AlienDating_Horrible - 3 - 3 - Disquiet - 1 - -
  • - - Oh! That's not right... - -10 -
  • -
    -
    - - - SawHAR_AlienDating_Acceptable - 3 - 3 - 1 - -
  • - - Oops, sorry about walking in on you! - -4 -
  • -
    -
    - - - SawHAR_AlienDating_Preferred - 3 - 3 - 1 - -
  • - - I wonder what their kids would look like? - +1 -
  • -
    -
    - - - SawHAR_AlienDating_Know_Honorable - 3 - 3 - 1 - -
  • - - A blending of species will make us stronger. - +2 -
  • -
    -
    - -
    diff --git a/Defs/ThoughtDefs/ThoughtsDefsUnderwear.xml b/Defs/ThoughtDefs/ThoughtsDefsUnderwear.xml deleted file mode 100644 index 93d0f0d..0000000 --- a/Defs/ThoughtDefs/ThoughtsDefsUnderwear.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - ExposeUnderwear - Rimworld_Animations_Patch.ThoughtWorker_ExposedUnderwear - true - -
  • - - People can see my underwear, it's embarassing. - -2 -
  • -
  • - - People can see my underwear. It's a bit thrilling, to be honest! - 1 -
  • -
    -
    - -
    diff --git a/Languages/English/Keyed/SettingsKeys.xml b/Languages/English/Keyed/SettingsKeys.xml index 5aa3f9c..fca9f69 100644 --- a/Languages/English/Keyed/SettingsKeys.xml +++ b/Languages/English/Keyed/SettingsKeys.xml @@ -7,22 +7,30 @@ General Options - People require privacy for lovin' - If someone encounters another engaged in lovin' related activities, both individuals will feel embarrassed, depending on their traits and ideology. + People have opinions about having sex in front of others + 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. People will react if they encounter their partner cheating - Their reaction depends on their traits and ideology. This is not considered committing taboo by default. + 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. People will react to beastiality - Their reaction depends on their traits and ideology. This is considered committing a major taboo by default. + Their reaction will depend on their Bestiality precept (Sexperience - Ideology) and whether they are a Zoophile. Beastiality is considered a major taboo by default. People will react to rape - Their reaction depends on their traits and ideology. This is considered committing a major taboo by default. - People will ignore rape if the victim is a prisoner or slave + 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. + People will ignore a rape if the victim is a prisoner or slave People will react to necrophilia - Their reaction depends on their traits and ideology. This is considered committing a major taboo by default. + 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. People will react to couplings between humanoids of different species - Their reaction depends on their traits and ideology. This is not considered committing taboo by default. + 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. + People will react to necrophilia + 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. + People will react to incest + Their reaction will depend on their Incest precept (Sexperience - Ideology). Incest is disapproved of by default. + Witnessing a major taboo will result in an extreme reaction Individuals who witness something that seriously upsets them will cause them to flee, or even possibly attack the offender. - + Prisoners and slaves ignore sex + Prisoners and slaves have learnt it is better to simply ignore any sexual acts occurring around them. + People belong to other factions will ignore sex + The other factions will turn a blind eye to any sexual acts occurring around them. People who are lovin' have a chance to invite passersby to join them for some fun (default is 0.25) 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. Hide names when getting some lovin' @@ -34,11 +42,13 @@ Auto-scale animation offsets based on body size Turning this setting on may help when using alien races which are much larger or smaller than regular humans. - Add animated hands to animations - Requires RimNudeWorld. This feature can be performance intense. If you have large colonies (50+ colonist), you may wish to turn this off. Redraw hair in pawn portraits 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. - + Patch RimWorld Animation System + 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. + Add animated hands to animations + Requires RimNudeWorld. This feature can be performance intense. If you have large colonies (50+ colonist), you may wish to turn this off. + Clothing options Crop the bottoms of worn shirts, tank tops, etc. when not wearing pants or a skirt 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. diff --git a/Patches/UnderWhere_Clothing.xml b/Patches/UnderWhere_Clothing.xml deleted file mode 100644 index 8f5af27..0000000 --- a/Patches/UnderWhere_Clothing.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - -
  • UnderWhere
  • -
    - - Always - - -
  • - Defs/ThingDef[defName="UnderWhere_Panties" or defName="UnderWhere_Boxers" or defName="UnderWhere_Loincloth"]/apparel/bodyPartGroups - - -
  • GenitalsBPG
  • - - - - -
  • - Defs/ThingDef[defName="UnderWhere_Bra" or defName="UnderWhere_Chestwrap"]/apparel/bodyPartGroups - - -
  • ChestBPG
  • - - - - -
    -
    -
    -
    \ No newline at end of file diff --git a/Patches/s16_Clothing.xml b/Patches/s16_Clothing.xml deleted file mode 100644 index cf4d3f0..0000000 --- a/Patches/s16_Clothing.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - -
  • S16's Extension
  • -
    - - Always - - -
  • - Defs/ThingDef/thingCategories[li="S16_Underwear"]/../apparel/bodyPartGroups - - -
  • GenitalsBPG
  • - - - - -
    -
    -
    -
    \ No newline at end of file diff --git a/Source/.vs/Rimworld-Animations-Patch/v16/.suo b/Source/.vs/Rimworld-Animations-Patch/v16/.suo index 9851ffb..5f262b8 100644 Binary files a/Source/.vs/Rimworld-Animations-Patch/v16/.suo and b/Source/.vs/Rimworld-Animations-Patch/v16/.suo differ diff --git a/Source/Rimworld-Animations-Patch.csproj b/Source/Rimworld-Animations-Patch.csproj index e4bdb6d..06ea0ac 100644 --- a/Source/Rimworld-Animations-Patch.csproj +++ b/Source/Rimworld-Animations-Patch.csproj @@ -19,7 +19,7 @@ true full false - ..\1.3\Assemblies\ + ..\1.4\Assemblies\ DEBUG;TRACE prompt 4 @@ -42,7 +42,7 @@ False - ..\..\..\..\..\workshop\content\294100\839005762\1.3\Assemblies\AlienRace.dll + ..\..\..\..\..\workshop\content\294100\839005762\1.4\Assemblies\AlienRace.dll False @@ -66,34 +66,25 @@ False - ..\..\rimnude-unofficial-master\1.3 Assembly\Assemblies\RimNudeWorld.dll + ..\..\rimnude-unofficial-master\Assembly Folders\1.4 Assembly\Assemblies\RimNudeWorld.dll False - - False - ..\..\rimworld-animations-master\1.3\Assemblies\Rimworld-Animations.dll + + ..\..\rimworld-animations-master\1.4\Assemblies\Rimworld-Animations.dll False - - False - ..\..\rjw-master\1.3\Assemblies\RJW.dll + + ..\..\RJW\1.4\Assemblies\RJW.dll False - ..\..\rjw-events-master\1.3\Assemblies\RJW-Events.dll - False - - - ..\..\rjw-toys-and-masturbation-master\Assemblies\RJW-ToysAndMasturbation.dll - False - - - ..\..\rjw-sexperience-ideology-master\1.3\Assemblies\RJWSexperience.Ideology.dll + ..\..\rjw-events-master\1.4\Assemblies\RJW-Events.dll False + ..\..\..\RimWorldWin64_Data\Managed\UnityEngine.dll False @@ -117,20 +108,32 @@ + + + + + + + + + + + + + + - - @@ -149,7 +152,6 @@ - \ No newline at end of file diff --git a/Source/Scripts/Comps/CompApparelVisibility.cs b/Source/Scripts/Comps/CompApparelVisibility.cs index 4e3286a..53d94d3 100644 --- a/Source/Scripts/Comps/CompApparelVisibility.cs +++ b/Source/Scripts/Comps/CompApparelVisibility.cs @@ -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; diff --git a/Source/Scripts/Comps/CompPawnSexData.cs b/Source/Scripts/Comps/CompPawnSexData.cs index 61a1fb5..151889c 100644 --- a/Source/Scripts/Comps/CompPawnSexData.cs +++ b/Source/Scripts/Comps/CompPawnSexData.cs @@ -16,12 +16,13 @@ namespace Rimworld_Animations_Patch public Graphic handGraphic = null; public List hands = new List(); + public float sizeOfPenis = 0f; + public float sizeOfBreasts = 0f; + public Dictionary bodyAddonData = new Dictionary(); public Dictionary bodyAddonDataPortraits = new Dictionary(); 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); - } - } } } diff --git a/Source/Scripts/Defs/ActorAddon.cs b/Source/Scripts/Defs/ActorAddon.cs new file mode 100644 index 0000000..55df53b --- /dev/null +++ b/Source/Scripts/Defs/ActorAddon.cs @@ -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; + } + } +} diff --git a/Source/Scripts/Defs/ActorAddonDef.cs b/Source/Scripts/Defs/ActorAddonDef.cs new file mode 100644 index 0000000..378e224 --- /dev/null +++ b/Source/Scripts/Defs/ActorAddonDef.cs @@ -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; + } +} diff --git a/Source/Scripts/Defs/ActorAnimationData.cs b/Source/Scripts/Defs/ActorAnimationData.cs index 036d681..d18a56a 100644 --- a/Source/Scripts/Defs/ActorAnimationData.cs +++ b/Source/Scripts/Defs/ActorAnimationData.cs @@ -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; } } } diff --git a/Source/Scripts/Defs/AddonKeyFrame.cs b/Source/Scripts/Defs/AddonKeyFrame.cs new file mode 100644 index 0000000..4dd3eab --- /dev/null +++ b/Source/Scripts/Defs/AddonKeyFrame.cs @@ -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; + } + } +} diff --git a/Source/Scripts/Defs/BodyAddonData.cs b/Source/Scripts/Defs/BodyAddonData.cs index 384849a..3297d9a 100644 --- a/Source/Scripts/Defs/BodyAddonData.cs +++ b/Source/Scripts/Defs/BodyAddonData.cs @@ -16,7 +16,7 @@ namespace Rimworld_Animations_Patch public BodyPartRecord bodyPartRecord; public List bodyAddonOffsets = new List(); 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(); 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; } } diff --git a/Source/Scripts/Defs/HandAnimationDef.cs b/Source/Scripts/Defs/HandAnimationDef.cs index 8a0f24d..ac4e0c4 100644 --- a/Source/Scripts/Defs/HandAnimationDef.cs +++ b/Source/Scripts/Defs/HandAnimationDef.cs @@ -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 = new List(); } @@ -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; + } + } } } diff --git a/Source/Scripts/Extensions/PawnAnimationClipExt.cs b/Source/Scripts/Extensions/PawnAnimationClipExt.cs new file mode 100644 index 0000000..8727b2a --- /dev/null +++ b/Source/Scripts/Extensions/PawnAnimationClipExt.cs @@ -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 addons = new List(); + + 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; + } + } + } + } +} diff --git a/Source/Scripts/Extensions/PawnExtension.cs b/Source/Scripts/Extensions/PawnExtension.cs index 6040ddc..61c660b 100644 --- a/Source/Scripts/Extensions/PawnExtension.cs +++ b/Source/Scripts/Extensions/PawnExtension.cs @@ -85,14 +85,14 @@ namespace Rimworld_Animations_Patch if (pawn.GetSexReceiver() != null) { - List partners = (pawn.GetSexReceiver().jobs.curDriver as JobDriver_SexBaseReciever).parteners.ToList(); + List 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 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.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() == null) return null; @@ -192,82 +121,9 @@ namespace Rimworld_Animations_Patch int currentStage = (int)AccessTools.Field(typeof(CompBodyAnimator), "curStage").GetValue(pawn.TryGetComp()); int stageTicks = (int)AccessTools.Field(typeof(CompBodyAnimator), "stageTicks").GetValue(pawn.TryGetComp()); Rot4 actorFacing = (Rot4)AccessTools.Field(typeof(CompBodyAnimator), "bodyFacing").GetValue(pawn.TryGetComp()); + bool isMirrored = pawn.TryGetComp().Mirror; - return new ActorAnimationData(animationDef, actorID, currentStage, stageTicks, actorFacing); - } - - public static List 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 traits = new List() { "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 traits = new List() { "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.GetNamedSilentFail(trait); - - if (traitDef == null) - { traitDef = DefDatabase.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); } } } diff --git a/Source/Scripts/Extensions/PawnKeyframeExt.cs b/Source/Scripts/Extensions/PawnKeyframeExt.cs new file mode 100644 index 0000000..ac658d6 --- /dev/null +++ b/Source/Scripts/Extensions/PawnKeyframeExt.cs @@ -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 addonKeyframes; + + public AddonKeyframe GetAddonKeyframe(string addonName) + { + return addonKeyframes.FirstOrDefault(x => x.AddonName == addonName); + } + } +} diff --git a/Source/Scripts/Extensions/StringExtension.cs b/Source/Scripts/Extensions/StringExtension.cs new file mode 100644 index 0000000..d033c9f --- /dev/null +++ b/Source/Scripts/Extensions/StringExtension.cs @@ -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; + } + } +} diff --git a/Source/Scripts/HandMotions/HandMotion.cs b/Source/Scripts/HandMotions/HandMotion.cs new file mode 100644 index 0000000..12f1418 --- /dev/null +++ b/Source/Scripts/HandMotions/HandMotion.cs @@ -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); + } +} diff --git a/Source/Scripts/HandMotions/RubBreasts_FacingEW.cs b/Source/Scripts/HandMotions/RubBreasts_FacingEW.cs new file mode 100644 index 0000000..8f64989 --- /dev/null +++ b/Source/Scripts/HandMotions/RubBreasts_FacingEW.cs @@ -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; + } + } +} diff --git a/Source/Scripts/HandMotions/RubBreasts_FacingNS.cs b/Source/Scripts/HandMotions/RubBreasts_FacingNS.cs new file mode 100644 index 0000000..447749b --- /dev/null +++ b/Source/Scripts/HandMotions/RubBreasts_FacingNS.cs @@ -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; + } + } +} diff --git a/Source/Scripts/HandMotions/RubGenitals_FacingEW.cs b/Source/Scripts/HandMotions/RubGenitals_FacingEW.cs new file mode 100644 index 0000000..d8f645e --- /dev/null +++ b/Source/Scripts/HandMotions/RubGenitals_FacingEW.cs @@ -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; + } + } +} diff --git a/Source/Scripts/HandMotions/RubGenitals_FacingNS.cs b/Source/Scripts/HandMotions/RubGenitals_FacingNS.cs new file mode 100644 index 0000000..4c2747c --- /dev/null +++ b/Source/Scripts/HandMotions/RubGenitals_FacingNS.cs @@ -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; + } + } +} diff --git a/Source/Scripts/HandMotions/StrokeGenitalsUpAndDownShort_FacingNS.cs b/Source/Scripts/HandMotions/StrokeGenitalsUpAndDownShort_FacingNS.cs new file mode 100644 index 0000000..82eb51b --- /dev/null +++ b/Source/Scripts/HandMotions/StrokeGenitalsUpAndDownShort_FacingNS.cs @@ -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; + } + } +} diff --git a/Source/Scripts/HandMotions/StrokeGenitalsUpAndDown_FacingEW.cs b/Source/Scripts/HandMotions/StrokeGenitalsUpAndDown_FacingEW.cs new file mode 100644 index 0000000..f2e10a5 --- /dev/null +++ b/Source/Scripts/HandMotions/StrokeGenitalsUpAndDown_FacingEW.cs @@ -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; + } + } +} diff --git a/Source/Scripts/HandMotions/StrokeGenitalsUpAndDown_FacingNS.cs b/Source/Scripts/HandMotions/StrokeGenitalsUpAndDown_FacingNS.cs new file mode 100644 index 0000000..d3cf120 --- /dev/null +++ b/Source/Scripts/HandMotions/StrokeGenitalsUpAndDown_FacingNS.cs @@ -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; + } + } +} diff --git a/Source/Scripts/Patches/HarmonyPatch_BabiesAndChildren.cs b/Source/Scripts/Patches/HarmonyPatch_BabiesAndChildren.cs index 7faf36f..80455f4 100644 --- a/Source/Scripts/Patches/HarmonyPatch_BabiesAndChildren.cs +++ b/Source/Scripts/Patches/HarmonyPatch_BabiesAndChildren.cs @@ -29,7 +29,7 @@ namespace Rimworld_Animations_Patch }))(); } - catch (TypeLoadException ex) { } + catch (TypeLoadException) { } } public static bool Prefix_ShouldNotDrawAddonsForPawn(ref bool __result, Pawn pawn) diff --git a/Source/Scripts/Patches/HarmonyPatch_JobDriver.cs b/Source/Scripts/Patches/HarmonyPatch_JobDriver.cs index 84231ee..01c55af 100644 --- a/Source/Scripts/Patches/HarmonyPatch_JobDriver.cs +++ b/Source/Scripts/Patches/HarmonyPatch_JobDriver.cs @@ -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; diff --git a/Source/Scripts/Patches/HarmonyPatch_PatchAll.cs b/Source/Scripts/Patches/HarmonyPatch_PatchAll.cs index 96f6280..2be3ea5 100644 --- a/Source/Scripts/Patches/HarmonyPatch_PatchAll.cs +++ b/Source/Scripts/Patches/HarmonyPatch_PatchAll.cs @@ -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); } } } } diff --git a/Source/Scripts/Patches/HarmonyPatch_PawnRenderer.cs b/Source/Scripts/Patches/HarmonyPatch_PawnRenderer.cs index 84d8ce3..ffe0756 100644 --- a/Source/Scripts/Patches/HarmonyPatch_PawnRenderer.cs +++ b/Source/Scripts/Patches/HarmonyPatch_PawnRenderer.cs @@ -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 Transpiler(IEnumerable instructions) - { - List 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) diff --git a/Source/Scripts/Patches/HarmonyPatch_RJW.cs b/Source/Scripts/Patches/HarmonyPatch_RJW.cs index 3c986a7..debb74f 100644 --- a/Source/Scripts/Patches/HarmonyPatch_RJW.cs +++ b/Source/Scripts/Patches/HarmonyPatch_RJW.cs @@ -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 candidates = new List(); - 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.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 interactionDefs = DefDatabase.AllDefs.Where(x => x.HasModExtension()).ToList(); + IEnumerable interactionDefs = DefDatabase.AllDefs.Where(x => x.HasModExtension()); Dictionary interactionsPlusWeights = new Dictionary(); foreach (InteractionDef interactionDef in interactionDefs) @@ -161,7 +120,6 @@ namespace Rimworld_Animations_Patch { return; } // Get animation data - AnimationDef anim = __instance.pawn.GetAnimationData()?.animationDef; List 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 kissingAnims = DefDatabase.AllDefs.Where(x => x.defName.Contains("Kiss")).ToList(); - AnimationDef anim = kissingAnims[Random.Range(0, kissingAnims.Count)]; + IEnumerable kissingAnims = DefDatabase.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 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 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; } diff --git a/Source/Scripts/Patches/HarmonyPatch_RJWEvents.cs b/Source/Scripts/Patches/HarmonyPatch_RJWEvents.cs index 4f3a569..c044d78 100644 --- a/Source/Scripts/Patches/HarmonyPatch_RJWEvents.cs +++ b/Source/Scripts/Patches/HarmonyPatch_RJWEvents.cs @@ -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() != null && x.TryGetComp().isBeingWorn.HasValue)) + if (pawn.apparel.WornApparel.NullOrEmpty() || pawn.apparel.WornApparel.Any(x => x.TryGetComp() != null && x.TryGetComp().isBeingWorn.HasValue)) { __result = true; } } diff --git a/Source/Scripts/Patches/HarmonyPatch_RimNudeWorld.cs b/Source/Scripts/Patches/HarmonyPatch_RimNudeWorld.cs index d2e57d0..982618e 100644 --- a/Source/Scripts/Patches/HarmonyPatch_RimNudeWorld.cs +++ b/Source/Scripts/Patches/HarmonyPatch_RimNudeWorld.cs @@ -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; } - } + }*/ } diff --git a/Source/Scripts/Patches/HarmonyPatch_Rimworld_Animations.cs b/Source/Scripts/Patches/HarmonyPatch_Rimworld_Animations.cs index 5c3e632..ed8157a 100644 --- a/Source/Scripts/Patches/HarmonyPatch_Rimworld_Animations.cs +++ b/Source/Scripts/Patches/HarmonyPatch_Rimworld_Animations.cs @@ -38,7 +38,7 @@ namespace Rimworld_Animations_Patch CompPawnSexData comp = participant.TryGetComp(); if (comp == null) return; - comp.UpdateHands(); + comp.UpdateBodyPartCountAndSize(); } } @@ -48,7 +48,7 @@ namespace Rimworld_Animations_Patch CompPawnSexData comp = __instance.pawn.TryGetComp(); if (comp == null) return; - comp.handAnimationDef = DefDatabase.AllDefs.FirstOrDefault(x => x.animationDefName == __instance.pawn?.GetAnimationData()?.animationDef?.defName); + comp.handAnimationDef = DefDatabase.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 bodyAddons = alienProps.alienRace.generalSettings.alienPartGenerator.bodyAddons; + AlienPartGenerator.AlienComp alienComp = pawn.GetComp(); + CompBodyAnimator animatorComp = pawn.TryGetComp(); + CompPawnSexData sexDataComp = pawn.TryGetComp(); + ActorAnimationData pawnAnimationData = pawn?.GetAnimationData(); // Try to draw apparel thrown on ground if (ApparelSettings.clothesThrownOnGround) { ApparelAnimationUtility.TryToDrawApparelOnFloor(pawn); } - // Get actor components and body addons - List bodyAddons = alienProps.alienRace.generalSettings.alienPartGenerator.bodyAddons.ToList(); - AlienPartGenerator.AlienComp alienComp = pawn.GetComp(); - CompBodyAnimator animatorComp = pawn.TryGetComp(); - CompPawnSexData sexDataComp = pawn.TryGetComp(); - 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(x, i)).OrderBy(x => x.Key.offsets.GetOffset(rotation).layerOffset).ToList(); - List idxBodyAddons = sortedBodyAddons.Select(x => x.Value).ToList(); + var sortedBodyAddons = bodyAddons.Select((x, i) => new KeyValuePair(x, i)).OrderBy(x => x.Key.offsets.GetOffset(rotation).layerOffset); + IEnumerable 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()?.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 diff --git a/Source/Scripts/Patches/HarmonyPatch_ThoughtWorkers.cs b/Source/Scripts/Patches/HarmonyPatch_ThoughtWorkers.cs deleted file mode 100644 index be5997a..0000000 --- a/Source/Scripts/Patches/HarmonyPatch_ThoughtWorkers.cs +++ /dev/null @@ -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; - } - } -} diff --git a/Source/Scripts/Settings/ApparelSettings.cs b/Source/Scripts/Settings/ApparelSettings.cs index 904d566..7ec5b5d 100644 --- a/Source/Scripts/Settings/ApparelSettings.cs +++ b/Source/Scripts/Settings/ApparelSettings.cs @@ -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 thingDefs = new List(); + private IEnumerable shortListedApparelDefs = new List(); + private IEnumerable allApparelDefs = new List(); + + private IEnumerable relevantModContentPacks = new List(); + 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 options = new List { }; + + 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 options = new List { 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; diff --git a/Source/Scripts/Settings/BasicSettings.cs b/Source/Scripts/Settings/BasicSettings.cs index a8c24df..8bd84b5 100644 --- a/Source/Scripts/Settings/BasicSettings.cs +++ b/Source/Scripts/Settings/BasicSettings.cs @@ -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); } diff --git a/Source/Scripts/ThoughtWorkers/ThoughtWorker_ExposedUnderwear.cs b/Source/Scripts/ThoughtWorkers/ThoughtWorker_ExposedUnderwear.cs deleted file mode 100644 index 933df5f..0000000 --- a/Source/Scripts/ThoughtWorkers/ThoughtWorker_ExposedUnderwear.cs +++ /dev/null @@ -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; - } - } -} diff --git a/Source/Scripts/Utilities/AnimationPatchUtility.cs b/Source/Scripts/Utilities/AnimationPatchUtility.cs index 453e9f1..cea6963 100644 --- a/Source/Scripts/Utilities/AnimationPatchUtility.cs +++ b/Source/Scripts/Utilities/AnimationPatchUtility.cs @@ -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; diff --git a/Source/Scripts/Utilities/ApparelAnimationUtility.cs b/Source/Scripts/Utilities/ApparelAnimationUtility.cs index 23c2e89..f2dc2ea 100644 --- a/Source/Scripts/Utilities/ApparelAnimationUtility.cs +++ b/Source/Scripts/Utilities/ApparelAnimationUtility.cs @@ -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; } diff --git a/Source/Scripts/Utilities/HandAnimationUtility.cs b/Source/Scripts/Utilities/HandAnimationUtility.cs index 0d18c39..b53686d 100644 --- a/Source/Scripts/Utilities/HandAnimationUtility.cs +++ b/Source/Scripts/Utilities/HandAnimationUtility.cs @@ -13,27 +13,21 @@ namespace Rimworld_Animations_Patch { public static BodyPartDef handDef; - public static bool BodyPartIsBeingTouched(Pawn pawn, string bodypartFilePath, out List handAnimationData) + public static bool BodyPartIsBeingTouched(Pawn pawn, ActorAnimationData actorAnimationData, string bodypartFilePath, out List handAnimationData) { handAnimationData = new List(); HandAnimationDef handAnimationDef = pawn?.TryGetComp()?.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(); + 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().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().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().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(); @@ -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)) + if (BodyPartIsBeingTouched(pawn, pawnAnimationData, bodyAddonName, out List handAnimationData)) { foreach (HandAnimationData datum in handAnimationData) { diff --git a/Source/Scripts/Utilities/MathUtility.cs b/Source/Scripts/Utilities/MathUtility.cs index b602858..1c53244 100644 --- a/Source/Scripts/Utilities/MathUtility.cs +++ b/Source/Scripts/Utilities/MathUtility.cs @@ -33,14 +33,19 @@ namespace Rimworld_Animations_Patch { for (int radius = 1; radius < maxRadius; radius++) { - List cells = GenRadial.RadialCellsAround(pawn.Position, radius + 0.75f, false).Where(x => x.Standable(pawn.Map) && x.GetRoom(pawn.Map) == pawn.GetRoom())?.ToList(); + IEnumerable 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; + } } } diff --git a/Source/Scripts/Utilities/PatchDefOf.cs b/Source/Scripts/Utilities/PatchDefOf.cs index fcec121..c88c271 100644 --- a/Source/Scripts/Utilities/PatchDefOf.cs +++ b/Source/Scripts/Utilities/PatchDefOf.cs @@ -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; } } diff --git a/Source/Scripts/Utilities/SexInteractionUtility.cs b/Source/Scripts/Utilities/SexInteractionUtility.cs deleted file mode 100644 index dbbaae5..0000000 --- a/Source/Scripts/Utilities/SexInteractionUtility.cs +++ /dev/null @@ -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 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 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.GetNamedSilentFail("Xenophobia")) > 0; - bool isXenophile = pawn.HasTrait("Xenophobia") && pawn.story.traits.DegreeOfTrait(DefDatabase.GetNamedSilentFail("Xenophobia")) < 0; - - if (BasicSettings.worryAboutNecro && sexIsNecro && xxx.is_necrophiliac(pawn) == false) - { - thoughtDef = xxx.is_necrophiliac(pawn) ? DefDatabase.GetNamedSilentFail("SawNecrophilia_Honorable") : - pawn.HasPreceptForIssue("Necrophilia", out precept) ? DefDatabase.GetNamedSilentFail("Saw" + precept.def.defName) : - DefDatabase.GetNamedSilentFail("SawNecrophilia_Abhorrent"); - } - - else if (BasicSettings.worryAboutBeastiality && sexIsBeastial) - { - thoughtDef = xxx.is_zoophile(pawn) ? DefDatabase.GetNamedSilentFail("SawBeastility_Honorable") : - pawn.HasPreceptForIssue("Beastility", out precept) ? DefDatabase.GetNamedSilentFail("Saw" + precept.def.defName) : - DefDatabase.GetNamedSilentFail("SawBeastility_Abhorrent"); - } - - else if (BasicSettings.worryAboutRape && BasicSettings.ignoreSlaveRape == false && sexIsSlaveRape) - { - thoughtDef = xxx.is_rapist(pawn) ? DefDatabase.GetNamedSilentFail("SawRape_Honorable") : - pawn.HasPreceptForIssue("Rape", out precept) ? DefDatabase.GetNamedSilentFail("Saw" + precept.def.defName) : - DefDatabase.GetNamedSilentFail("SawRape_Abhorrent"); - } - - else if (BasicSettings.worryAboutRape && sexIsRape) - { - thoughtDef = xxx.is_rapist(pawn) ? DefDatabase.GetNamedSilentFail("SawRape_Honorable") : - pawn.HasPreceptForIssue("Rape", out precept) ? DefDatabase.GetNamedSilentFail("Saw" + precept.def.defName) : - DefDatabase.GetNamedSilentFail("SawRape_Abhorrent"); - } - - else if (BasicSettings.worryAboutXeno && sexIsXeno) - { - thoughtDef = isXenophobe ? DefDatabase.GetNamedSilentFail("SawHAR_AlienDating_Prohibited") : - isXenophile ? DefDatabase.GetNamedSilentFail("SawHAR_AlienDating_Honorable") : - pawn.HasPreceptForIssue("HAR_AlienDating", out precept) ? DefDatabase.GetNamedSilentFail("Saw" + precept.def.defName) : - DefDatabase.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() { 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() { 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.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.GetNamedSilentFail(pawnThoughtDefName) : null; - ThoughtDef witnessThoughtDef = BasicSettings.needPrivacy ? DefDatabase.GetNamedSilentFail(witnessThoughtDefName) : null; - - // Exhibitionist pawn - if (xxx.has_quirk(pawn, "Exhibitionist")) - { pawnThoughtDef = DefDatabase.GetNamedSilentFail(pawnThoughtDefName + "Exhibitionist"); } - - // Voyeuristic witness - if (xxx.has_quirk(witness, "Voyeur")) - { witnessThoughtDef = DefDatabase.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.GetNamedSilentFail("CaughtCheating")) == null) - { pawn.needs.mood.thoughts.memories.TryGainMemory(DefDatabase.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()?.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()?.TryToExclaim(); } - } - - return witnessJoiningSex; - } - } -} diff --git a/Source/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/Source/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache index bdbed12..5c8fd1d 100644 Binary files a/Source/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache and b/Source/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ diff --git a/Source/obj/Debug/Rimworld-Animations-Patch.csproj.CoreCompileInputs.cache b/Source/obj/Debug/Rimworld-Animations-Patch.csproj.CoreCompileInputs.cache index c13d4d7..c0f1592 100644 --- a/Source/obj/Debug/Rimworld-Animations-Patch.csproj.CoreCompileInputs.cache +++ b/Source/obj/Debug/Rimworld-Animations-Patch.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -80ac53cd1937a7f3bc413d1816a7df030fc583c6 +0035486d66161d603d82d58abd89b02b042a2e0c diff --git a/Source/obj/Debug/Rimworld-Animations-Patch.csproj.FileListAbsolute.txt b/Source/obj/Debug/Rimworld-Animations-Patch.csproj.FileListAbsolute.txt index 94ebc10..22744b5 100644 --- a/Source/obj/Debug/Rimworld-Animations-Patch.csproj.FileListAbsolute.txt +++ b/Source/obj/Debug/Rimworld-Animations-Patch.csproj.FileListAbsolute.txt @@ -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 diff --git a/Source/obj/Debug/Rimworld-Animations-Patch.csprojAssemblyReference.cache b/Source/obj/Debug/Rimworld-Animations-Patch.csprojAssemblyReference.cache index e9f773b..dfa0f5f 100644 Binary files a/Source/obj/Debug/Rimworld-Animations-Patch.csprojAssemblyReference.cache and b/Source/obj/Debug/Rimworld-Animations-Patch.csprojAssemblyReference.cache differ diff --git a/Source/obj/Debug/Rimworld-Animations-Patch.dll b/Source/obj/Debug/Rimworld-Animations-Patch.dll index 1c13061..41cfc9f 100644 Binary files a/Source/obj/Debug/Rimworld-Animations-Patch.dll and b/Source/obj/Debug/Rimworld-Animations-Patch.dll differ diff --git a/Source/obj/Debug/Rimworld-Animations-Patch.pdb b/Source/obj/Debug/Rimworld-Animations-Patch.pdb index 4ca4542..8a81570 100644 Binary files a/Source/obj/Debug/Rimworld-Animations-Patch.pdb and b/Source/obj/Debug/Rimworld-Animations-Patch.pdb differ