mirror of
				https://gitgud.io/LonelyRain/rjw-quirks.git
				synced 2024-08-15 00:03:31 +00:00 
			
		
		
		
	Initial upload
This commit is contained in:
		
							parent
							
								
									feb28b10a4
								
							
						
					
					
						commit
						7585da099c
					
				
					 106 changed files with 4860 additions and 0 deletions
				
			
		
							
								
								
									
										398
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										398
									
								
								.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,398 @@
 | 
			
		|||
## Ignore Visual Studio temporary files, build results, and
 | 
			
		||||
## files generated by popular Visual Studio add-ons.
 | 
			
		||||
##
 | 
			
		||||
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
 | 
			
		||||
 | 
			
		||||
# User-specific files
 | 
			
		||||
*.rsuser
 | 
			
		||||
*.suo
 | 
			
		||||
*.user
 | 
			
		||||
*.userosscache
 | 
			
		||||
*.sln.docstates
 | 
			
		||||
 | 
			
		||||
# User-specific files (MonoDevelop/Xamarin Studio)
 | 
			
		||||
*.userprefs
 | 
			
		||||
 | 
			
		||||
# Mono auto generated files
 | 
			
		||||
mono_crash.*
 | 
			
		||||
 | 
			
		||||
# Build results
 | 
			
		||||
[Dd]ebug/
 | 
			
		||||
[Dd]ebugPublic/
 | 
			
		||||
[Rr]elease/
 | 
			
		||||
[Rr]eleases/
 | 
			
		||||
x64/
 | 
			
		||||
x86/
 | 
			
		||||
[Ww][Ii][Nn]32/
 | 
			
		||||
[Aa][Rr][Mm]/
 | 
			
		||||
[Aa][Rr][Mm]64/
 | 
			
		||||
bld/
 | 
			
		||||
[Bb]in/
 | 
			
		||||
[Oo]bj/
 | 
			
		||||
[Ll]og/
 | 
			
		||||
[Ll]ogs/
 | 
			
		||||
 | 
			
		||||
# Visual Studio 2015/2017 cache/options directory
 | 
			
		||||
.vs/
 | 
			
		||||
# Uncomment if you have tasks that create the project's static files in wwwroot
 | 
			
		||||
#wwwroot/
 | 
			
		||||
 | 
			
		||||
# Visual Studio 2017 auto generated files
 | 
			
		||||
Generated\ Files/
 | 
			
		||||
 | 
			
		||||
# MSTest test Results
 | 
			
		||||
[Tt]est[Rr]esult*/
 | 
			
		||||
[Bb]uild[Ll]og.*
 | 
			
		||||
 | 
			
		||||
# NUnit
 | 
			
		||||
*.VisualState.xml
 | 
			
		||||
TestResult.xml
 | 
			
		||||
nunit-*.xml
 | 
			
		||||
 | 
			
		||||
# Build Results of an ATL Project
 | 
			
		||||
[Dd]ebugPS/
 | 
			
		||||
[Rr]eleasePS/
 | 
			
		||||
dlldata.c
 | 
			
		||||
 | 
			
		||||
# Benchmark Results
 | 
			
		||||
BenchmarkDotNet.Artifacts/
 | 
			
		||||
 | 
			
		||||
# .NET Core
 | 
			
		||||
project.lock.json
 | 
			
		||||
project.fragment.lock.json
 | 
			
		||||
artifacts/
 | 
			
		||||
 | 
			
		||||
# ASP.NET Scaffolding
 | 
			
		||||
ScaffoldingReadMe.txt
 | 
			
		||||
 | 
			
		||||
# StyleCop
 | 
			
		||||
StyleCopReport.xml
 | 
			
		||||
 | 
			
		||||
# Files built by Visual Studio
 | 
			
		||||
*_i.c
 | 
			
		||||
*_p.c
 | 
			
		||||
*_h.h
 | 
			
		||||
*.ilk
 | 
			
		||||
*.meta
 | 
			
		||||
*.obj
 | 
			
		||||
*.iobj
 | 
			
		||||
*.pch
 | 
			
		||||
*.pdb
 | 
			
		||||
*.ipdb
 | 
			
		||||
*.pgc
 | 
			
		||||
*.pgd
 | 
			
		||||
*.rsp
 | 
			
		||||
*.sbr
 | 
			
		||||
*.tlb
 | 
			
		||||
*.tli
 | 
			
		||||
*.tlh
 | 
			
		||||
*.tmp
 | 
			
		||||
*.tmp_proj
 | 
			
		||||
*_wpftmp.csproj
 | 
			
		||||
*.log
 | 
			
		||||
*.tlog
 | 
			
		||||
*.vspscc
 | 
			
		||||
*.vssscc
 | 
			
		||||
.builds
 | 
			
		||||
*.pidb
 | 
			
		||||
*.svclog
 | 
			
		||||
*.scc
 | 
			
		||||
 | 
			
		||||
# Chutzpah Test files
 | 
			
		||||
_Chutzpah*
 | 
			
		||||
 | 
			
		||||
# Visual C++ cache files
 | 
			
		||||
ipch/
 | 
			
		||||
*.aps
 | 
			
		||||
*.ncb
 | 
			
		||||
*.opendb
 | 
			
		||||
*.opensdf
 | 
			
		||||
*.sdf
 | 
			
		||||
*.cachefile
 | 
			
		||||
*.VC.db
 | 
			
		||||
*.VC.VC.opendb
 | 
			
		||||
 | 
			
		||||
# Visual Studio profiler
 | 
			
		||||
*.psess
 | 
			
		||||
*.vsp
 | 
			
		||||
*.vspx
 | 
			
		||||
*.sap
 | 
			
		||||
 | 
			
		||||
# Visual Studio Trace Files
 | 
			
		||||
*.e2e
 | 
			
		||||
 | 
			
		||||
# TFS 2012 Local Workspace
 | 
			
		||||
$tf/
 | 
			
		||||
 | 
			
		||||
# Guidance Automation Toolkit
 | 
			
		||||
*.gpState
 | 
			
		||||
 | 
			
		||||
# ReSharper is a .NET coding add-in
 | 
			
		||||
_ReSharper*/
 | 
			
		||||
*.[Rr]e[Ss]harper
 | 
			
		||||
*.DotSettings.user
 | 
			
		||||
 | 
			
		||||
# TeamCity is a build add-in
 | 
			
		||||
_TeamCity*
 | 
			
		||||
 | 
			
		||||
# DotCover is a Code Coverage Tool
 | 
			
		||||
*.dotCover
 | 
			
		||||
 | 
			
		||||
# AxoCover is a Code Coverage Tool
 | 
			
		||||
.axoCover/*
 | 
			
		||||
!.axoCover/settings.json
 | 
			
		||||
 | 
			
		||||
# Coverlet is a free, cross platform Code Coverage Tool
 | 
			
		||||
coverage*.json
 | 
			
		||||
coverage*.xml
 | 
			
		||||
coverage*.info
 | 
			
		||||
 | 
			
		||||
# Visual Studio code coverage results
 | 
			
		||||
*.coverage
 | 
			
		||||
*.coveragexml
 | 
			
		||||
 | 
			
		||||
# NCrunch
 | 
			
		||||
_NCrunch_*
 | 
			
		||||
.*crunch*.local.xml
 | 
			
		||||
nCrunchTemp_*
 | 
			
		||||
 | 
			
		||||
# MightyMoose
 | 
			
		||||
*.mm.*
 | 
			
		||||
AutoTest.Net/
 | 
			
		||||
 | 
			
		||||
# Web workbench (sass)
 | 
			
		||||
.sass-cache/
 | 
			
		||||
 | 
			
		||||
# Installshield output folder
 | 
			
		||||
[Ee]xpress/
 | 
			
		||||
 | 
			
		||||
# DocProject is a documentation generator add-in
 | 
			
		||||
DocProject/buildhelp/
 | 
			
		||||
DocProject/Help/*.HxT
 | 
			
		||||
DocProject/Help/*.HxC
 | 
			
		||||
DocProject/Help/*.hhc
 | 
			
		||||
DocProject/Help/*.hhk
 | 
			
		||||
DocProject/Help/*.hhp
 | 
			
		||||
DocProject/Help/Html2
 | 
			
		||||
DocProject/Help/html
 | 
			
		||||
 | 
			
		||||
# Click-Once directory
 | 
			
		||||
publish/
 | 
			
		||||
 | 
			
		||||
# Publish Web Output
 | 
			
		||||
*.[Pp]ublish.xml
 | 
			
		||||
*.azurePubxml
 | 
			
		||||
# Note: Comment the next line if you want to checkin your web deploy settings,
 | 
			
		||||
# but database connection strings (with potential passwords) will be unencrypted
 | 
			
		||||
*.pubxml
 | 
			
		||||
*.publishproj
 | 
			
		||||
 | 
			
		||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
 | 
			
		||||
# checkin your Azure Web App publish settings, but sensitive information contained
 | 
			
		||||
# in these scripts will be unencrypted
 | 
			
		||||
PublishScripts/
 | 
			
		||||
 | 
			
		||||
# NuGet Packages
 | 
			
		||||
*.nupkg
 | 
			
		||||
# NuGet Symbol Packages
 | 
			
		||||
*.snupkg
 | 
			
		||||
# The packages folder can be ignored because of Package Restore
 | 
			
		||||
**/[Pp]ackages/*
 | 
			
		||||
# except build/, which is used as an MSBuild target.
 | 
			
		||||
!**/[Pp]ackages/build/
 | 
			
		||||
# Uncomment if necessary however generally it will be regenerated when needed
 | 
			
		||||
#!**/[Pp]ackages/repositories.config
 | 
			
		||||
# NuGet v3's project.json files produces more ignorable files
 | 
			
		||||
*.nuget.props
 | 
			
		||||
*.nuget.targets
 | 
			
		||||
 | 
			
		||||
# Microsoft Azure Build Output
 | 
			
		||||
csx/
 | 
			
		||||
*.build.csdef
 | 
			
		||||
 | 
			
		||||
# Microsoft Azure Emulator
 | 
			
		||||
ecf/
 | 
			
		||||
rcf/
 | 
			
		||||
 | 
			
		||||
# Windows Store app package directories and files
 | 
			
		||||
AppPackages/
 | 
			
		||||
BundleArtifacts/
 | 
			
		||||
Package.StoreAssociation.xml
 | 
			
		||||
_pkginfo.txt
 | 
			
		||||
*.appx
 | 
			
		||||
*.appxbundle
 | 
			
		||||
*.appxupload
 | 
			
		||||
 | 
			
		||||
# Visual Studio cache files
 | 
			
		||||
# files ending in .cache can be ignored
 | 
			
		||||
*.[Cc]ache
 | 
			
		||||
# but keep track of directories ending in .cache
 | 
			
		||||
!?*.[Cc]ache/
 | 
			
		||||
 | 
			
		||||
# Others
 | 
			
		||||
ClientBin/
 | 
			
		||||
~$*
 | 
			
		||||
*~
 | 
			
		||||
*.dbmdl
 | 
			
		||||
*.dbproj.schemaview
 | 
			
		||||
*.jfm
 | 
			
		||||
*.pfx
 | 
			
		||||
*.publishsettings
 | 
			
		||||
orleans.codegen.cs
 | 
			
		||||
 | 
			
		||||
# Including strong name files can present a security risk
 | 
			
		||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
 | 
			
		||||
#*.snk
 | 
			
		||||
 | 
			
		||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
 | 
			
		||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
 | 
			
		||||
#bower_components/
 | 
			
		||||
 | 
			
		||||
# RIA/Silverlight projects
 | 
			
		||||
Generated_Code/
 | 
			
		||||
 | 
			
		||||
# Backup & report files from converting an old project file
 | 
			
		||||
# to a newer Visual Studio version. Backup files are not needed,
 | 
			
		||||
# because we have git ;-)
 | 
			
		||||
_UpgradeReport_Files/
 | 
			
		||||
Backup*/
 | 
			
		||||
UpgradeLog*.XML
 | 
			
		||||
UpgradeLog*.htm
 | 
			
		||||
ServiceFabricBackup/
 | 
			
		||||
*.rptproj.bak
 | 
			
		||||
 | 
			
		||||
# SQL Server files
 | 
			
		||||
*.mdf
 | 
			
		||||
*.ldf
 | 
			
		||||
*.ndf
 | 
			
		||||
 | 
			
		||||
# Business Intelligence projects
 | 
			
		||||
*.rdl.data
 | 
			
		||||
*.bim.layout
 | 
			
		||||
*.bim_*.settings
 | 
			
		||||
*.rptproj.rsuser
 | 
			
		||||
*- [Bb]ackup.rdl
 | 
			
		||||
*- [Bb]ackup ([0-9]).rdl
 | 
			
		||||
*- [Bb]ackup ([0-9][0-9]).rdl
 | 
			
		||||
 | 
			
		||||
# Microsoft Fakes
 | 
			
		||||
FakesAssemblies/
 | 
			
		||||
 | 
			
		||||
# GhostDoc plugin setting file
 | 
			
		||||
*.GhostDoc.xml
 | 
			
		||||
 | 
			
		||||
# Node.js Tools for Visual Studio
 | 
			
		||||
.ntvs_analysis.dat
 | 
			
		||||
node_modules/
 | 
			
		||||
 | 
			
		||||
# Visual Studio 6 build log
 | 
			
		||||
*.plg
 | 
			
		||||
 | 
			
		||||
# Visual Studio 6 workspace options file
 | 
			
		||||
*.opt
 | 
			
		||||
 | 
			
		||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
 | 
			
		||||
*.vbw
 | 
			
		||||
 | 
			
		||||
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
 | 
			
		||||
*.vbp
 | 
			
		||||
 | 
			
		||||
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
 | 
			
		||||
*.dsw
 | 
			
		||||
*.dsp
 | 
			
		||||
 | 
			
		||||
# Visual Studio 6 technical files
 | 
			
		||||
*.ncb
 | 
			
		||||
*.aps
 | 
			
		||||
 | 
			
		||||
# Visual Studio LightSwitch build output
 | 
			
		||||
**/*.HTMLClient/GeneratedArtifacts
 | 
			
		||||
**/*.DesktopClient/GeneratedArtifacts
 | 
			
		||||
**/*.DesktopClient/ModelManifest.xml
 | 
			
		||||
**/*.Server/GeneratedArtifacts
 | 
			
		||||
**/*.Server/ModelManifest.xml
 | 
			
		||||
_Pvt_Extensions
 | 
			
		||||
 | 
			
		||||
# Paket dependency manager
 | 
			
		||||
.paket/paket.exe
 | 
			
		||||
paket-files/
 | 
			
		||||
 | 
			
		||||
# FAKE - F# Make
 | 
			
		||||
.fake/
 | 
			
		||||
 | 
			
		||||
# CodeRush personal settings
 | 
			
		||||
.cr/personal
 | 
			
		||||
 | 
			
		||||
# Python Tools for Visual Studio (PTVS)
 | 
			
		||||
__pycache__/
 | 
			
		||||
*.pyc
 | 
			
		||||
 | 
			
		||||
# Cake - Uncomment if you are using it
 | 
			
		||||
# tools/**
 | 
			
		||||
# !tools/packages.config
 | 
			
		||||
 | 
			
		||||
# Tabs Studio
 | 
			
		||||
*.tss
 | 
			
		||||
 | 
			
		||||
# Telerik's JustMock configuration file
 | 
			
		||||
*.jmconfig
 | 
			
		||||
 | 
			
		||||
# BizTalk build output
 | 
			
		||||
*.btp.cs
 | 
			
		||||
*.btm.cs
 | 
			
		||||
*.odx.cs
 | 
			
		||||
*.xsd.cs
 | 
			
		||||
 | 
			
		||||
# OpenCover UI analysis results
 | 
			
		||||
OpenCover/
 | 
			
		||||
 | 
			
		||||
# Azure Stream Analytics local run output
 | 
			
		||||
ASALocalRun/
 | 
			
		||||
 | 
			
		||||
# MSBuild Binary and Structured Log
 | 
			
		||||
*.binlog
 | 
			
		||||
 | 
			
		||||
# NVidia Nsight GPU debugger configuration file
 | 
			
		||||
*.nvuser
 | 
			
		||||
 | 
			
		||||
# MFractors (Xamarin productivity tool) working folder
 | 
			
		||||
.mfractor/
 | 
			
		||||
 | 
			
		||||
# Local History for Visual Studio
 | 
			
		||||
.localhistory/
 | 
			
		||||
 | 
			
		||||
# Visual Studio History (VSHistory) files
 | 
			
		||||
.vshistory/
 | 
			
		||||
 | 
			
		||||
# BeatPulse healthcheck temp database
 | 
			
		||||
healthchecksdb
 | 
			
		||||
 | 
			
		||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
 | 
			
		||||
MigrationBackup/
 | 
			
		||||
 | 
			
		||||
# Ionide (cross platform F# VS Code tools) working folder
 | 
			
		||||
.ionide/
 | 
			
		||||
 | 
			
		||||
# Fody - auto-generated XML schema
 | 
			
		||||
FodyWeavers.xsd
 | 
			
		||||
 | 
			
		||||
# VS Code files for those working on multiple tools
 | 
			
		||||
.vscode/*
 | 
			
		||||
!.vscode/settings.json
 | 
			
		||||
!.vscode/tasks.json
 | 
			
		||||
!.vscode/launch.json
 | 
			
		||||
!.vscode/extensions.json
 | 
			
		||||
*.code-workspace
 | 
			
		||||
 | 
			
		||||
# Local History for Visual Studio Code
 | 
			
		||||
.history/
 | 
			
		||||
 | 
			
		||||
# Windows Installer files from build outputs
 | 
			
		||||
*.cab
 | 
			
		||||
*.msi
 | 
			
		||||
*.msix
 | 
			
		||||
*.msm
 | 
			
		||||
*.msp
 | 
			
		||||
 | 
			
		||||
# JetBrains Rider
 | 
			
		||||
*.sln.iml
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								1.4/Assemblies/RJW-Quirks.dll
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								1.4/Assemblies/RJW-Quirks.dll
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										116
									
								
								1.4/Defs/QuirkDefs/QuirkDef.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								1.4/Defs/QuirkDefs/QuirkDef.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,116 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
 | 
			
		||||
<Defs>
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
		<defName>Breeder</defName>
 | 
			
		||||
		<label>Breeder</label>
 | 
			
		||||
		<description>{pawn} has given birth so many times that {pawn_possessive} body has adapted to breeding. {pawn_possessive} pregnancies are shorter and produce more offspring.</description>
 | 
			
		||||
		<rarity>ForcedOnly</rarity>
 | 
			
		||||
		<hidden>true</hidden>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.Adder_OnRecordExceeding">
 | 
			
		||||
				<eventDef>RecordChanged</eventDef>
 | 
			
		||||
				<record>CountOfBirthHuman</record>
 | 
			
		||||
				<value>10</value>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.Adder_OnRecordExceeding">
 | 
			
		||||
				<eventDef>RecordChanged</eventDef>
 | 
			
		||||
				<record>CountOfBirthAnimal</record>
 | 
			
		||||
				<value>20</value>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ValueModifier_ApplyMultiplier">
 | 
			
		||||
				<valueName>maxLitterOnBirth</valueName>
 | 
			
		||||
				<multiplier>2.0</multiplier>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
		<defName>Fertile</defName>
 | 
			
		||||
		<label>Fertile</label>
 | 
			
		||||
		<description>{pawn} has unusually high fertility and so is more likely to have children.</description>
 | 
			
		||||
		<conflictingQuirks>
 | 
			
		||||
			<li>Infertile</li>
 | 
			
		||||
		</conflictingQuirks>
 | 
			
		||||
		<ownerRequirements>
 | 
			
		||||
			<li>
 | 
			
		||||
				<pawnSelector Class="rjwquirks.Modules.Shared.PawnSelectors.HasFertility"></pawnSelector>
 | 
			
		||||
				<rejectionReason>RaceHasNoFertility</rejectionReason>
 | 
			
		||||
			</li>
 | 
			
		||||
		</ownerRequirements>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.HediffAdder">
 | 
			
		||||
				<eventDef>QuirkAddedTo</eventDef>
 | 
			
		||||
				<hediff>IncreasedFertility</hediff>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.HediffRemover">
 | 
			
		||||
				<eventDef>QuirkRemovedFrom</eventDef>
 | 
			
		||||
				<hediff>IncreasedFertility</hediff>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
		<defName>Incubator</defName>
 | 
			
		||||
		<label>Incubator</label>
 | 
			
		||||
		<description>{pawn} has birthed so many eggs that {pawn_possessive} body has adapted to handling them. {pawn_possessive} egg incubation speed has increased.</description>
 | 
			
		||||
		<rarity>ForcedOnly</rarity>
 | 
			
		||||
		<hidden>true</hidden>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.Adder_OnRecordExceeding">
 | 
			
		||||
				<eventDef>RecordChanged</eventDef>
 | 
			
		||||
				<record>CountOfBirthEgg</record>
 | 
			
		||||
				<value>100</value>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ValueModifier_ApplyMultiplier">
 | 
			
		||||
				<valueName>maxEggsSize</valueName>
 | 
			
		||||
				<multiplier>2.0</multiplier>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ValueModifier_ApplyMultiplier">
 | 
			
		||||
				<valueName>maxLitterOnBirth</valueName>
 | 
			
		||||
				<multiplier>2.0</multiplier>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
		<defName>Infertile</defName>
 | 
			
		||||
		<label>Infertile</label>
 | 
			
		||||
		<description>{pawn} has unusually low fertility and so is unlikely to have children.</description>
 | 
			
		||||
		<conflictingQuirks>
 | 
			
		||||
			<li>Fertile</li>
 | 
			
		||||
		</conflictingQuirks>
 | 
			
		||||
		<ownerRequirements>
 | 
			
		||||
			<li>
 | 
			
		||||
				<pawnSelector Class="rjwquirks.Modules.Shared.PawnSelectors.HasFertility"></pawnSelector>
 | 
			
		||||
				<rejectionReason>RaceHasNoFertility</rejectionReason>
 | 
			
		||||
			</li>
 | 
			
		||||
		</ownerRequirements>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.HediffAdder">
 | 
			
		||||
				<eventDef>QuirkAddedTo</eventDef>
 | 
			
		||||
				<hediff>DecreasedFertility</hediff>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.HediffRemover">
 | 
			
		||||
				<eventDef>QuirkRemovedFrom</eventDef>
 | 
			
		||||
				<hediff>DecreasedFertility</hediff>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
		<defName>Messy</defName>
 | 
			
		||||
		<label>Messy</label>
 | 
			
		||||
		<description>{pawn} not only produces copious amounts of fluid during sex but {pawn_pronoun} rarely bothers to clean {pawn_possessive}self afterwards.</description>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ValueModifier_ApplyMultiplier">
 | 
			
		||||
				<valueName>cumFilthAmount</valueName>
 | 
			
		||||
				<multiplier>2.0</multiplier>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ValueModifier_ApplyOffset">
 | 
			
		||||
				<valueName>cleanAfterFapChance</valueName>
 | 
			
		||||
				<offset>-0.75</offset>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
</Defs>
 | 
			
		||||
							
								
								
									
										268
									
								
								1.4/Defs/QuirkDefs/QuirkDef_Humanlike.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								1.4/Defs/QuirkDefs/QuirkDef_Humanlike.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,268 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
 | 
			
		||||
<Defs>
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef Abstract="True" Name="HumanlikeQuirk">
 | 
			
		||||
		<ownerRequirements>
 | 
			
		||||
			<li>
 | 
			
		||||
				<pawnSelector Class="rjwquirks.Modules.Shared.PawnSelectors.IsHumanlike"></pawnSelector>
 | 
			
		||||
				<rejectionReason>NotHumanlike</rejectionReason>
 | 
			
		||||
			</li>
 | 
			
		||||
		</ownerRequirements>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="HumanlikeQuirk">
 | 
			
		||||
		<defName>Endytophile</defName>
 | 
			
		||||
		<label>Endytophile</label>
 | 
			
		||||
		<description>{pawn} prefers to keep {pawn_possessive} clothes on during sex.</description>
 | 
			
		||||
		<sexPreference Class="rjwquirks.Modules.Quirks.SexSelectors.Clothed"></sexPreference>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ThoughtAdder_OnSexEvent_Preferred">
 | 
			
		||||
				<eventDef>Orgasm</eventDef>
 | 
			
		||||
				<thought>ThatsMyFetish</thought>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="HumanlikeQuirk">
 | 
			
		||||
		<defName>Exhibitionist</defName>
 | 
			
		||||
		<label>Exhibitionist</label>
 | 
			
		||||
		<description>{pawn} enjoys having sex where others can see.</description>
 | 
			
		||||
		<sexPreference Class="rjwquirks.Modules.Quirks.SexSelectors.Seen"></sexPreference>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ThoughtAdder_OnSexEvent_Preferred">
 | 
			
		||||
				<eventDef>Orgasm</eventDef>
 | 
			
		||||
				<thought>ThatsMyFetish</thought>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="HumanlikeQuirk">
 | 
			
		||||
		<defName>Gerontophile</defName>
 | 
			
		||||
		<label>Gerontophile</label>
 | 
			
		||||
		<description>{pawn} prefers older partners (55+ on a human scale).</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PawnSelectors.HasHumanScaleAge">
 | 
			
		||||
			<min>55</min>
 | 
			
		||||
		</partnerPreference>
 | 
			
		||||
		<sexPreference Class="rjwquirks.Modules.Quirks.SexSelectors.WithPreferedPartner"></sexPreference>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ThoughtAdder_OnSexEvent_Preferred">
 | 
			
		||||
				<eventDef>Orgasm</eventDef>
 | 
			
		||||
				<thought>ThatsMyFetish</thought>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.SexAppraisalModifier_SetValue">
 | 
			
		||||
				<factorName>ageFactor</factorName>
 | 
			
		||||
				<value>1.0</value>
 | 
			
		||||
				<priority>First</priority>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="HumanlikeQuirk">
 | 
			
		||||
		<defName>ImpregnationFetish</defName>
 | 
			
		||||
		<label>Impregnation fetish</label>
 | 
			
		||||
		<description>{pawn} really likes the idea of someone becoming pregnant. {pawn_pronoun} prefers partners and sex positions where there is a possibility of pregnancy. {pawn_pronoun} doesn't care if {pawn_pronoun} is getting pregnant or {pawn_possessive} partner is as long as babby is formed.</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PartnerSelectors.LogicalOr">
 | 
			
		||||
			<parts>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PartnerSelectors.CanImpregnate"></li>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PartnerSelectors.CanBeImpregnatedBy"></li>
 | 
			
		||||
			</parts>
 | 
			
		||||
		</partnerPreference>
 | 
			
		||||
		<sexPreference Class="rjwquirks.Modules.Quirks.SexSelectors.LogicalOr">
 | 
			
		||||
			<parts>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Quirks.SexSelectors.CanImpregnate"></li>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Quirks.SexSelectors.CanBeImpregnated"></li>
 | 
			
		||||
			</parts>
 | 
			
		||||
		</sexPreference>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ThoughtAdder_OnSexEvent_Preferred">
 | 
			
		||||
				<eventDef>Orgasm</eventDef>
 | 
			
		||||
				<thought>ThatsMyFetish</thought>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.PartKindUsageRules_ImpregnationFetish"></li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.Adder_OnRecordExceeding">
 | 
			
		||||
				<eventDef>RecordChanged</eventDef>
 | 
			
		||||
				<record>CountOfBirthHuman</record>
 | 
			
		||||
				<value>10</value>
 | 
			
		||||
				<message>{pawn} has given birth so many times that {pawn_pronoun} developed a fetish for impregnation</message>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.Adder_OnRecordExceeding">
 | 
			
		||||
				<eventDef>RecordChanged</eventDef>
 | 
			
		||||
				<record>CountOfBirthAnimal</record>
 | 
			
		||||
				<value>20</value>
 | 
			
		||||
				<message>{pawn} has given birth so many times that {pawn_pronoun} developed a fetish for impregnation</message>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.Adder_OnRecordExceeding">
 | 
			
		||||
				<eventDef>RecordChanged</eventDef>
 | 
			
		||||
				<record>CountOfBirthEgg</record>
 | 
			
		||||
				<value>100</value>
 | 
			
		||||
				<message>{pawn} has birthed so many eggs that {pawn_pronoun} developed a fetish for impregnation</message>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.SexAppraisalModifier_ApplyMultiplier">
 | 
			
		||||
				<factorName>bodyFactor</factorName>
 | 
			
		||||
				<multiplier>1.25</multiplier>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="HumanlikeQuirk">
 | 
			
		||||
		<defName>Podophile</defName>
 | 
			
		||||
		<label>Podophile</label>
 | 
			
		||||
		<description>{pawn} really likes feet and prefers foot-related sex acts.</description>
 | 
			
		||||
		<sexPreference Class="rjwquirks.Modules.Quirks.SexSelectors.BySextype">
 | 
			
		||||
			<sextype>Footjob</sextype>
 | 
			
		||||
		</sexPreference>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ThoughtAdder_OnSexEvent_Preferred">
 | 
			
		||||
				<eventDef>Orgasm</eventDef>
 | 
			
		||||
				<thought>ThatsMyFetish</thought>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.PartKindUsageRules_Static">
 | 
			
		||||
				<partner>
 | 
			
		||||
					<li>
 | 
			
		||||
						<partKind>Foot</partKind>
 | 
			
		||||
						<weightMultiplier>2.0</weightMultiplier>
 | 
			
		||||
					</li>
 | 
			
		||||
				</partner>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="HumanlikeQuirk">
 | 
			
		||||
		<defName>PregnancyFetish</defName>
 | 
			
		||||
		<label>Pregnancy fetish</label>
 | 
			
		||||
		<description>{pawn} prefers partners who are visibly pregnant.</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PawnSelectors.IsVisiblyPregnant"></partnerPreference>
 | 
			
		||||
		<sexPreference Class="rjwquirks.Modules.Quirks.SexSelectors.WithPreferedPartner"></sexPreference>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ThoughtAdder_OnSexEvent_Preferred">
 | 
			
		||||
				<eventDef>Orgasm</eventDef>
 | 
			
		||||
				<thought>ThatsMyFetish</thought>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.SexAppraisalModifier_ApplyMultiplier">
 | 
			
		||||
				<factorName>bodyFactor</factorName>
 | 
			
		||||
				<multiplier>1.25</multiplier>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="HumanlikeQuirk">
 | 
			
		||||
		<defName>Sapiosexual</defName>
 | 
			
		||||
		<label>Sapiosexual</label>
 | 
			
		||||
		<description>{pawn} prefers smart partners.</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PartnerSelectors.LogicalOr">
 | 
			
		||||
			<parts>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PawnSelectors.HasTrait">
 | 
			
		||||
					<trait>Transhumanist</trait>
 | 
			
		||||
				</li>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PawnSelectors.HasTrait">
 | 
			
		||||
					<trait>GreatMemory</trait>
 | 
			
		||||
				</li>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PawnSelectors.HasTrait">
 | 
			
		||||
					<trait>TooSmart</trait>
 | 
			
		||||
				</li>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PawnSelectors.HasTrait" MayRequire="consolidatedtraits.kv.rw">
 | 
			
		||||
					<trait>RCT_Savant</trait>
 | 
			
		||||
				</li>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PawnSelectors.HasTrait" MayRequire="consolidatedtraits.kv.rw">
 | 
			
		||||
					<trait>RCT_Inventor</trait>
 | 
			
		||||
				</li>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PawnSelectors.HasTrait" MayRequire="syrchalis.individuality">
 | 
			
		||||
					<trait>SYR_CreativeThinker</trait>
 | 
			
		||||
				</li>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PawnSelectors.HasSkillLevel">
 | 
			
		||||
					<skill>Intellectual</skill>
 | 
			
		||||
					<minLevel>15</minLevel>
 | 
			
		||||
				</li>
 | 
			
		||||
			</parts>
 | 
			
		||||
		</partnerPreference>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.SexAppraisalModifier_ApplyMultiplier">
 | 
			
		||||
				<factorName>opinionFactor</factorName>
 | 
			
		||||
				<multiplier>1.4</multiplier>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="HumanlikeQuirk">
 | 
			
		||||
		<defName>Somnophile</defName>
 | 
			
		||||
		<label>Somnophile</label>
 | 
			
		||||
		<description>{pawn} prefers {pawn_possessive} partners to be asleep.</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PawnSelectors.IsSleeping"></partnerPreference>
 | 
			
		||||
		<sexPreference Class="rjwquirks.Modules.Quirks.SexSelectors.WithPreferedPartner"></sexPreference>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ThoughtAdder_OnSexEvent_Preferred">
 | 
			
		||||
				<eventDef>Orgasm</eventDef>
 | 
			
		||||
				<thought>ThatsMyFetish</thought>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.SexAppraisalModifier_ApplyMultiplier">
 | 
			
		||||
				<factorName>bodyFactor</factorName>
 | 
			
		||||
				<multiplier>1.25</multiplier>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="HumanlikeQuirk">
 | 
			
		||||
		<defName>Teratophile</defName>
 | 
			
		||||
		<label>Teratophile</label>
 | 
			
		||||
		<description>{pawn} prefers ugly partners. {pawn_pronoun} would also prefer larger and wilder animals if {pawn_pronoun} were into that sort of thing...</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PartnerSelectors.LogicalOr">
 | 
			
		||||
			<parts>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PawnSelectors.HasTrait">
 | 
			
		||||
					<trait>CreepyBreathing</trait>
 | 
			
		||||
				</li>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PawnSelectors.HasDegreeOfTrait">
 | 
			
		||||
					<trait>Beauty</trait>
 | 
			
		||||
					<degree>-1</degree>
 | 
			
		||||
				</li>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PawnSelectors.HasDegreeOfTrait">
 | 
			
		||||
					<trait>Beauty</trait>
 | 
			
		||||
					<degree>-2</degree>
 | 
			
		||||
				</li>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PawnSelectors.HasBodyType">
 | 
			
		||||
					<bodyType>Fat</bodyType>
 | 
			
		||||
				</li>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PawnSelectors.IsDisfigured"></li>
 | 
			
		||||
				<li Class="rjwquirks.Modules.Shared.PawnSelectors.HasStatValue">
 | 
			
		||||
					<stat>PawnBeauty</stat>
 | 
			
		||||
					<maxValue>-0.1</maxValue>
 | 
			
		||||
				</li>
 | 
			
		||||
			</parts>
 | 
			
		||||
		</partnerPreference>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.SexAppraisalModifier_SetValue">
 | 
			
		||||
				<factorName>bodyFactor</factorName>
 | 
			
		||||
				<value>1.4</value>
 | 
			
		||||
				<priority>First</priority>
 | 
			
		||||
			</li>
 | 
			
		||||
			<!-- Teratophiles prefer more 'monstrous' partners -->
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ValueModifier_ApplyMultiplier">
 | 
			
		||||
				<valueName>wouldFuckAnimalBodySizeMin</valueName>
 | 
			
		||||
				<multiplier>0.8</multiplier>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ValueModifier_ApplyMultiplier">
 | 
			
		||||
				<valueName>wouldFuckAnimalBodySizeMax</valueName>
 | 
			
		||||
				<multiplier>2.0</multiplier>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ValueModifier_ApplyMultiplier">
 | 
			
		||||
				<valueName>wouldFuckAnimalWildnessModifier</valueName>
 | 
			
		||||
				<multiplier>0.3</multiplier>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="HumanlikeQuirk">
 | 
			
		||||
		<defName>Vigorous</defName>
 | 
			
		||||
		<label>Vigorous</label>
 | 
			
		||||
		<description>{pawn} is invigorated by sex. {pawn_pronoun} does not get tired as much during sex.</description>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ValueModifier_ApplyMultiplier">
 | 
			
		||||
				<valueName>ticksToNextLovin</valueName>
 | 
			
		||||
				<multiplier>0.8</multiplier>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ValueModifier_ApplyMultiplier">
 | 
			
		||||
				<valueName>reduceRest</valueName>
 | 
			
		||||
				<multiplier>0.5</multiplier>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
</Defs>
 | 
			
		||||
							
								
								
									
										188
									
								
								1.4/Defs/QuirkDefs/QuirkDef_RaceTag.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								1.4/Defs/QuirkDefs/QuirkDef_RaceTag.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,188 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
 | 
			
		||||
<!-- There might be too many of these I dunno.
 | 
			
		||||
	People have expressed "special interest" in some of them so I thought
 | 
			
		||||
	it would be cool to have them in the game but since people are weird you end up with a lot of fetishes.-->
 | 
			
		||||
<Defs>
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef Abstract="True" Name="RaceTagQuirk" ParentName="HumanlikeQuirk">
 | 
			
		||||
		<sexPreference Class="rjwquirks.Modules.Quirks.SexSelectors.WithPreferedPartner"></sexPreference>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="rjwquirks.Modules.Quirks.Comps.ThoughtAdder_OnSexEvent_Preferred">
 | 
			
		||||
				<eventDef>Orgasm</eventDef>
 | 
			
		||||
				<thought>ThatsMyFetish</thought>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="RaceTagQuirk">
 | 
			
		||||
		<defName>ChitinLover</defName>
 | 
			
		||||
		<label>Chitin lover</label>
 | 
			
		||||
		<description>{pawn} enjoys the smooth strength of a chitinous exoskeleton. {pawn_pronoun} prefers arachnoid or insectoid partners.</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
			<raceTag>Chitin</raceTag>
 | 
			
		||||
		</partnerPreference>
 | 
			
		||||
		<ownerRequirements>
 | 
			
		||||
			<li>
 | 
			
		||||
				<!-- No fair having a fetish for your own race -->
 | 
			
		||||
				<pawnSelector Class="rjwquirks.Modules.Shared.PawnSelectors.LogicalNot">
 | 
			
		||||
					<negated Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
						<raceTag>Chitin</raceTag>
 | 
			
		||||
					</negated>
 | 
			
		||||
				</pawnSelector>
 | 
			
		||||
				<rejectionReason>QuirkForOwnRace</rejectionReason>
 | 
			
		||||
			</li>
 | 
			
		||||
		</ownerRequirements>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="RaceTagQuirk">
 | 
			
		||||
		<defName>DemonLover</defName>
 | 
			
		||||
		<label>Demon lover</label>
 | 
			
		||||
		<description>{pawn} is after the naughty ones. {pawn_pronoun} prefers {pawn_possessive} partners to come from the literal depths of hell, or at least look the part.</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
			<raceTag>Demon</raceTag>
 | 
			
		||||
		</partnerPreference>
 | 
			
		||||
		<ownerRequirements>
 | 
			
		||||
			<li>
 | 
			
		||||
				<pawnSelector Class="rjwquirks.Modules.Shared.PawnSelectors.LogicalNot">
 | 
			
		||||
					<negated Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
						<raceTag>Demon</raceTag>
 | 
			
		||||
					</negated>
 | 
			
		||||
				</pawnSelector>
 | 
			
		||||
				<rejectionReason>QuirkForOwnRace</rejectionReason>
 | 
			
		||||
			</li>
 | 
			
		||||
		</ownerRequirements>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="RaceTagQuirk">
 | 
			
		||||
		<defName>FeatherLover</defName>
 | 
			
		||||
		<label>Feather lover</label>
 | 
			
		||||
		<description>{pawn} loves that downy fluff. {pawn_pronoun} prefers avian or dinosaur partners. Because dinosaurs are birds and have feathers, as {pawn_pronoun} will explain at great length if given a chance.</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
			<raceTag>Feathers</raceTag>
 | 
			
		||||
		</partnerPreference>
 | 
			
		||||
		<ownerRequirements>
 | 
			
		||||
			<li>
 | 
			
		||||
				<pawnSelector Class="rjwquirks.Modules.Shared.PawnSelectors.LogicalNot">
 | 
			
		||||
					<negated Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
						<raceTag>Feathers</raceTag>
 | 
			
		||||
					</negated>
 | 
			
		||||
				</pawnSelector>
 | 
			
		||||
				<rejectionReason>QuirkForOwnRace</rejectionReason>
 | 
			
		||||
			</li>
 | 
			
		||||
		</ownerRequirements>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="RaceTagQuirk">
 | 
			
		||||
		<defName>FurLover</defName>
 | 
			
		||||
		<label>Fur lover</label>
 | 
			
		||||
		<description>{pawn} prefers a partner with a thick, luxurious, snuggly-soft coat of fur.</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
			<raceTag>Fur</raceTag>
 | 
			
		||||
		</partnerPreference>
 | 
			
		||||
		<ownerRequirements>
 | 
			
		||||
			<li>
 | 
			
		||||
				<pawnSelector Class="rjwquirks.Modules.Shared.PawnSelectors.LogicalNot">
 | 
			
		||||
					<negated Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
						<raceTag>Fur</raceTag>
 | 
			
		||||
					</negated>
 | 
			
		||||
				</pawnSelector>
 | 
			
		||||
				<rejectionReason>QuirkForOwnRace</rejectionReason>
 | 
			
		||||
			</li>
 | 
			
		||||
		</ownerRequirements>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="RaceTagQuirk">
 | 
			
		||||
		<defName>PlantLover</defName>
 | 
			
		||||
		<label>Plant lover</label>
 | 
			
		||||
		<description>{pawn} likes watering plants. If you know what I mean.</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
			<raceTag>Plant</raceTag>
 | 
			
		||||
		</partnerPreference>
 | 
			
		||||
		<ownerRequirements>
 | 
			
		||||
			<li>
 | 
			
		||||
				<pawnSelector Class="rjwquirks.Modules.Shared.PawnSelectors.LogicalNot">
 | 
			
		||||
					<negated Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
						<raceTag>Plant</raceTag>
 | 
			
		||||
					</negated>
 | 
			
		||||
				</pawnSelector>
 | 
			
		||||
				<rejectionReason>QuirkForOwnRace</rejectionReason>
 | 
			
		||||
			</li>
 | 
			
		||||
		</ownerRequirements>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="RaceTagQuirk">
 | 
			
		||||
		<defName>RobotLover</defName>
 | 
			
		||||
		<label>Robot lover</label>
 | 
			
		||||
		<description>Which is better, 2D or 3D? {pawn} knows that 3D-printed gives you the best of both worlds.</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
			<raceTag>Robot</raceTag>
 | 
			
		||||
		</partnerPreference>
 | 
			
		||||
		<ownerRequirements>
 | 
			
		||||
			<li>
 | 
			
		||||
				<pawnSelector Class="rjwquirks.Modules.Shared.PawnSelectors.LogicalNot">
 | 
			
		||||
					<negated Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
						<raceTag>Robot</raceTag>
 | 
			
		||||
					</negated>
 | 
			
		||||
				</pawnSelector>
 | 
			
		||||
				<rejectionReason>QuirkForOwnRace</rejectionReason>
 | 
			
		||||
			</li>
 | 
			
		||||
		</ownerRequirements>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="RaceTagQuirk">
 | 
			
		||||
		<defName>ScaleLover</defName>
 | 
			
		||||
		<label>Scale lover</label>
 | 
			
		||||
		<description>Who wouldn't want to fuck a dragon? Definitely not {pawn}. {pawn} wants to fuck a dragon.</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
			<raceTag>Scales</raceTag>
 | 
			
		||||
		</partnerPreference>
 | 
			
		||||
		<ownerRequirements>
 | 
			
		||||
			<li>
 | 
			
		||||
				<pawnSelector Class="rjwquirks.Modules.Shared.PawnSelectors.LogicalNot">
 | 
			
		||||
					<negated Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
						<raceTag>Scales</raceTag>
 | 
			
		||||
					</negated>
 | 
			
		||||
				</pawnSelector>
 | 
			
		||||
				<rejectionReason>QuirkForOwnRace</rejectionReason>
 | 
			
		||||
			</li>
 | 
			
		||||
		</ownerRequirements>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="RaceTagQuirk">
 | 
			
		||||
		<defName>SkinLover</defName>
 | 
			
		||||
		<label>Skin lover</label>
 | 
			
		||||
		<description>{pawn} prefers {pawn_possessive} partners to have smooth sensitive skin without fur or scales getting in the way. Lucky for {pawn_objective} humans are all over the place.</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
			<raceTag>Skin</raceTag>
 | 
			
		||||
		</partnerPreference>
 | 
			
		||||
		<ownerRequirements>
 | 
			
		||||
			<li>
 | 
			
		||||
				<pawnSelector Class="rjwquirks.Modules.Shared.PawnSelectors.LogicalNot">
 | 
			
		||||
					<negated Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
						<raceTag>Skin</raceTag>
 | 
			
		||||
					</negated>
 | 
			
		||||
				</pawnSelector>
 | 
			
		||||
				<rejectionReason>QuirkForOwnRace</rejectionReason>
 | 
			
		||||
			</li>
 | 
			
		||||
		</ownerRequirements>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Quirks.QuirkDef ParentName="RaceTagQuirk">
 | 
			
		||||
		<defName>SlimeLover</defName>
 | 
			
		||||
		<label>Slime lover</label>
 | 
			
		||||
		<description>Because of their slippery and malleable nature slimes are very, very good at sex. As you will hear over and over if you listen to {pawn} talk for any length of time.</description>
 | 
			
		||||
		<partnerPreference Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
			<raceTag>Slime</raceTag>
 | 
			
		||||
		</partnerPreference>
 | 
			
		||||
		<ownerRequirements>
 | 
			
		||||
			<li>
 | 
			
		||||
				<pawnSelector Class="rjwquirks.Modules.Shared.PawnSelectors.LogicalNot">
 | 
			
		||||
					<negated Class="rjwquirks.Modules.Shared.PawnSelectors.HasRaceTag">
 | 
			
		||||
						<raceTag>Slime</raceTag>
 | 
			
		||||
					</negated>
 | 
			
		||||
				</pawnSelector>
 | 
			
		||||
				<rejectionReason>QuirkForOwnRace</rejectionReason>
 | 
			
		||||
			</li>
 | 
			
		||||
		</ownerRequirements>
 | 
			
		||||
	</rjwquirks.Modules.Quirks.QuirkDef>
 | 
			
		||||
</Defs>
 | 
			
		||||
							
								
								
									
										43
									
								
								1.4/Defs/RjwEventDefs/RjwEventDef.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								1.4/Defs/RjwEventDefs/RjwEventDef.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
 | 
			
		||||
<Defs>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Shared.Events.RjwEventDef>
 | 
			
		||||
		<defName>QuirkAddedTo</defName>
 | 
			
		||||
		<obligatoryArgs>
 | 
			
		||||
			<li>Pawn</li>
 | 
			
		||||
			<li>Quirk</li>
 | 
			
		||||
		</obligatoryArgs>
 | 
			
		||||
	</rjwquirks.Modules.Shared.Events.RjwEventDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Shared.Events.RjwEventDef>
 | 
			
		||||
		<defName>QuirkRemovedFrom</defName>
 | 
			
		||||
		<obligatoryArgs>
 | 
			
		||||
			<li>Pawn</li>
 | 
			
		||||
			<li>Quirk</li>
 | 
			
		||||
		</obligatoryArgs>
 | 
			
		||||
	</rjwquirks.Modules.Shared.Events.RjwEventDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Shared.Events.RjwEventDef>
 | 
			
		||||
		<defName>Orgasm</defName>
 | 
			
		||||
		<obligatoryArgs>
 | 
			
		||||
			<li>SexProps</li>
 | 
			
		||||
		</obligatoryArgs>
 | 
			
		||||
	</rjwquirks.Modules.Shared.Events.RjwEventDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Shared.Events.RjwEventDef>
 | 
			
		||||
		<defName>RecordChanged</defName>
 | 
			
		||||
		<obligatoryArgs>
 | 
			
		||||
			<li>Pawn</li>
 | 
			
		||||
			<li>Record</li>
 | 
			
		||||
		</obligatoryArgs>
 | 
			
		||||
	</rjwquirks.Modules.Shared.Events.RjwEventDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Shared.Events.RjwEventDef>
 | 
			
		||||
		<defName>PawnSexualized</defName>
 | 
			
		||||
		<obligatoryArgs>
 | 
			
		||||
			<li>Pawn</li>
 | 
			
		||||
		</obligatoryArgs>
 | 
			
		||||
	</rjwquirks.Modules.Shared.Events.RjwEventDef>
 | 
			
		||||
 | 
			
		||||
</Defs>
 | 
			
		||||
							
								
								
									
										38
									
								
								1.4/Defs/RjwEventHandlerDefs/QuirkHandlers.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								1.4/Defs/RjwEventHandlerDefs/QuirkHandlers.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
 | 
			
		||||
<Defs>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Shared.Events.RjwEventHandlerDef>
 | 
			
		||||
		<defName>Quirk</defName>
 | 
			
		||||
		<workerClass>rjwquirks.Modules.Quirks.EventHandlers.QuirkRjwEventHandler</workerClass>
 | 
			
		||||
		<handlesEvents>
 | 
			
		||||
			<li>QuirkAddedTo</li>
 | 
			
		||||
			<li>QuirkRemovedFrom</li>
 | 
			
		||||
		</handlesEvents>
 | 
			
		||||
	</rjwquirks.Modules.Shared.Events.RjwEventHandlerDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Shared.Events.RjwEventHandlerDef>
 | 
			
		||||
		<defName>QuirkSet</defName>
 | 
			
		||||
		<workerClass>rjwquirks.Modules.Quirks.EventHandlers.QuirkSetRjwEventHandler</workerClass>
 | 
			
		||||
		<handlesEvents>
 | 
			
		||||
			<li>Orgasm</li>
 | 
			
		||||
		</handlesEvents>
 | 
			
		||||
	</rjwquirks.Modules.Shared.Events.RjwEventHandlerDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Shared.Events.RjwEventHandlerDef>
 | 
			
		||||
		<defName>QuirkRecordChanged</defName>
 | 
			
		||||
		<workerClass>rjwquirks.Modules.Quirks.EventHandlers.RecordChangedRjwEventHandler</workerClass>
 | 
			
		||||
		<handlesEvents>
 | 
			
		||||
			<li>RecordChanged</li>
 | 
			
		||||
		</handlesEvents>
 | 
			
		||||
	</rjwquirks.Modules.Shared.Events.RjwEventHandlerDef>
 | 
			
		||||
 | 
			
		||||
	<rjwquirks.Modules.Shared.Events.RjwEventHandlerDef>
 | 
			
		||||
		<defName>QuirkGenerator</defName>
 | 
			
		||||
		<workerClass>rjwquirks.Modules.Quirks.EventHandlers.QuirkGenerator</workerClass>
 | 
			
		||||
		<handlesEvents>
 | 
			
		||||
			<li>PawnSexualized</li>
 | 
			
		||||
		</handlesEvents>
 | 
			
		||||
	</rjwquirks.Modules.Shared.Events.RjwEventHandlerDef>
 | 
			
		||||
 | 
			
		||||
</Defs>
 | 
			
		||||
							
								
								
									
										34
									
								
								About/About.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								About/About.xml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
 | 
			
		||||
<ModMetaData>
 | 
			
		||||
	<name>RJW Quirks</name>
 | 
			
		||||
	<author>Rain</author>
 | 
			
		||||
	<url></url>
 | 
			
		||||
	<supportedVersions>
 | 
			
		||||
		<li>1.4</li>
 | 
			
		||||
	</supportedVersions>
 | 
			
		||||
	<packageId>rain.quirks</packageId>
 | 
			
		||||
	<modDependencies>
 | 
			
		||||
		<li>
 | 
			
		||||
			<packageId>brrainz.harmony</packageId>
 | 
			
		||||
			<displayName>Harmony</displayName>
 | 
			
		||||
			<steamWorkshopUrl>steam://url/CommunityFilePage/2009463077</steamWorkshopUrl>
 | 
			
		||||
			<downloadUrl>https://github.com/pardeike/HarmonyRimWorld/releases/latest</downloadUrl>
 | 
			
		||||
		</li>
 | 
			
		||||
	</modDependencies>
 | 
			
		||||
	<loadAfter>
 | 
			
		||||
		<li>rim.job.world</li>
 | 
			
		||||
	</loadAfter>
 | 
			
		||||
	<incompatibleWith>
 | 
			
		||||
		<li>gregorycurrie.AnimalGenetics</li><!-- Breaks CompHatcher.Hatch preventing eggs hatching -->
 | 
			
		||||
		<li>EdB.PrepareCarefully</li><!-- Hijacks generated/edited pawns at world start, breaks C# hediffs of edited pawns and who knows what else -->
 | 
			
		||||
		<li>EdB.PrepareCarefully.UnofficialPatch</li><!-- Hijacks generated/edited pawns at world start, breaks C# hediffs of edited pawns and who knows what else -->
 | 
			
		||||
		<li>Dalrae.GaramRaceAddon</li><!-- Hijacks pawn generator fucking up pawn genders and who knows what else -->
 | 
			
		||||
		<li>IGNI.LostForest</li><!-- Intentionally breaks rjw jobs, hijacks storyteller to call raids and causes other issues when rjw detected -->
 | 
			
		||||
		<li>Sierra.RT.MedievalTalents</li><!-- Breaks pawn generator/pregnancies, causes pregnancies to instafail -->
 | 
			
		||||
		<li>com.yayo.raceQuestPawn</li><!-- Breaks pawn generator/pregnancies, wrong children outcome-->
 | 
			
		||||
	</incompatibleWith>
 | 
			
		||||
	<description>
 | 
			
		||||
big peepee sim
 | 
			
		||||
	</description>
 | 
			
		||||
</ModMetaData>
 | 
			
		||||
							
								
								
									
										18
									
								
								RJW-Quirks/Core.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								RJW-Quirks/Core.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
using HarmonyLib;
 | 
			
		||||
using HugsLib;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks
 | 
			
		||||
{
 | 
			
		||||
    public class Core : ModBase
 | 
			
		||||
    {
 | 
			
		||||
        // Originally did not use Hugslib, but due to RJW using hugslib I needed to in order for proper patching at correct times. could probably be done with priorities or something but this was easier
 | 
			
		||||
        /*public Core(ModContentPack pack)
 | 
			
		||||
        {
 | 
			
		||||
            //var harmony = new Harmony("rain.quirks");
 | 
			
		||||
            //harmony.PatchAll();
 | 
			
		||||
        }*/
 | 
			
		||||
 | 
			
		||||
        public override string ModIdentifier => "quirk";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										64
									
								
								RJW-Quirks/Data/RaceTags.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								RJW-Quirks/Data/RaceTags.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,64 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Data
 | 
			
		||||
{
 | 
			
		||||
    public class RaceTags
 | 
			
		||||
    {
 | 
			
		||||
        private readonly static Dictionary<string, RaceTags> tagDatabase = new Dictionary<string, RaceTags>();
 | 
			
		||||
 | 
			
		||||
        // I only created tags for RaceGroupDef properties that seemed like keywords (like slime) rather than behavior (like oviPregnancy).
 | 
			
		||||
        public readonly static RaceTags Chitin = new RaceTags("Chitin");
 | 
			
		||||
        public readonly static RaceTags Demon = new RaceTags("Demon");
 | 
			
		||||
        public readonly static RaceTags Feathers = new RaceTags("Feathers");
 | 
			
		||||
        public readonly static RaceTags Fur = new RaceTags("Fur");
 | 
			
		||||
        public readonly static RaceTags Plant = new RaceTags("Plant");
 | 
			
		||||
        public readonly static RaceTags Robot = new RaceTags("Robot");
 | 
			
		||||
        public readonly static RaceTags Scales = new RaceTags("Scales");
 | 
			
		||||
        public readonly static RaceTags Skin = new RaceTags("Skin");
 | 
			
		||||
        public readonly static RaceTags Slime = new RaceTags("Slime");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public string Key { get;  }
 | 
			
		||||
 | 
			
		||||
        private RaceTags(string key)
 | 
			
		||||
        {
 | 
			
		||||
            Key = key;
 | 
			
		||||
            tagDatabase.Add(key, this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool TryParse(string key, out RaceTags raceTag)
 | 
			
		||||
        {
 | 
			
		||||
            return tagDatabase.TryGetValue(key, out raceTag);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
		/// For backwards compatability only. Shouldn't add more special cases here.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public bool DefaultWhenNoRaceGroupDef(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            if (this == Demon)
 | 
			
		||||
            {
 | 
			
		||||
                return xxx.is_demon(pawn);
 | 
			
		||||
            }
 | 
			
		||||
            else if (this == Slime)
 | 
			
		||||
            {
 | 
			
		||||
                return xxx.is_slime(pawn);
 | 
			
		||||
            }
 | 
			
		||||
            else if (this == Skin)
 | 
			
		||||
            {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										74
									
								
								RJW-Quirks/HarmonyPatches/Patch_CasualSex_Helper.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								RJW-Quirks/HarmonyPatches/Patch_CasualSex_Helper.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,74 @@
 | 
			
		|||
using HarmonyLib;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Quirks;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.HarmonyPatches
 | 
			
		||||
{
 | 
			
		||||
    [HarmonyPatch(typeof(CasualSex_Helper), nameof(CasualSex_Helper.GetScore))]
 | 
			
		||||
    public class Patch_CasualSex_Helper
 | 
			
		||||
    {
 | 
			
		||||
        // Edits the "score" of a cell for a pawn to fuck in
 | 
			
		||||
        public static void Postfix(Pawn pawn, IntVec3 cell, Pawn partner, ref int __result)
 | 
			
		||||
        {
 | 
			
		||||
            QuirkSet quirks = pawn.GetQuirks();
 | 
			
		||||
 | 
			
		||||
            if (quirks.AllQuirks.EnumerableNullOrEmpty())
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            List<Pawn> all_pawns = pawn.Map.mapPawns.AllPawnsSpawned.Where(x
 | 
			
		||||
                => x.Position.DistanceTo(pawn.Position) < 100
 | 
			
		||||
                && xxx.is_human(x)
 | 
			
		||||
                && x != pawn
 | 
			
		||||
                && x != partner
 | 
			
		||||
                ).ToList();
 | 
			
		||||
 | 
			
		||||
            // Somnophile code
 | 
			
		||||
            if (partner != null && quirks.Contains(QuirkDefOf.Somnophile))
 | 
			
		||||
            {
 | 
			
		||||
                if (all_pawns.Any(x
 | 
			
		||||
                    => !x.Awake()
 | 
			
		||||
                    && x.Position.DistanceTo(cell) < 6
 | 
			
		||||
                    && GenSight.LineOfSight(cell, x.Position, pawn.Map)
 | 
			
		||||
                    ))
 | 
			
		||||
                    __result += 50;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Exhibitionist code
 | 
			
		||||
            if (quirks.Contains(QuirkDefOf.Exhibitionist))
 | 
			
		||||
            {
 | 
			
		||||
                bool might_be_seen = CasualSex_Helper.MightBeSeen(all_pawns, cell, pawn, partner);
 | 
			
		||||
                Room room = cell.GetRoom(pawn.Map);
 | 
			
		||||
 | 
			
		||||
                // Readd the 30 score removed in regular RJW
 | 
			
		||||
                __result += 30;
 | 
			
		||||
                // Readd the 100 score taken from being in a doorway in regular RJW
 | 
			
		||||
                __result += 100;
 | 
			
		||||
 | 
			
		||||
                if (might_be_seen)
 | 
			
		||||
                    __result += 5;
 | 
			
		||||
                else
 | 
			
		||||
                    __result -= 10;
 | 
			
		||||
 | 
			
		||||
                if (room.Role == RoomRoleDefOf.Barracks || room.Role == RoomRoleDefOf.PrisonBarracks || room.Role == RoomRoleDefOf.PrisonCell
 | 
			
		||||
                    || room.Role == RoomRoleDefOf.Laboratory || room.Role == RoomRoleDefOf.RecRoom
 | 
			
		||||
                    || room.Role == RoomRoleDefOf.DiningRoom || room.Role == RoomRoleDefOf.Hospital
 | 
			
		||||
                    )
 | 
			
		||||
                    __result += 15;     // Add 15 instead of 10 to counteract the -5 in regular RJW
 | 
			
		||||
 | 
			
		||||
                Dictionary<int, int> cell_doors = new Dictionary<int, int>();
 | 
			
		||||
 | 
			
		||||
                var doors = cell_doors.TryGetValue(room.ID);
 | 
			
		||||
 | 
			
		||||
                if (doors > 1)
 | 
			
		||||
                    __result += 7 * doors;          // Multiply by 7 instead of 2 to counteract the negative in regular RJW
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								RJW-Quirks/HarmonyPatches/Patch_CondomUtility.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								RJW-Quirks/HarmonyPatches/Patch_CondomUtility.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
using HarmonyLib;
 | 
			
		||||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Quirks;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.HarmonyPatches
 | 
			
		||||
{
 | 
			
		||||
    // Skips condom code entirely if they have pregnation fetish or similar. RJW used to do this with the same quirk.
 | 
			
		||||
    [HarmonyPatch(typeof(CondomUtility))]
 | 
			
		||||
    public class Patch_CondomUtility
 | 
			
		||||
    {
 | 
			
		||||
        [HarmonyPrefix]
 | 
			
		||||
        [HarmonyPatch(nameof(CondomUtility.TryUseCondom))]
 | 
			
		||||
        public static bool UseCondomPrefix(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            if (xxx.is_human(pawn) && pawn.HasQuirk(QuirkDefOf.ImpregnationFetish))
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [HarmonyPrefix]
 | 
			
		||||
        [HarmonyPatch(nameof(CondomUtility.GetCondomFromRoom))]
 | 
			
		||||
        public static bool GetCondomPrefix(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            if (xxx.is_human(pawn) && pawn.HasQuirk(QuirkDefOf.ImpregnationFetish))
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										131
									
								
								RJW-Quirks/HarmonyPatches/Patch_Dialog_Sexcard.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								RJW-Quirks/HarmonyPatches/Patch_Dialog_Sexcard.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,131 @@
 | 
			
		|||
using HarmonyLib;
 | 
			
		||||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Quirks;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Reflection.Emit;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.HarmonyPatches
 | 
			
		||||
{
 | 
			
		||||
    [HarmonyPatch(typeof(Dialog_Sexcard), "SexualityCard")]
 | 
			
		||||
    public static class Patch_Dialog_Sexcard
 | 
			
		||||
    {
 | 
			
		||||
        static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
 | 
			
		||||
        {
 | 
			
		||||
            MethodInfo InsertQuirks = AccessTools.Method(typeof(Patch_Dialog_Sexcard), nameof(DrawQuirks));
 | 
			
		||||
            MethodInfo DrawSexuality = AccessTools.Method(typeof(Dialog_Sexcard), "DrawSexuality");
 | 
			
		||||
            bool found = false;
 | 
			
		||||
 | 
			
		||||
            // When RJW calls draw sexuality we inject our quirk drawing.
 | 
			
		||||
            foreach (CodeInstruction i in instructions)
 | 
			
		||||
            {
 | 
			
		||||
                if (i.opcode == OpCodes.Call && i.operand as MethodInfo == DrawSexuality)
 | 
			
		||||
                    found = true;
 | 
			
		||||
 | 
			
		||||
                if (found)
 | 
			
		||||
                {
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Ldarg_2);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Ldloc_3);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Call, InsertQuirks);
 | 
			
		||||
                    found = false;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                yield return i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void DrawQuirks(Pawn pawn, Rect rect)
 | 
			
		||||
        {
 | 
			
		||||
            QuirkSet quirks = pawn.GetQuirks();
 | 
			
		||||
            rect.y += 24;
 | 
			
		||||
 | 
			
		||||
            if (quirks == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            var quirkString = quirks.AllQuirks
 | 
			
		||||
                .Select(quirk => quirk.Label)
 | 
			
		||||
                .OrderBy(Label => Label)
 | 
			
		||||
                .ToCommaList();
 | 
			
		||||
 | 
			
		||||
            if ((Current.ProgramState == ProgramState.Playing &&
 | 
			
		||||
                pawn.IsDesignatedHero() && pawn.IsHeroOwner() || Prefs.DevMode) ||
 | 
			
		||||
                Current.ProgramState == ProgramState.Entry)
 | 
			
		||||
            {
 | 
			
		||||
                if (Widgets.ButtonText(rect, "Quirks".Translate() + quirkString, false))
 | 
			
		||||
                    DrawQuirkEditMenu(pawn, quirks);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
                Widgets.Label(rect, "Quirks".Translate() + quirkString);
 | 
			
		||||
 | 
			
		||||
            if (!Mouse.IsOver(rect)) return;
 | 
			
		||||
 | 
			
		||||
            Widgets.DrawHighlight(rect);
 | 
			
		||||
 | 
			
		||||
            TooltipHandler.TipRegion(rect, quirks.TipString());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        static void DrawQuirkEditMenu(Pawn pawn, QuirkSet quirks)
 | 
			
		||||
        {
 | 
			
		||||
            var quirkDefsAll = DefDatabase<QuirkDef>.AllDefs.OrderBy(def => def.GetLabelFor(pawn));
 | 
			
		||||
 | 
			
		||||
            var menuOptions = new List<FloatMenuOption>();
 | 
			
		||||
 | 
			
		||||
            if (RJWSettings.DevMode)
 | 
			
		||||
                menuOptions.Add(new FloatMenuOption("[DEV] Forced Reset", () => quirks.Clear(true)));
 | 
			
		||||
 | 
			
		||||
            menuOptions.Add(new FloatMenuOption("Reset", () => quirks.Clear()));
 | 
			
		||||
 | 
			
		||||
            foreach (QuirkDef quirkDef in quirkDefsAll)
 | 
			
		||||
            {
 | 
			
		||||
                if (quirkDef.hidden && !RJWSettings.DevMode && !quirks.Contains(quirkDef))
 | 
			
		||||
                    continue;
 | 
			
		||||
 | 
			
		||||
                Quirk quirk = quirks.GetQuirk(quirkDef);
 | 
			
		||||
                FloatMenuOption option;
 | 
			
		||||
 | 
			
		||||
                if (quirk == null)
 | 
			
		||||
                {
 | 
			
		||||
                    AcceptanceReport report = quirks.CanBeAdded(quirkDef);
 | 
			
		||||
                    if (report.Accepted)
 | 
			
		||||
                    {
 | 
			
		||||
                        option = new FloatMenuOption(
 | 
			
		||||
                            quirkDef.GetLabelFor(pawn),
 | 
			
		||||
                            () => quirks.AddQuirk(quirkDef),
 | 
			
		||||
                            mouseoverGuiAction: (Rect rect) => TooltipHandler.TipRegion(rect, quirkDef.GetDescriptionFor(pawn))
 | 
			
		||||
                            );
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (RJWSettings.DevMode)
 | 
			
		||||
                        option = new FloatMenuOption($"[DEV]{quirkDef.GetLabelFor(pawn)}: {report.Reason}", () => quirks.AddQuirk(quirkDef, true));
 | 
			
		||||
                    else
 | 
			
		||||
                        // Game does not call mouseoverGuiAction for the disabled entries
 | 
			
		||||
                        option = new FloatMenuOption($"{quirkDef.GetLabelFor(pawn)}: {report.Reason}", null);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    AcceptanceReport report = quirks.CanBeRemoved(quirkDef);
 | 
			
		||||
                    if (report.Accepted)
 | 
			
		||||
                    {
 | 
			
		||||
                        option = new FloatMenuOption(
 | 
			
		||||
                            "- " + quirk.Label,
 | 
			
		||||
                            () => quirks.RemoveQuirk(quirk),
 | 
			
		||||
                            mouseoverGuiAction: (Rect rect) => TooltipHandler.TipRegion(rect, quirk.Description)
 | 
			
		||||
                            );
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (RJWSettings.DevMode)
 | 
			
		||||
                        option = new FloatMenuOption($"- {quirk.Label}: {report.Reason}", () => quirks.RemoveQuirk(quirk, true));
 | 
			
		||||
                    else
 | 
			
		||||
                        option = new FloatMenuOption($"- {quirk.Label}: {report.Reason}", null);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                menuOptions.Add(option);
 | 
			
		||||
            }
 | 
			
		||||
            Find.WindowStack.Add(new FloatMenu(menuOptions));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								RJW-Quirks/HarmonyPatches/Patch_DrawNude.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								RJW-Quirks/HarmonyPatches/Patch_DrawNude.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
using HarmonyLib;
 | 
			
		||||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Quirks;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.HarmonyPatches
 | 
			
		||||
{
 | 
			
		||||
    [HarmonyPatch(typeof(SexUtility), nameof(SexUtility.DrawNude))]
 | 
			
		||||
    public class Patch_DrawNude
 | 
			
		||||
    {
 | 
			
		||||
        public static bool Prefix(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.HasQuirk(QuirkDefOf.Endytophile))
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								RJW-Quirks/HarmonyPatches/Patch_Hediff_BasePregnancy.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								RJW-Quirks/HarmonyPatches/Patch_Hediff_BasePregnancy.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
using HarmonyLib;
 | 
			
		||||
using rjw;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Reflection.Emit;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.HarmonyPatches
 | 
			
		||||
{
 | 
			
		||||
    /*[HarmonyPatch(typeof(Hediff_BasePregnancy))]
 | 
			
		||||
    public class Patch_Hediff_BasePregnancy
 | 
			
		||||
    {
 | 
			
		||||
        [HarmonyTranspiler]
 | 
			
		||||
        [HarmonyPatch("GenerateBabies")]
 | 
			
		||||
        public static IEnumerable<CodeInstruction> AdjustMaxLitterSize(IEnumerable<CodeInstruction> instructions)
 | 
			
		||||
        {
 | 
			
		||||
            bool found = false;
 | 
			
		||||
 | 
			
		||||
            foreach (CodeInstruction i in instructions)
 | 
			
		||||
            {
 | 
			
		||||
                if (i.opcode == OpCodes.Ldc_R4 && i.operand as string == "0.33333334")
 | 
			
		||||
                    found = true;
 | 
			
		||||
 | 
			
		||||
                if (found && i.opcode == OpCodes.Stloc_S)
 | 
			
		||||
                    Log.Warning(i.operand as string);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                yield return i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }*/
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								RJW-Quirks/HarmonyPatches/Patch_Hediff_PartBaseArtifical.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								RJW-Quirks/HarmonyPatches/Patch_Hediff_PartBaseArtifical.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
using HarmonyLib;
 | 
			
		||||
using rjw;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Reflection.Emit;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.HarmonyPatches
 | 
			
		||||
{
 | 
			
		||||
    [HarmonyPatch(typeof(Hediff_PartBaseArtifical))]
 | 
			
		||||
    public class Patch_Hediff_PartBaseArtifical
 | 
			
		||||
    {
 | 
			
		||||
        [HarmonyTranspiler]
 | 
			
		||||
        [HarmonyPatch(nameof(Hediff_PartBaseArtifical.Tick))]
 | 
			
		||||
        public static IEnumerable<CodeInstruction> ChangeMaxEggsSize(IEnumerable<CodeInstruction> instructions)
 | 
			
		||||
        {
 | 
			
		||||
            FieldInfo Pawn = AccessTools.Field(typeof(Hediff_PartBaseArtifical), nameof(Hediff_PartBaseArtifical.pawn));
 | 
			
		||||
            MethodInfo EggSize = AccessTools.Method(typeof(Patch_Hediff_PartBaseArtifical), nameof(EditMaxEggsSize));
 | 
			
		||||
 | 
			
		||||
            foreach (CodeInstruction i in instructions)
 | 
			
		||||
            {
 | 
			
		||||
                if (i.opcode == OpCodes.Ldc_R4 && i.operand as string == "0.0")
 | 
			
		||||
                {
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Ldfld, Pawn);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Ldloc_3);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Call, EggSize);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                yield return i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void EditMaxEggsSize(Pawn pawn, float eggsSize)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.GetQuirks() != null)
 | 
			
		||||
                pawn.GetQuirks().ApplyValueModifiers("maxEggsSize", ref eggsSize);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								RJW-Quirks/HarmonyPatches/Patch_Hediff_PartBaseNatural.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								RJW-Quirks/HarmonyPatches/Patch_Hediff_PartBaseNatural.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
using HarmonyLib;
 | 
			
		||||
using rjw;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Reflection.Emit;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.HarmonyPatches
 | 
			
		||||
{
 | 
			
		||||
    [HarmonyPatch(typeof(Hediff_PartBaseNatural))]
 | 
			
		||||
    public class Patch_Hediff_PartBaseNatural
 | 
			
		||||
    {
 | 
			
		||||
        [HarmonyTranspiler]
 | 
			
		||||
        [HarmonyPatch(nameof(Hediff_PartBaseNatural.Tick))]
 | 
			
		||||
        public static IEnumerable<CodeInstruction> ChangeMaxEggsSize(IEnumerable<CodeInstruction> instructions)
 | 
			
		||||
        {
 | 
			
		||||
            FieldInfo Pawn = AccessTools.Field(typeof(Hediff_PartBaseNatural), nameof(Hediff_PartBaseNatural.pawn));
 | 
			
		||||
            MethodInfo EggSize = AccessTools.Method(typeof(Patch_Hediff_PartBaseNatural), nameof(EditMaxEggsSize));
 | 
			
		||||
            bool found = false;
 | 
			
		||||
 | 
			
		||||
            foreach (CodeInstruction i in instructions)
 | 
			
		||||
            {
 | 
			
		||||
                if (i.opcode == OpCodes.Ldc_R4 && i.operand as string == "0.0" && found)
 | 
			
		||||
                {
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Ldfld, Pawn);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Ldloc_3);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Call, EggSize);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (i.opcode == OpCodes.Ldc_R4 && i.operand as string == "0.0")
 | 
			
		||||
                    found = true;
 | 
			
		||||
 | 
			
		||||
                yield return i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void EditMaxEggsSize(Pawn pawn, float eggsSize)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.GetQuirks() != null)
 | 
			
		||||
                pawn.GetQuirks().ApplyValueModifiers("maxEggsSize", ref eggsSize);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								RJW-Quirks/HarmonyPatches/Patch_JobGiver_Masturbate.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								RJW-Quirks/HarmonyPatches/Patch_JobGiver_Masturbate.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
using HarmonyLib;
 | 
			
		||||
using rjw;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Reflection.Emit;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
using rjwquirks.Modules.Quirks;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.HarmonyPatches
 | 
			
		||||
{
 | 
			
		||||
    /*[HarmonyPatch(typeof(JobGiver_Masturbate))]
 | 
			
		||||
    public class Patch_JobGiver_Masturbate
 | 
			
		||||
    {
 | 
			
		||||
        [HarmonyTranspiler]
 | 
			
		||||
        [HarmonyPatch("TryGiveJob")]
 | 
			
		||||
        public static IEnumerable<CodeInstruction> ApplyQuirkToMasturbate(IEnumerable<CodeInstruction> instructions)
 | 
			
		||||
        {
 | 
			
		||||
            MethodInfo Frustrated = AccessTools.Method(typeof(xxx), nameof(xxx.is_frustrated));
 | 
			
		||||
            MethodInfo Apply = AccessTools.Method(typeof(Patch_JobGiver_Masturbate), nameof(ApplyQuirk));
 | 
			
		||||
            var labels = instructions.ElementAt(0).labels.ListFullCopy<Label>();
 | 
			
		||||
            Log.Warning(labels.Count.ToString());
 | 
			
		||||
            bool found = false;
 | 
			
		||||
 | 
			
		||||
            foreach (CodeInstruction i in instructions)
 | 
			
		||||
            {
 | 
			
		||||
                if (i.opcode == OpCodes.Call && i.operand as MethodInfo == Frustrated)
 | 
			
		||||
                {
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Ldarg_1);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Call, Apply);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Brtrue_S, labels[4]);
 | 
			
		||||
                    found = true;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (found && i.opcode == OpCodes.Call && i.operand as MethodInfo == Frustrated)
 | 
			
		||||
                {
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Ldarg_1);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Call, Apply);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Brtrue_S, labels[5]);
 | 
			
		||||
                    found = false;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                yield return i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool ApplyQuirk(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.GetQuirks() != null)
 | 
			
		||||
                return pawn.HasQuirk(QuirkDefOf.Exhibitionist);
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }*/
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								RJW-Quirks/HarmonyPatches/Patch_QuirkPartPreference.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								RJW-Quirks/HarmonyPatches/Patch_QuirkPartPreference.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
using HarmonyLib;
 | 
			
		||||
using rjw.Modules.Interactions.Contexts;
 | 
			
		||||
using rjw.Modules.Interactions.Internals.Implementation;
 | 
			
		||||
using rjw.Modules.Interactions.Rules.PartKindUsageRules;
 | 
			
		||||
using rjwquirks.Modules.Interactions;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.HarmonyPatches
 | 
			
		||||
{
 | 
			
		||||
    [HarmonyPatch(typeof(PartPreferenceDetectorService), nameof(PartPreferenceDetectorService.DetectPartPreferences))]
 | 
			
		||||
    public class Patch_QuirkPartPreference
 | 
			
		||||
    {
 | 
			
		||||
        public static void Prefix(InteractionContext context, IList<IPartPreferenceRule> ____partKindUsageRules)
 | 
			
		||||
        {
 | 
			
		||||
            if (____partKindUsageRules.Any(x => x.GetType() == typeof(QuirksPartKindUsageRule)) || (context.Internals.Submissive.Pawn.GetQuirks() == null || context.Internals.Dominant.Pawn.GetQuirks() == null))
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            Log.Warning(____partKindUsageRules.Count().ToString());
 | 
			
		||||
            ____partKindUsageRules.Add(new QuirksPartKindUsageRule());
 | 
			
		||||
            Log.Warning(____partKindUsageRules.Count().ToString());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
using HarmonyLib;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using rjwquirks.Modules.Shared.Events;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.HarmonyPatches
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Patch to generate events on record changes
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [HarmonyPatch(typeof(Pawn_RecordsTracker))]
 | 
			
		||||
	public static class Patch_RecordsTracker_NotifyRecordChanged
 | 
			
		||||
	{
 | 
			
		||||
		[HarmonyPatch(nameof(Pawn_RecordsTracker.Increment))]
 | 
			
		||||
		[HarmonyPostfix]
 | 
			
		||||
		public static void IncrementPostfix(Pawn_RecordsTracker __instance, RecordDef def)
 | 
			
		||||
		{
 | 
			
		||||
			NotifyEvent(__instance.pawn, def);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[HarmonyPatch(nameof(Pawn_RecordsTracker.AddTo))]
 | 
			
		||||
		[HarmonyPostfix]
 | 
			
		||||
		public static void AddToPostfix(Pawn_RecordsTracker __instance, RecordDef def)
 | 
			
		||||
		{
 | 
			
		||||
			NotifyEvent(__instance.pawn, def);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private static void NotifyEvent(Pawn pawn, RecordDef def) => RjwEventManager.NotifyEvent(new RjwEvent(RjwEventDefOf.RecordChanged, pawn.Named(RjwEventArgNames.Pawn), def.Named(RjwEventArgNames.Record)));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										64
									
								
								RJW-Quirks/HarmonyPatches/Patch_SexAppraiser.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								RJW-Quirks/HarmonyPatches/Patch_SexAppraiser.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,64 @@
 | 
			
		|||
using HarmonyLib;
 | 
			
		||||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Quirks;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.HarmonyPatches
 | 
			
		||||
{
 | 
			
		||||
    [HarmonyPatch(typeof(SexAppraiser))]
 | 
			
		||||
    public class Patch_SexAppraiser
 | 
			
		||||
    {
 | 
			
		||||
        [HarmonyPostfix]
 | 
			
		||||
        [HarmonyPatch(nameof(SexAppraiser.GetMinSizePreference))]
 | 
			
		||||
        public static void AdjustMinSize(Pawn pawn, ref float __result)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.GetQuirks() != null)
 | 
			
		||||
                pawn.GetQuirks().ApplyValueModifiers("wouldFuckAnimalBodySizeMin", ref __result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [HarmonyPostfix]
 | 
			
		||||
        [HarmonyPatch(nameof(SexAppraiser.GetMaxSizePreference))]
 | 
			
		||||
        public static void AdjustMaxSize(Pawn pawn, ref float __result)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.GetQuirks() != null)
 | 
			
		||||
                pawn.GetQuirks().ApplyValueModifiers("wouldFuckAnimalBodySizeMax", ref __result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [HarmonyPostfix]
 | 
			
		||||
        [HarmonyPatch(nameof(SexAppraiser.GetMinSizePreference))]
 | 
			
		||||
        public static void AdjustWildnessModifier(Pawn pawn, ref float __result)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.GetQuirks() != null)
 | 
			
		||||
                pawn.GetQuirks().ApplyValueModifiers("wouldFuckAnimalWildnessModifier", ref __result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [HarmonyPostfix]
 | 
			
		||||
        [HarmonyPatch("GetOpinionFactor")]
 | 
			
		||||
        public static void AdjustOpinionFactor(Pawn fucker, Pawn fucked, ref float __result)
 | 
			
		||||
        {
 | 
			
		||||
            if (fucker.GetQuirks() != null)
 | 
			
		||||
                fucker.GetQuirks().ApplySexAppraisalModifiers(fucked, "opinionFactor", ref __result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [HarmonyPostfix]
 | 
			
		||||
        [HarmonyPatch("GetBodyFactor")]
 | 
			
		||||
        public static void AdjustBodyFactor(Pawn fucker, Pawn fucked, ref float __result)
 | 
			
		||||
        {
 | 
			
		||||
            if (fucker.GetQuirks() != null)
 | 
			
		||||
                fucker.GetQuirks().ApplySexAppraisalModifiers(fucked, "bodyFactor", ref __result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [HarmonyPostfix]
 | 
			
		||||
        [HarmonyPatch("GetAgeFactor")]
 | 
			
		||||
        public static void AdjustAgeFactor(Pawn fucker, Pawn fucked, int p_age, ref float __result)
 | 
			
		||||
        {
 | 
			
		||||
            if (fucker.GetQuirks() != null)
 | 
			
		||||
                fucker.GetQuirks().ApplySexAppraisalModifiers(fucked, "ageFactor", ref __result);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										146
									
								
								RJW-Quirks/HarmonyPatches/Patch_SexUtility.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								RJW-Quirks/HarmonyPatches/Patch_SexUtility.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,146 @@
 | 
			
		|||
using HarmonyLib;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Quirks;
 | 
			
		||||
using rjwquirks.Modules.Shared.Events;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Reflection;
 | 
			
		||||
using System.Reflection.Emit;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.HarmonyPatches
 | 
			
		||||
{
 | 
			
		||||
    [HarmonyPatch(typeof(SexUtility))]
 | 
			
		||||
    public class Patch_SexUtility
 | 
			
		||||
    {
 | 
			
		||||
        // Increases cum filth generated by pawn
 | 
			
		||||
        [HarmonyPostfix]
 | 
			
		||||
        [HarmonyPatch(nameof(SexUtility.CumOutputModifier))]
 | 
			
		||||
        public static void FilthAdder(Pawn pawn, ref float __result)
 | 
			
		||||
        {
 | 
			
		||||
            if(pawn.GetQuirks() != null)
 | 
			
		||||
                pawn.GetQuirks().ApplyValueModifiers("cumFilthAmount", ref __result);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Change how much the pawn wants to clean post sex
 | 
			
		||||
        [HarmonyTranspiler]
 | 
			
		||||
        [HarmonyPatch(nameof(SexUtility.ConsiderCleaning))]
 | 
			
		||||
        static IEnumerable<CodeInstruction> ConsiderCleanup(IEnumerable<CodeInstruction> instructions)
 | 
			
		||||
        {
 | 
			
		||||
            FieldInfo PawnNeeds = AccessTools.Field(typeof(Pawn), nameof(Pawn.needs));
 | 
			
		||||
            MethodInfo Cleanup = AccessTools.Method(typeof(Patch_SexUtility), nameof(CleanupChanceAdjuster));
 | 
			
		||||
 | 
			
		||||
            bool found = false;
 | 
			
		||||
 | 
			
		||||
            foreach (CodeInstruction i in instructions)
 | 
			
		||||
            {
 | 
			
		||||
                if (found)
 | 
			
		||||
                {
 | 
			
		||||
                    yield return i;
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Ldloc_0);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Ldarg_0);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Call, Cleanup);
 | 
			
		||||
                    found = false;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (i.opcode == OpCodes.Ldfld && i.operand as FieldInfo == PawnNeeds)
 | 
			
		||||
                    found = true;
 | 
			
		||||
 | 
			
		||||
                yield return i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void CleanupChanceAdjuster(float chance, Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            pawn.GetQuirks().ApplyValueModifiers("cleanAfterFapChance", ref chance);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Change satisfaction from sex
 | 
			
		||||
        [HarmonyPostfix]
 | 
			
		||||
        [HarmonyPatch(nameof(SexUtility.GetExtraSatisfaction))]
 | 
			
		||||
        public static void Satisfaction(SexProps props, ref float __result)
 | 
			
		||||
        {
 | 
			
		||||
            var quirkCount = props.pawn.GetQuirks().GetSatisfiedBySex(props).Count();
 | 
			
		||||
 | 
			
		||||
            if (quirkCount > 0)
 | 
			
		||||
            {
 | 
			
		||||
                __result += props.pawn.GetQuirks().GetSatisfiedBySex(props).Count() * 0.20f;
 | 
			
		||||
                RjwEventManager.NotifyEvent(new RjwEvent(RjwEventDefOf.Orgasm, props.Named(RjwEventArgNames.SexProps), __result.Named(RjwEventArgNames.Satisfaction)));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Change ticks to next lovin
 | 
			
		||||
        [HarmonyTranspiler]
 | 
			
		||||
        [HarmonyPatch(nameof(SexUtility.GenerateMinTicksToNextLovin))]
 | 
			
		||||
        public static IEnumerable<CodeInstruction> ChangeTicksToNextLovin(IEnumerable<CodeInstruction> instructions)
 | 
			
		||||
        {
 | 
			
		||||
            MethodInfo SexDrive = AccessTools.Method(typeof(xxx), nameof(xxx.get_sex_drive));
 | 
			
		||||
            MethodInfo AdjustTicks = AccessTools.Method(typeof(Patch_SexUtility), nameof(AdjustTicksToNextLovin));
 | 
			
		||||
            bool found = false;
 | 
			
		||||
 | 
			
		||||
            foreach (var i in instructions)
 | 
			
		||||
            {
 | 
			
		||||
                if (found)
 | 
			
		||||
                {
 | 
			
		||||
                    yield return i;
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Ldloc_0);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Ldarg_0);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Call, AdjustTicks);
 | 
			
		||||
                    found = false;
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (i.opcode == OpCodes.Call && i.operand as MethodInfo == SexDrive)
 | 
			
		||||
                    found = true;
 | 
			
		||||
 | 
			
		||||
                yield return i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void AdjustTicksToNextLovin(float ticks, Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.GetQuirks() != null)
 | 
			
		||||
            {
 | 
			
		||||
                pawn.GetQuirks().ApplyValueModifiers("ticksToNextLovin", ref ticks);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Rest adjustments
 | 
			
		||||
        [HarmonyTranspiler]
 | 
			
		||||
        [HarmonyPatch(nameof(SexUtility.reduce_rest))]
 | 
			
		||||
        public static IEnumerable<CodeInstruction> AdjustRest(IEnumerable<CodeInstruction> instructions)
 | 
			
		||||
        {
 | 
			
		||||
            MethodInfo Adjustment = AccessTools.Method(typeof(Patch_SexUtility), nameof(AdjustRestFromQuirk));
 | 
			
		||||
            bool found = false;
 | 
			
		||||
            bool completed = false;
 | 
			
		||||
 | 
			
		||||
            foreach (CodeInstruction i in instructions)
 | 
			
		||||
            {
 | 
			
		||||
                if (found && !completed)
 | 
			
		||||
                {
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Ldarg_0);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Ldarg_1);
 | 
			
		||||
                    yield return new CodeInstruction(OpCodes.Call, Adjustment);
 | 
			
		||||
                    completed = true;
 | 
			
		||||
                    found = false;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (i.opcode == OpCodes.Dup)
 | 
			
		||||
                    found = true;
 | 
			
		||||
 | 
			
		||||
                yield return i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void AdjustRestFromQuirk(Pawn pawn, float x)
 | 
			
		||||
        {
 | 
			
		||||
            if(pawn.GetQuirks() != null)
 | 
			
		||||
                pawn.GetQuirks().ApplyValueModifiers("reduceRest", ref x);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										71
									
								
								RJW-Quirks/Modules/Interactions/QuirksPartKindUsageRule.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								RJW-Quirks/Modules/Interactions/QuirksPartKindUsageRule.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,71 @@
 | 
			
		|||
using rjw.Modules.Interactions.Contexts;
 | 
			
		||||
using rjw.Modules.Interactions.Enums;
 | 
			
		||||
using rjw.Modules.Interactions.Objects;
 | 
			
		||||
using rjw.Modules.Interactions.Rules.PartKindUsageRules;
 | 
			
		||||
using rjw.Modules.Shared;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Interactions
 | 
			
		||||
{
 | 
			
		||||
    public class QuirksPartKindUsageRule : IPartPreferenceRule
 | 
			
		||||
    {
 | 
			
		||||
        public IEnumerable<Weighted<LewdablePartKind>> ModifiersForDominant(InteractionContext context)
 | 
			
		||||
        {
 | 
			
		||||
            return Enumerable.Concat(
 | 
			
		||||
                ModifierFromPawnQuirks(context.Internals.Dominant, context.Internals.Submissive),
 | 
			
		||||
                ModifierFromPartnerQuirks(context.Internals.Submissive, context.Internals.Dominant)
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IEnumerable<Weighted<LewdablePartKind>> ModifiersForSubmissive(InteractionContext context)
 | 
			
		||||
        {
 | 
			
		||||
            return Enumerable.Concat(
 | 
			
		||||
                ModifierFromPawnQuirks(context.Internals.Submissive, context.Internals.Dominant),
 | 
			
		||||
                ModifierFromPartnerQuirks(context.Internals.Dominant, context.Internals.Submissive)
 | 
			
		||||
                );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// What pawn wants to use because of quirks
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private IEnumerable<Weighted<LewdablePartKind>> ModifierFromPawnQuirks(InteractionPawn quirkOwner, InteractionPawn partner)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var comp in GetQuirkComps(quirkOwner.Pawn))
 | 
			
		||||
            {
 | 
			
		||||
                foreach (var rule in comp.GetModifiersForPawn(quirkOwner, partner))
 | 
			
		||||
                {
 | 
			
		||||
                    yield return rule;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// What pawn want from partner because of pawn's quirks
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private IEnumerable<Weighted<LewdablePartKind>> ModifierFromPartnerQuirks(InteractionPawn quirkOwner, InteractionPawn partner)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var comp in GetQuirkComps(quirkOwner.Pawn))
 | 
			
		||||
            {
 | 
			
		||||
                foreach (var rule in comp.GetModifiersForPartner(quirkOwner, partner))
 | 
			
		||||
                {
 | 
			
		||||
                    yield return rule;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private IEnumerable<Quirks.Comps.PartKindUsageRules> GetQuirkComps(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var comp in pawn.GetQuirks().AllQuirks.SelectMany(quirk => quirk.def.GetComps<Quirks.Comps.PartKindUsageRules>()))
 | 
			
		||||
            {
 | 
			
		||||
                yield return comp;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								RJW-Quirks/Modules/Quirks/CompProperties_QuirkSet.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								RJW-Quirks/Modules/Quirks/CompProperties_QuirkSet.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks
 | 
			
		||||
{
 | 
			
		||||
    public class CompProperties_QuirkSet : CompProperties
 | 
			
		||||
    {
 | 
			
		||||
        public CompProperties_QuirkSet()
 | 
			
		||||
        {
 | 
			
		||||
            compClass = typeof(QuirkSet);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								RJW-Quirks/Modules/Quirks/Comps/Adder.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								RJW-Quirks/Modules/Quirks/Comps/Adder.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Base class for the comps that add quirks to the pawns
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public abstract class Adder : QuirkComp
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// For def load only. Use <see cref="GetMessageFor"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string message;
 | 
			
		||||
        public MessageTypeDef messageType;
 | 
			
		||||
 | 
			
		||||
        protected string MessageTemplate => message ?? parent.description;
 | 
			
		||||
 | 
			
		||||
        public MessageTypeDef MessageType => messageType ?? MessageTypeDefOf.NeutralEvent;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get adjusted message text to be shown to the user when adding a quirk
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string GetMessageFor(Pawn pawn) => MessageTemplate.Formatted(pawn.Named("pawn")).AdjustedFor(pawn).Resolve();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Add quirk of comp parent def to the pawn
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected void AddQuirkTo(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            Quirk addedQuirk = pawn.GetQuirks().AddQuirk(parent);
 | 
			
		||||
 | 
			
		||||
            if (addedQuirk != null)
 | 
			
		||||
            {
 | 
			
		||||
                Messages.Message(GetMessageFor(pawn), pawn, MessageType);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors(QuirkDef parent)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors(parent))
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (eventDef == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<eventDef> is empty";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										52
									
								
								RJW-Quirks/Modules/Quirks/Comps/Adder_OnRecordExceeding.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								RJW-Quirks/Modules/Quirks/Comps/Adder_OnRecordExceeding.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using rjw;
 | 
			
		||||
using rjwquirks;
 | 
			
		||||
using rjwquirks.Modules.Shared.Events;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Comp to add a quirk when <see cref="record"/> crosses <see cref="value"/>
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class Adder_OnRecordExceeding : Adder
 | 
			
		||||
    {
 | 
			
		||||
        public RecordDef record;
 | 
			
		||||
        public float value;
 | 
			
		||||
 | 
			
		||||
        protected override void HandleEvent(RjwEvent ev)
 | 
			
		||||
        {
 | 
			
		||||
            if (!ev.args.TryGetArg(RjwEventArgNames.Pawn, out Pawn pawn))
 | 
			
		||||
            {
 | 
			
		||||
                ModLog.Error($"{GetType()}.HandleEvent: No pawn in the event");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            float recordValue = pawn.records?.GetValue(record) ?? 0f;
 | 
			
		||||
 | 
			
		||||
            if (recordValue >= value && !pawn.HasQuirk(parent))
 | 
			
		||||
            {
 | 
			
		||||
                AddQuirkTo(pawn);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors(QuirkDef parent)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors(parent))
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (record == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<record> is empty";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (value == 0f)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<value> is empty";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								RJW-Quirks/Modules/Quirks/Comps/CompAdder.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								RJW-Quirks/Modules/Quirks/Comps/CompAdder.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    // Adds quirk comp to all races
 | 
			
		||||
    [StaticConstructorOnStartup]
 | 
			
		||||
    public static class CompAdder
 | 
			
		||||
    {
 | 
			
		||||
        static CompAdder()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (ThingDef thingDef in DefDatabase<ThingDef>.AllDefs.Where(thingDef =>
 | 
			
		||||
                    thingDef.race != null && !thingDef.race.Animal ))
 | 
			
		||||
            {
 | 
			
		||||
                thingDef.comps.Add(new CompProperties_QuirkSet());
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								RJW-Quirks/Modules/Quirks/Comps/HediffAdder.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								RJW-Quirks/Modules/Quirks/Comps/HediffAdder.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Shared.Events;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Comp to add an <see cref="hediff"/> to the pawn on RJW event
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class HediffAdder : QuirkComp
 | 
			
		||||
    {
 | 
			
		||||
        public HediffDef hediff;
 | 
			
		||||
 | 
			
		||||
        protected override void HandleEvent(RjwEvent ev)
 | 
			
		||||
        {
 | 
			
		||||
            if (!ev.args.TryGetArg(RjwEventArgNames.Pawn, out Pawn pawn))
 | 
			
		||||
            {
 | 
			
		||||
                ModLog.Error($"{GetType()}.HandleEvent: No pawn in the event");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            pawn.health?.AddHediff(hediff);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors(QuirkDef parent)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors(parent))
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (hediff == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<hediff> is empty";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (eventDef == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<eventDef> is empty";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								RJW-Quirks/Modules/Quirks/Comps/HediffRemover.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								RJW-Quirks/Modules/Quirks/Comps/HediffRemover.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,48 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Shared.Events;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Comp to remove an <see cref="hediff"/> to the pawn on RJW event
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class HediffRemover : QuirkComp
 | 
			
		||||
    {
 | 
			
		||||
        public HediffDef hediff;
 | 
			
		||||
 | 
			
		||||
        protected override void HandleEvent(RjwEvent ev)
 | 
			
		||||
        {
 | 
			
		||||
            if (!ev.args.TryGetArg(RjwEventArgNames.Pawn, out Pawn pawn))
 | 
			
		||||
            {
 | 
			
		||||
                ModLog.Error($"{GetType()}.HandleEvent: No pawn in the event");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Hediff existingHediff = pawn.health?.hediffSet?.GetFirstHediffOfDef(hediff);
 | 
			
		||||
            if (existingHediff != null)
 | 
			
		||||
            {
 | 
			
		||||
                pawn.health.RemoveHediff(existingHediff);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors(QuirkDef parent)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors(parent))
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (hediff == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<hediff> is empty";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (eventDef == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<eventDef> is empty";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								RJW-Quirks/Modules/Quirks/Comps/PartKindUsageRules.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								RJW-Quirks/Modules/Quirks/Comps/PartKindUsageRules.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
using rjw.Modules.Interactions.Enums;
 | 
			
		||||
using rjw.Modules.Interactions.Objects;
 | 
			
		||||
using rjw.Modules.Shared;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// QuirkComp to affect body part selection when choosing sex interaction
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public abstract class PartKindUsageRules : QuirkComp
 | 
			
		||||
	{
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Returns body parts that pawn prefers because of the quirk
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		/// <param name="pawn">Quirk owner</param>
 | 
			
		||||
		/// <param name="partner">Quirk owner's sex partner</param>
 | 
			
		||||
		public abstract IEnumerable<Weighted<LewdablePartKind>> GetModifiersForPawn(InteractionPawn quirkOwner, InteractionPawn partner);
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Returns body parts that pawn wants partner to use
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		/// <param name="pawn">Quirk owner</param>
 | 
			
		||||
		/// <param name="partner">Quirk owner's sex partner</param>
 | 
			
		||||
		public abstract IEnumerable<Weighted<LewdablePartKind>> GetModifiersForPartner(InteractionPawn quirkOwner, InteractionPawn partner);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
using rjw.Modules.Interactions.Enums;
 | 
			
		||||
using rjw.Modules.Interactions.Objects;
 | 
			
		||||
using rjw.Modules.Shared;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    public class PartKindUsageRules_ImpregnationFetish : PartKindUsageRules
 | 
			
		||||
	{
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Add desire to use penis if partner has vagina and vise-verse.
 | 
			
		||||
		/// Check of partner's parts is to avoid boosting vagina on futa when partner is female.
 | 
			
		||||
		/// No check of pawn's parts because interaction framework will filter it anyway
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public override IEnumerable<Weighted<LewdablePartKind>> GetModifiersForPawn(InteractionPawn quirkOwner, InteractionPawn partner)
 | 
			
		||||
		{
 | 
			
		||||
			if (!partner.BlockedParts.Contains(LewdablePartKind.Vagina))
 | 
			
		||||
			{
 | 
			
		||||
				yield return new Weighted<LewdablePartKind>(Multipliers.Doubled, LewdablePartKind.Penis);
 | 
			
		||||
			}
 | 
			
		||||
			if (!partner.BlockedParts.Contains(LewdablePartKind.Penis))
 | 
			
		||||
			{
 | 
			
		||||
				yield return new Weighted<LewdablePartKind>(Multipliers.Doubled, LewdablePartKind.Vagina);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Ask partner to use penis if quirk owner has vagina and provide vagina if owner has penis.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public override IEnumerable<Weighted<LewdablePartKind>> GetModifiersForPartner(InteractionPawn quirkOwner, InteractionPawn partner)
 | 
			
		||||
		{
 | 
			
		||||
			if (!quirkOwner.BlockedParts.Contains(LewdablePartKind.Vagina))
 | 
			
		||||
			{
 | 
			
		||||
				yield return new Weighted<LewdablePartKind>(Multipliers.Doubled, LewdablePartKind.Penis);
 | 
			
		||||
			}
 | 
			
		||||
			if (!quirkOwner.BlockedParts.Contains(LewdablePartKind.Penis))
 | 
			
		||||
			{
 | 
			
		||||
				yield return new Weighted<LewdablePartKind>(Multipliers.Doubled, LewdablePartKind.Vagina);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										45
									
								
								RJW-Quirks/Modules/Quirks/Comps/PartKindUsageRules_Static.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								RJW-Quirks/Modules/Quirks/Comps/PartKindUsageRules_Static.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
using rjw.Modules.Interactions.Enums;
 | 
			
		||||
using rjw.Modules.Interactions.Objects;
 | 
			
		||||
using rjw.Modules.Shared;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    public class PartKindUsageRules_Static : PartKindUsageRules
 | 
			
		||||
    {
 | 
			
		||||
        // rjw.Modules.Shared can't be loaded directly because it uses properties.
 | 
			
		||||
        // Probably should change that, but it'll cause more ripples then I'm willing to handle rn
 | 
			
		||||
        public class WeightedDef
 | 
			
		||||
        {
 | 
			
		||||
            public LewdablePartKind partKind;
 | 
			
		||||
            public float weightMultiplier;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public List<WeightedDef> self = new List<WeightedDef>();
 | 
			
		||||
        public List<WeightedDef> partner = new List<WeightedDef>();
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<Weighted<LewdablePartKind>> GetModifiersForPawn(InteractionPawn quirkOwner, InteractionPawn partner)
 | 
			
		||||
        {
 | 
			
		||||
            return self.ConvertAll(ruleDef => new Weighted<LewdablePartKind>(ruleDef.weightMultiplier, ruleDef.partKind));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<Weighted<LewdablePartKind>> GetModifiersForPartner(InteractionPawn quirkOwner, InteractionPawn partner)
 | 
			
		||||
        {
 | 
			
		||||
            return this.partner.ConvertAll(ruleDef => new Weighted<LewdablePartKind>(ruleDef.weightMultiplier, ruleDef.partKind));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors(QuirkDef parent)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors(parent))
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (self.NullOrEmpty() && partner.NullOrEmpty())
 | 
			
		||||
            {
 | 
			
		||||
                yield return "Both <self> and <partner> can not be empty";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								RJW-Quirks/Modules/Quirks/Comps/QuirkComp.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								RJW-Quirks/Modules/Quirks/Comps/QuirkComp.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
using rjwquirks.Modules.Shared.Events;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    public abstract class QuirkComp
 | 
			
		||||
    {
 | 
			
		||||
        public QuirkDef parent;
 | 
			
		||||
        public RjwEventDef eventDef;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Notify quirk comp about the RJW event
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void NotifyEvent(RjwEvent ev)
 | 
			
		||||
        {
 | 
			
		||||
            if (eventDef != null && ev.def == eventDef)
 | 
			
		||||
            {
 | 
			
		||||
                HandleEvent(ev);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Handle an RJW event. This method called only for events of <see cref="eventDef"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected virtual void HandleEvent(RjwEvent ev) { }
 | 
			
		||||
 | 
			
		||||
        public virtual IEnumerable<string> ConfigErrors(QuirkDef parent)
 | 
			
		||||
        {
 | 
			
		||||
            yield break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								RJW-Quirks/Modules/Quirks/Comps/SexAppraisalModifier.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								RJW-Quirks/Modules/Quirks/Comps/SexAppraisalModifier.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    public abstract class SexAppraisalModifier : QuirkComp
 | 
			
		||||
    {
 | 
			
		||||
        public string factorName;
 | 
			
		||||
        public QuirkModifierPriority priority = QuirkModifierPriority.Normal;
 | 
			
		||||
 | 
			
		||||
        public void TryModifyValue(Pawn quirkOwner, Pawn partner, string factorName, ref float value)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.factorName != factorName)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (parent.partnerPreference?.PartnerSatisfies(quirkOwner, partner) != true)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ModifyValue(quirkOwner, partner, ref value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public abstract void ModifyValue(Pawn quirkOwner, Pawn partner, ref float value);
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors(QuirkDef parent)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors(parent))
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (factorName.NullOrEmpty())
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<factorName> is empty";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    public class SexAppraisalModifier_ApplyMultiplier : SexAppraisalModifier
 | 
			
		||||
    {
 | 
			
		||||
        public float multiplier = 1f;
 | 
			
		||||
 | 
			
		||||
        public override void ModifyValue(Pawn quirkOwner, Pawn partner, ref float value)
 | 
			
		||||
        {
 | 
			
		||||
            value *= multiplier;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors(QuirkDef parent)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors(parent))
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (multiplier == 1f)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<multiplier> is empty or is 1";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    public class SexAppraisalModifier_SetValue : SexAppraisalModifier
 | 
			
		||||
    {
 | 
			
		||||
        public float value;
 | 
			
		||||
 | 
			
		||||
        public override void ModifyValue(Pawn quirkOwner, Pawn partner, ref float value)
 | 
			
		||||
        {
 | 
			
		||||
            value = this.value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors(QuirkDef parent)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors(parent))
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (value <= 0f)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<value> must be > 0";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								RJW-Quirks/Modules/Quirks/Comps/ThoughtAdder.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								RJW-Quirks/Modules/Quirks/Comps/ThoughtAdder.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Base class for the comps that add thoughts to the pawn
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public abstract class ThoughtAdder : QuirkComp
 | 
			
		||||
    {
 | 
			
		||||
        public ThoughtDef thought;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Add <see cref="thought"/> to the <paramref name="pawn"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void ApplyThought(Pawn pawn, Pawn partner) => pawn.needs?.mood?.thoughts?.memories?.TryGainMemory(thought, partner);
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors(QuirkDef parent)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors(parent))
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (thought == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<thought> is empty";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (eventDef == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<eventDef> is empty";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								RJW-Quirks/Modules/Quirks/Comps/ThoughtAdder_OnSexEvent.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								RJW-Quirks/Modules/Quirks/Comps/ThoughtAdder_OnSexEvent.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Shared.Events;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Base class for the comps that add thoughts on RJW event with SexProps argument
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public abstract class ThoughtAdder_OnSexEvent : ThoughtAdder
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Check if thought should be applied
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public abstract bool ShouldApplyThought(SexProps props);
 | 
			
		||||
 | 
			
		||||
        protected override void HandleEvent(RjwEvent ev)
 | 
			
		||||
        {
 | 
			
		||||
            if (!ev.args.TryGetArg(RjwEventArgNames.SexProps, out SexProps props))
 | 
			
		||||
            {
 | 
			
		||||
                ModLog.Error($"{GetType()}.HandleEvent: No SexProps in the event");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (ShouldApplyThought(props))
 | 
			
		||||
            {
 | 
			
		||||
                ApplyThought(props.pawn, props.partner);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    public class ThoughtAdder_OnSexEvent_NonPreferred : ThoughtAdder_OnSexEvent
 | 
			
		||||
    {
 | 
			
		||||
        public override bool ShouldApplyThought(SexProps props) => !parent.IsSatisfiedBySex(props);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    public class ThoughtAdder_OnSexEvent_Preferred : ThoughtAdder_OnSexEvent
 | 
			
		||||
    {
 | 
			
		||||
        public override bool ShouldApplyThought(SexProps props) => parent.IsSatisfiedBySex(props);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								RJW-Quirks/Modules/Quirks/Comps/ValueModifier.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								RJW-Quirks/Modules/Quirks/Comps/ValueModifier.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    public abstract class ValueModifier : QuirkComp
 | 
			
		||||
    {
 | 
			
		||||
        public string valueName;
 | 
			
		||||
        public QuirkModifierPriority priority = QuirkModifierPriority.Normal;
 | 
			
		||||
 | 
			
		||||
        public void TryModifyValue(string valueName, ref float value)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.valueName != valueName)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ModifyValue(ref value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public abstract void ModifyValue(ref float value);
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors(QuirkDef parent)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors(parent))
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (valueName.NullOrEmpty())
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<valueName> is empty";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    public class ValueModifier_ApplyMultiplier : ValueModifier
 | 
			
		||||
    {
 | 
			
		||||
        public float multiplier = 1f;
 | 
			
		||||
 | 
			
		||||
        public override void ModifyValue(ref float value)
 | 
			
		||||
        {
 | 
			
		||||
            value *= multiplier;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors(QuirkDef parent)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors(parent))
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (multiplier == 1f)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<multiplier> is empty or is 1";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								RJW-Quirks/Modules/Quirks/Comps/ValueModifier_ApplyOffset.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								RJW-Quirks/Modules/Quirks/Comps/ValueModifier_ApplyOffset.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.Comps
 | 
			
		||||
{
 | 
			
		||||
    public class ValueModifier_ApplyOffset : ValueModifier
 | 
			
		||||
    {
 | 
			
		||||
        public float offset;
 | 
			
		||||
 | 
			
		||||
        public override void ModifyValue(ref float value)
 | 
			
		||||
        {
 | 
			
		||||
            value += offset;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors(QuirkDef parent)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors(parent))
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (offset == 0f)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<offset> is empty or is 0";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										111
									
								
								RJW-Quirks/Modules/Quirks/EventHandlers/QuirkGenerator.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								RJW-Quirks/Modules/Quirks/EventHandlers/QuirkGenerator.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,111 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Shared.Events;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.EventHandlers
 | 
			
		||||
{
 | 
			
		||||
    public class QuirkGenerator : RjwEventHandler
 | 
			
		||||
	{
 | 
			
		||||
		public override void HandleEvent(RjwEvent ev)
 | 
			
		||||
		{
 | 
			
		||||
			if (!ev.args.TryGetArg(RjwEventArgNames.Pawn, out Pawn pawn))
 | 
			
		||||
			{
 | 
			
		||||
				ModLog.Error($"QuirkGenerator recieved {ev.def}, but event has no '{RjwEventArgNames.Pawn}' argument");
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			Generate(pawn);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Generate quirks for the pawn.
 | 
			
		||||
		/// Caution: Does not clears existing quirks
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public static void Generate(Pawn pawn)
 | 
			
		||||
		{
 | 
			
		||||
			if (!pawn.RaceHasSexNeed() || (pawn.kindDef.race.defName.ToLower().Contains("droid") && !AndroidsCompatibility.IsAndroid(pawn)))
 | 
			
		||||
			{
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			QuirkSet quirks = pawn.GetQuirks();
 | 
			
		||||
 | 
			
		||||
			if (pawn.IsAnimal())
 | 
			
		||||
			{
 | 
			
		||||
				GenerateForAnimal(quirks);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				GenerateForHumanlike(quirks);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Rolls an X number between 0 and max quirks setting.
 | 
			
		||||
		/// Tries to add random quirks to the QuirkSet until X are added or out of available quirks.
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		static void GenerateForHumanlike(QuirkSet quirks)
 | 
			
		||||
		{
 | 
			
		||||
			var count = Rand.RangeInclusive(0, RJWPreferenceSettings.MaxQuirks);
 | 
			
		||||
			var availableQuirks = DefDatabase<QuirkDef>.AllDefsListForReading
 | 
			
		||||
				.Where(def => def.rarity != QuirkRarity.ForcedOnly) // Have to earn these
 | 
			
		||||
				.ToArray(); // ToArray to get a shuffleable copy
 | 
			
		||||
			availableQuirks.Shuffle();
 | 
			
		||||
 | 
			
		||||
			// Some quirks may be hard for a given pawn to indulge in.
 | 
			
		||||
			// For example a female homosexual will have a hard time satisfying an impregnation fetish.
 | 
			
		||||
			// But rimworld is a weird place and you never know what the pawn will be capable of in the future.
 | 
			
		||||
			// We still don't want straight up contradictory results like fertile + infertile.
 | 
			
		||||
			foreach (var quirkDef in availableQuirks)
 | 
			
		||||
			{
 | 
			
		||||
				if (count == 0)
 | 
			
		||||
				{
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (!quirks.CanBeAdded(quirkDef))
 | 
			
		||||
				{
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				count--;
 | 
			
		||||
				quirks.AddQuirk(quirkDef);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Original method rolled 10% chance on 3 hardcoded animal quirks.
 | 
			
		||||
		/// This implementation takes MaxQuirks (3 by default) number of quirks from
 | 
			
		||||
		/// available for animals and rolls 10% chance for each
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		static void GenerateForAnimal(QuirkSet quirks)
 | 
			
		||||
		{
 | 
			
		||||
			int count = RJWPreferenceSettings.MaxQuirks;
 | 
			
		||||
			var availableQuirks = DefDatabase<QuirkDef>.AllDefsListForReading
 | 
			
		||||
				.Where(def => def.rarity != QuirkRarity.ForcedOnly)
 | 
			
		||||
				.ToArray();
 | 
			
		||||
			availableQuirks.Shuffle();
 | 
			
		||||
 | 
			
		||||
			foreach (var quirkDef in availableQuirks)
 | 
			
		||||
			{
 | 
			
		||||
				if (count == 0)
 | 
			
		||||
				{
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (!quirks.CanBeAdded(quirkDef))
 | 
			
		||||
				{
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				count--;
 | 
			
		||||
 | 
			
		||||
				if (Rand.Chance(0.1f))
 | 
			
		||||
				{
 | 
			
		||||
					quirks.AddQuirk(quirkDef);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Shared.Events;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.EventHandlers
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Handler that passes RJW events to a single quirk
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class QuirkRjwEventHandler : RjwEventHandler
 | 
			
		||||
    {
 | 
			
		||||
        public override void HandleEvent(RjwEvent ev)
 | 
			
		||||
        {
 | 
			
		||||
            if (!ev.args.TryGetArg(RjwEventArgNames.Quirk, out Quirk quirk))
 | 
			
		||||
            {
 | 
			
		||||
                ModLog.Error($"QuirkRjwEventHandler recieved {ev.def}, but event has no '{RjwEventArgNames.Quirk}' argument");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            quirk.NotifyEvent(ev);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Shared.Events;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.EventHandlers
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Handler that passes RJW events to all quirks of a pawn
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class QuirkSetRjwEventHandler : RjwEventHandler
 | 
			
		||||
    {
 | 
			
		||||
        public override void HandleEvent(RjwEvent ev)
 | 
			
		||||
        {
 | 
			
		||||
            ev.args.TryGetArg(RjwEventArgNames.Pawn, out Pawn pawn);
 | 
			
		||||
 | 
			
		||||
            if (pawn == null && ev.args.TryGetArg(RjwEventArgNames.SexProps, out SexProps props))
 | 
			
		||||
            {
 | 
			
		||||
                pawn = props.pawn;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (pawn == null)
 | 
			
		||||
            {
 | 
			
		||||
                ModLog.Error($"QuirkSetRjwEventHandler recieved {ev.def}, but event has neither '{RjwEventArgNames.Pawn}' or '{RjwEventArgNames.SexProps}' argument");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            pawn.GetQuirks().NotifyEvent(ev);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Shared.Events;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.EventHandlers
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Handler that passes RJW events a particular comps of an unassigned QuirkDef
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class RecordChangedRjwEventHandler : RjwEventHandler
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Records that have associated quirk adder def comps.
 | 
			
		||||
        /// Used to quickly filter out updates of irrelevant records.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static Dictionary<RecordDef, List<Comps.Adder_OnRecordExceeding>> _recordsWithAdder;
 | 
			
		||||
 | 
			
		||||
        public override void HandleEvent(RjwEvent ev)
 | 
			
		||||
        {
 | 
			
		||||
            if (ev.def != RjwEventDefOf.RecordChanged)
 | 
			
		||||
            {
 | 
			
		||||
                ModLog.Warning($"RecordChangedRjwEventHandler recieved {ev.def}, but it only handles RecordChanged event");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (_recordsWithAdder == null)
 | 
			
		||||
            {
 | 
			
		||||
                BuildAdderCache();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!ev.args.TryGetArg(RjwEventArgNames.Record, out RecordDef recordDef))
 | 
			
		||||
            {
 | 
			
		||||
                ModLog.Error($"RecordChangedRjwEventHandler recieved {ev.def}, but event has no '{RjwEventArgNames.Record}' argument");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!_recordsWithAdder.TryGetValue(recordDef, out var comps))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (var comp in comps)
 | 
			
		||||
            {
 | 
			
		||||
                // Send message to the def comps directly because the quirk is not assigned to a pawn yet
 | 
			
		||||
                comp.NotifyEvent(ev);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Builds _recordsWithAdder dictionary
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        private static void BuildAdderCache()
 | 
			
		||||
        {
 | 
			
		||||
            _recordsWithAdder = new Dictionary<RecordDef, List<Comps.Adder_OnRecordExceeding>>();
 | 
			
		||||
 | 
			
		||||
            foreach (var comp in DefDatabase<QuirkDef>.AllDefs.SelectMany(def => def.GetComps<Comps.Adder_OnRecordExceeding>()))
 | 
			
		||||
            {
 | 
			
		||||
                if (_recordsWithAdder.TryGetValue(comp.record, out var comps))
 | 
			
		||||
                {
 | 
			
		||||
                    comps.Add(comp);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    _recordsWithAdder[comp.record] = new List<Comps.Adder_OnRecordExceeding>() { comp };
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										58
									
								
								RJW-Quirks/Modules/Quirks/OwnerRequirement.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								RJW-Quirks/Modules/Quirks/OwnerRequirement.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,58 @@
 | 
			
		|||
using rjwquirks.Modules.Shared.PawnSelectors;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Class to check if quirk can be assigned to a pawn
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class OwnerRequirement
 | 
			
		||||
	{
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Requirement conditions
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public IPawnSelector pawnSelector;
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Translation key for a displayed reason why quirk can't be assigned to a pawn
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		[NoTranslate]
 | 
			
		||||
		public string rejectionReason;
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Check if pawn satisfies requirement conditions
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		public AcceptanceReport CheckBeforeAdd(Pawn pawn)
 | 
			
		||||
		{
 | 
			
		||||
			if (pawnSelector?.PawnSatisfies(pawn) == true)
 | 
			
		||||
			{
 | 
			
		||||
				return AcceptanceReport.WasAccepted;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				return new AcceptanceReport(rejectionReason.Translate());
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public IEnumerable<string> ConfigErrors()
 | 
			
		||||
		{
 | 
			
		||||
			if (pawnSelector == null)
 | 
			
		||||
			{
 | 
			
		||||
				yield return "<pawnSelector> is empty";
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				foreach (string error in pawnSelector.ConfigErrors())
 | 
			
		||||
				{
 | 
			
		||||
					yield return error;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (rejectionReason.NullOrEmpty())
 | 
			
		||||
			{
 | 
			
		||||
				yield return "<rejectionReason> is empty";
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										71
									
								
								RJW-Quirks/Modules/Quirks/Quirk.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								RJW-Quirks/Modules/Quirks/Quirk.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,71 @@
 | 
			
		|||
using rjwquirks.Modules.Shared.Events;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks
 | 
			
		||||
{
 | 
			
		||||
    public class Quirk : IExposable
 | 
			
		||||
    {
 | 
			
		||||
        public QuirkDef def;
 | 
			
		||||
        public Pawn pawn;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Adjusted for the owner and cached quirk description
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string Description
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if (descriptionCache == null)
 | 
			
		||||
                {
 | 
			
		||||
                    // Description bulding is a fairly pricy operation
 | 
			
		||||
                    descriptionCache = def.GetDescriptionFor(pawn);
 | 
			
		||||
                }
 | 
			
		||||
                return descriptionCache;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gender specific quirk label
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string Label => def.GetLabelFor(pawn);
 | 
			
		||||
 | 
			
		||||
        protected string descriptionCache;
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// For save loading only
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Quirk() { }
 | 
			
		||||
 | 
			
		||||
        public Quirk(QuirkDef def, Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            this.def = def;
 | 
			
		||||
            this.pawn = pawn;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Pass RJW event to all comps of this quirk's def
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void NotifyEvent(RjwEvent ev) => def.comps.ForEach(comp => comp.NotifyEvent(ev));
 | 
			
		||||
 | 
			
		||||
        public string TipString()
 | 
			
		||||
        {
 | 
			
		||||
            StringBuilder stringBuilder = new StringBuilder();
 | 
			
		||||
            stringBuilder.AppendLine(Label.Colorize(UnityEngine.Color.yellow));
 | 
			
		||||
            stringBuilder.Append(Description);
 | 
			
		||||
            return stringBuilder.ToString();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ExposeData()
 | 
			
		||||
        {
 | 
			
		||||
            Scribe_Defs.Look(ref def, "def");
 | 
			
		||||
 | 
			
		||||
            if (Scribe.mode == LoadSaveMode.ResolvingCrossRefs && def == null)
 | 
			
		||||
            {
 | 
			
		||||
                def = DefDatabase<QuirkDef>.GetRandom();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override string ToString() => $"Quirk({def})";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										147
									
								
								RJW-Quirks/Modules/Quirks/QuirkDef.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								RJW-Quirks/Modules/Quirks/QuirkDef.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,147 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Quirks.Comps;
 | 
			
		||||
using rjwquirks.Modules.Quirks.SexSelectors;
 | 
			
		||||
using rjwquirks.Modules.Shared.PawnSelectors;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks
 | 
			
		||||
{
 | 
			
		||||
    public class QuirkDef : Def
 | 
			
		||||
    {
 | 
			
		||||
        [MustTranslate]
 | 
			
		||||
        public string labelMale;
 | 
			
		||||
        [MustTranslate]
 | 
			
		||||
        public string labelFemale;
 | 
			
		||||
        public QuirkRarity rarity = QuirkRarity.Common;
 | 
			
		||||
        public bool hidden;
 | 
			
		||||
        public IPartnerSelector partnerPreference;
 | 
			
		||||
        public ISexSelector sexPreference;
 | 
			
		||||
        public List<OwnerRequirement> ownerRequirements = new List<OwnerRequirement>();
 | 
			
		||||
        public List<QuirkComp> comps = new List<QuirkComp>();
 | 
			
		||||
        public List<QuirkDef> conflictingQuirks = new List<QuirkDef>();
 | 
			
		||||
        public List<TraitDef> conflictingTraits = new List<TraitDef>();
 | 
			
		||||
        public List<string> exclusionTags = new List<string>();
 | 
			
		||||
 | 
			
		||||
        public string GetLabelFor(Gender gender)
 | 
			
		||||
        {
 | 
			
		||||
            if (gender == Gender.Male && !labelMale.NullOrEmpty())
 | 
			
		||||
            {
 | 
			
		||||
                return labelMale;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (gender == Gender.Female && !labelFemale.NullOrEmpty())
 | 
			
		||||
            {
 | 
			
		||||
                return labelFemale;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return label;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string GetLabelFor(Pawn pawn) => GetLabelFor(pawn?.gender ?? Gender.None);
 | 
			
		||||
 | 
			
		||||
        public IEnumerable<T> GetComps<T>() where T : QuirkComp
 | 
			
		||||
        {
 | 
			
		||||
            for (int i = 0; i < comps.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (comps[i] is T compT)
 | 
			
		||||
                    yield return compT;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool IsSatisfiedBySex(SexProps props) => sexPreference?.SexSatisfies(props) == true;
 | 
			
		||||
 | 
			
		||||
        public bool ConflictsWith(QuirkDef other)
 | 
			
		||||
        {
 | 
			
		||||
            if (other.conflictingQuirks?.Contains(this) == true || conflictingQuirks?.Contains(other) == true)
 | 
			
		||||
            {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            if (exclusionTags != null && other.exclusionTags != null)
 | 
			
		||||
            {
 | 
			
		||||
                for (int i = 0; i < exclusionTags.Count; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    if (other.exclusionTags.Contains(exclusionTags[i]))
 | 
			
		||||
                    {
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool ConflictsWith(TraitDef traitDef)
 | 
			
		||||
        {
 | 
			
		||||
            if (/*traitDef.conflictingQuirks?.Contains(this) == true || */conflictingTraits?.Contains(traitDef) == true)
 | 
			
		||||
            {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            if (exclusionTags != null && traitDef.exclusionTags != null)
 | 
			
		||||
            {
 | 
			
		||||
                for (int i = 0; i < exclusionTags.Count; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    if (traitDef.exclusionTags.Contains(exclusionTags[i]))
 | 
			
		||||
                    {
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string GetDescriptionFor(Pawn pawn) => description.Formatted(pawn.Named("pawn")).AdjustedFor(pawn).Resolve();
 | 
			
		||||
 | 
			
		||||
        public override void PostLoad()
 | 
			
		||||
        {
 | 
			
		||||
            base.PostLoad();
 | 
			
		||||
 | 
			
		||||
            foreach (QuirkComp comp in comps)
 | 
			
		||||
            {
 | 
			
		||||
                comp.parent = this;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            sexPreference?.SetParent(this);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (partnerPreference != null)
 | 
			
		||||
            {
 | 
			
		||||
                foreach (string error in partnerPreference.ConfigErrors())
 | 
			
		||||
                {
 | 
			
		||||
                    yield return error;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (sexPreference != null)
 | 
			
		||||
            {
 | 
			
		||||
                foreach (string error in sexPreference.ConfigErrors())
 | 
			
		||||
                {
 | 
			
		||||
                    yield return error;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (OwnerRequirement req in ownerRequirements)
 | 
			
		||||
            {
 | 
			
		||||
                foreach (string error in req.ConfigErrors())
 | 
			
		||||
                {
 | 
			
		||||
                    yield return error;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (QuirkComp comp in comps)
 | 
			
		||||
            {
 | 
			
		||||
                foreach (string error in comp.ConfigErrors(this))
 | 
			
		||||
                {
 | 
			
		||||
                    yield return $"{comp.GetType()}: {error}";
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								RJW-Quirks/Modules/Quirks/QuirkDefOf.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								RJW-Quirks/Modules/Quirks/QuirkDefOf.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks
 | 
			
		||||
{
 | 
			
		||||
    [DefOf]
 | 
			
		||||
    public static class QuirkDefOf
 | 
			
		||||
    {
 | 
			
		||||
        public static readonly QuirkDef Breeder;
 | 
			
		||||
        public static readonly QuirkDef Endytophile;
 | 
			
		||||
        public static readonly QuirkDef Exhibitionist;
 | 
			
		||||
        public static readonly QuirkDef ImpregnationFetish;
 | 
			
		||||
        public static readonly QuirkDef Incubator;
 | 
			
		||||
        public static readonly QuirkDef Somnophile;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								RJW-Quirks/Modules/Quirks/QuirkModifierPriority.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								RJW-Quirks/Modules/Quirks/QuirkModifierPriority.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
namespace rjwquirks.Modules.Quirks
 | 
			
		||||
{
 | 
			
		||||
    public enum QuirkModifierPriority
 | 
			
		||||
    {
 | 
			
		||||
        First,
 | 
			
		||||
        High,
 | 
			
		||||
        Normal,
 | 
			
		||||
        Low,
 | 
			
		||||
        Last
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								RJW-Quirks/Modules/Quirks/QuirkRarity.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								RJW-Quirks/Modules/Quirks/QuirkRarity.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
namespace rjwquirks.Modules.Quirks
 | 
			
		||||
{
 | 
			
		||||
    public enum QuirkRarity
 | 
			
		||||
    {
 | 
			
		||||
        ForcedOnly,
 | 
			
		||||
        Common
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										339
									
								
								RJW-Quirks/Modules/Quirks/QuirkSet.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										339
									
								
								RJW-Quirks/Modules/Quirks/QuirkSet.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,339 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using rjw;
 | 
			
		||||
using rjwquirks.Modules.Shared.Events;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// A collection/tracker of pawn's quirks
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class QuirkSet : ThingComp
 | 
			
		||||
    {
 | 
			
		||||
        protected Pawn pawn;
 | 
			
		||||
        protected List<Quirk> quirks = new List<Quirk>();
 | 
			
		||||
 | 
			
		||||
        public QuirkSet() { }
 | 
			
		||||
 | 
			
		||||
        public override void PostSpawnSetup(bool respawningAfterLoad)
 | 
			
		||||
        {
 | 
			
		||||
            base.PostSpawnSetup(respawningAfterLoad);
 | 
			
		||||
 | 
			
		||||
            pawn = parent as Pawn;
 | 
			
		||||
 | 
			
		||||
            /*if (pawn.kindDef.race.defName.Contains("AIRobot") // No genitalia/sexuality for roombas.
 | 
			
		||||
                || pawn.kindDef.race.defName.Contains("AIPawn") // ...nor MAI.
 | 
			
		||||
                || pawn.kindDef.race.defName.Contains("RPP_Bot")
 | 
			
		||||
                || pawn.kindDef.race.defName.Contains("PRFDrone") // Project RimFactory Revived drones
 | 
			
		||||
                ) return;*/
 | 
			
		||||
 | 
			
		||||
            if (Scribe.mode == LoadSaveMode.LoadingVars && quirks == null)
 | 
			
		||||
            {
 | 
			
		||||
                // Try to restore quirks from old save
 | 
			
		||||
                string quirksave = string.Empty;
 | 
			
		||||
                Scribe_Values.Look(ref quirksave, "RJW_Quirks");
 | 
			
		||||
                if (!quirksave.NullOrEmpty()) // May be pawn really has no quirks
 | 
			
		||||
                {
 | 
			
		||||
                    ParseQuirkSave(quirksave);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else if (quirks.NullOrEmpty())
 | 
			
		||||
            {
 | 
			
		||||
                //add random quirk gen and shit later/last
 | 
			
		||||
                AddQuirk(QuirkDefOf.Incubator);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// QuirkSet owner
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Pawn Pawn => pawn;
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Read-only collection of pawn quirks
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IReadOnlyCollection<Quirk> AllQuirks => quirks.AsReadOnly();
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Try to add a quirk of <paramref name="quirkDef"/> to the pawn
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="quirkDef">Def of quirk to add</param>
 | 
			
		||||
        /// <param name="ignoreChecks">Ignore all restrictions and "just do it"</param>
 | 
			
		||||
        /// <returns>Added quirk or null if addiction failed</returns>
 | 
			
		||||
        public Quirk AddQuirk(QuirkDef quirkDef, bool ignoreChecks = false)
 | 
			
		||||
        {
 | 
			
		||||
            Quirk quirk = new Quirk(quirkDef, pawn);
 | 
			
		||||
 | 
			
		||||
            if (AddQuirk(quirk, ignoreChecks).Accepted)
 | 
			
		||||
            {
 | 
			
		||||
                return quirk;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Try to add the <paramref name="quirk"/> to the pawn
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="quirk">Quirk to add</param>
 | 
			
		||||
        /// <param name="ignoreChecks">Ignore all restrictions and "just do it"</param>
 | 
			
		||||
        /// <returns>AcceptanceReport</returns>
 | 
			
		||||
        protected AcceptanceReport AddQuirk(Quirk quirk, bool ignoreChecks = false)
 | 
			
		||||
        {
 | 
			
		||||
            if (!ignoreChecks)
 | 
			
		||||
            {
 | 
			
		||||
                AcceptanceReport report = CanBeAdded(quirk.def);
 | 
			
		||||
                if (!report.Accepted)
 | 
			
		||||
                {
 | 
			
		||||
                    return report;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            quirks.Add(quirk);
 | 
			
		||||
            RjwEventManager.NotifyEvent(new RjwEvent(RjwEventDefOf.QuirkAddedTo, pawn.Named(RjwEventArgNames.Pawn), quirk.Named(RjwEventArgNames.Quirk)));
 | 
			
		||||
            return AcceptanceReport.WasAccepted;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Try to remove the <paramref name="quirk"/> from the pawn
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="quirk">Quirk to remove</param>
 | 
			
		||||
        /// <param name="ignoreChecks">Ignore all restrictions and "just do it"</param>
 | 
			
		||||
        /// <returns>AcceptanceReport</returns>
 | 
			
		||||
        public AcceptanceReport RemoveQuirk(Quirk quirk, bool ignoreChecks = false)
 | 
			
		||||
        {
 | 
			
		||||
            if (!ignoreChecks)
 | 
			
		||||
            {
 | 
			
		||||
                AcceptanceReport report = CanBeRemoved(quirk.def);
 | 
			
		||||
                if (!report.Accepted)
 | 
			
		||||
                {
 | 
			
		||||
                    return report;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            bool result = quirks.Remove(quirk);
 | 
			
		||||
 | 
			
		||||
            if (!result)
 | 
			
		||||
            {
 | 
			
		||||
                if (quirks.Contains(quirk))
 | 
			
		||||
                {
 | 
			
		||||
                    ModLog.Warning($"Tried to remove {quirk.Label} quirk from {pawn} but failed.");
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    ModLog.Warning($"Trying to remove {quirk.Label} quirk but {pawn} doesn't have it.");
 | 
			
		||||
                }
 | 
			
		||||
                return AcceptanceReport.WasRejected;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            RjwEventManager.NotifyEvent(new RjwEvent(RjwEventDefOf.QuirkRemovedFrom, pawn.Named(RjwEventArgNames.Pawn), quirk.Named(RjwEventArgNames.Quirk)));
 | 
			
		||||
            return AcceptanceReport.WasAccepted;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Check if a quirk of <paramref name="quirkDef"/> can be added to the pawn
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public AcceptanceReport CanBeAdded(QuirkDef quirkDef)
 | 
			
		||||
        {
 | 
			
		||||
            if (Contains(quirkDef))
 | 
			
		||||
            {
 | 
			
		||||
                return AcceptanceReport.WasRejected;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (OwnerRequirement req in quirkDef.ownerRequirements)
 | 
			
		||||
            {
 | 
			
		||||
                AcceptanceReport report = req.CheckBeforeAdd(pawn);
 | 
			
		||||
                if (!report.Accepted)
 | 
			
		||||
                {
 | 
			
		||||
                    return report;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (quirks.Find(quirk => quirk.def.ConflictsWith(quirkDef)) is Quirk quirked)
 | 
			
		||||
            {
 | 
			
		||||
                return new AcceptanceReport("ConflictsWithQuirk".Translate(quirked.Label));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (Pawn?.story?.traits?.allTraits is List<Trait> traits)
 | 
			
		||||
            {
 | 
			
		||||
                foreach (Trait trait in traits)
 | 
			
		||||
                {
 | 
			
		||||
                    if (quirks.Find(quirk => quirk.def.ConflictsWith(trait.def)) != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        return new AcceptanceReport("ConflictsWithTrait".Translate(trait.LabelCap));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return AcceptanceReport.WasAccepted;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Check if a quirk of <paramref name="quirkDef"/> can be removed from the pawn
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public AcceptanceReport CanBeRemoved(QuirkDef quirkDef)
 | 
			
		||||
        {
 | 
			
		||||
            if (!Contains(quirkDef))
 | 
			
		||||
            {
 | 
			
		||||
                return AcceptanceReport.WasRejected;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (quirkDef.rarity == QuirkRarity.ForcedOnly)
 | 
			
		||||
            {
 | 
			
		||||
                return new AcceptanceReport("CannotRemoveForced".Translate());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return AcceptanceReport.WasAccepted;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Check if the pawn has a quirk of <paramref name="quirkDef"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool Contains(QuirkDef quirkDef)
 | 
			
		||||
        {
 | 
			
		||||
            for (int i = 0; i < quirks.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (quirks[i].def == quirkDef)
 | 
			
		||||
                {
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get a quirk of <paramref name="quirkDef"/>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Quirk GetQuirk(QuirkDef quirkDef)
 | 
			
		||||
        {
 | 
			
		||||
            for (int i = 0; i < quirks.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (quirks[i].def == quirkDef)
 | 
			
		||||
                {
 | 
			
		||||
                    return quirks[i];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Remove all quirks from the pawn
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="ignoreChecks">even quirks that can't be removed normaly</param>
 | 
			
		||||
        public void Clear(bool ignoreChecks = false) => new List<Quirk>(quirks).ForEach(quirk => RemoveQuirk(quirk, ignoreChecks));
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Get a collection of quirks that are satified by a particular sex act
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IEnumerable<Quirk> GetSatisfiedBySex(SexProps props) => quirks.Where(quirk => quirk.def.IsSatisfiedBySex(props));
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Pass the RJW event to every quirk of the pawn
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void NotifyEvent(RjwEvent ev) => quirks.ForEach(quirk => quirk.NotifyEvent(ev));
 | 
			
		||||
 | 
			
		||||
        public void ApplySexAppraisalModifiers(Pawn partner, string factorName, ref float value)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var comp in quirks.SelectMany(quirk => quirk.def.GetComps<Comps.SexAppraisalModifier>())
 | 
			
		||||
                                        .Where(comp => comp.factorName == factorName)
 | 
			
		||||
                                        .OrderBy(comp => comp.priority))
 | 
			
		||||
            {
 | 
			
		||||
                comp.TryModifyValue(pawn, partner, factorName, ref value);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ApplyValueModifiers(string valueName, ref float value)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (var comp in quirks.SelectMany(quirk => quirk.def.GetComps<Comps.ValueModifier>())
 | 
			
		||||
                                        .Where(comp => comp.valueName == valueName)
 | 
			
		||||
                                        .OrderBy(comp => comp.priority))
 | 
			
		||||
            {
 | 
			
		||||
                comp.TryModifyValue(valueName, ref value);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ApplyValueModifiers(string valueName, ref int value)
 | 
			
		||||
        {
 | 
			
		||||
            float valueF = value;
 | 
			
		||||
            ApplyValueModifiers(valueName, ref valueF);
 | 
			
		||||
            value = (int)valueF;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void PostExposeData()
 | 
			
		||||
        {
 | 
			
		||||
            base.PostExposeData();
 | 
			
		||||
 | 
			
		||||
            Scribe_Collections.Look(ref quirks, "allQuirks", LookMode.Deep);
 | 
			
		||||
 | 
			
		||||
            if (Scribe.mode == LoadSaveMode.LoadingVars)
 | 
			
		||||
            {
 | 
			
		||||
                if (quirks.RemoveAll((x) => x == null) != 0)
 | 
			
		||||
                {
 | 
			
		||||
                    Log.Error("Some quirks were null after loading.");
 | 
			
		||||
                }
 | 
			
		||||
                if (quirks.RemoveAll((x) => x.def == null) != 0)
 | 
			
		||||
                {
 | 
			
		||||
                    Log.Error("Some quirks had null def after loading.");
 | 
			
		||||
                }
 | 
			
		||||
                for (int i = 0; i < quirks.Count; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    quirks[i].pawn = pawn;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string TipString()
 | 
			
		||||
        {
 | 
			
		||||
            if (quirks.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                return "NoQuirks".Translate();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            StringBuilder stringBuilder = new StringBuilder();
 | 
			
		||||
            foreach (var quirk in quirks.OrderBy(q => q.Label))
 | 
			
		||||
            {
 | 
			
		||||
                stringBuilder.AppendLine(quirk.TipString());
 | 
			
		||||
                stringBuilder.AppendLine("");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return stringBuilder.ToString().TrimEndNewlines();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Fill the QuirkSet from a legacy save string
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void ParseQuirkSave(string quirksave)
 | 
			
		||||
        {
 | 
			
		||||
            if (quirksave == "None")
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (string name in quirksave.Split(','))
 | 
			
		||||
            {
 | 
			
		||||
                if (name.NullOrEmpty())
 | 
			
		||||
                    continue;
 | 
			
		||||
 | 
			
		||||
                string defName = name.Trim();
 | 
			
		||||
 | 
			
		||||
                // Old keys doubled as labels. But we can't rely on that becaule def.label can be localized
 | 
			
		||||
                if (defName.Contains(" "))
 | 
			
		||||
                {
 | 
			
		||||
                    // To PascalCase
 | 
			
		||||
                    defName = defName.Split(' ').Select(part => part.CapitalizeFirst()).Aggregate((x, y) => x + y);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                QuirkDef def = DefDatabase<QuirkDef>.GetNamed(defName);
 | 
			
		||||
 | 
			
		||||
                if (def == null)
 | 
			
		||||
                    continue;
 | 
			
		||||
 | 
			
		||||
                quirks.Add(new Quirk(def, pawn));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/BySextype.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/BySextype.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.SexSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class BySextype : SexSelector
 | 
			
		||||
	{
 | 
			
		||||
		public xxx.rjwSextype sextype = xxx.rjwSextype.None;
 | 
			
		||||
 | 
			
		||||
		public override bool SexSatisfies(SexProps sexProps) => sexProps.hasPartner() && sexProps.sexType == sextype;
 | 
			
		||||
 | 
			
		||||
		public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
		{
 | 
			
		||||
			foreach (string error in base.ConfigErrors())
 | 
			
		||||
			{
 | 
			
		||||
				yield return error;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (sextype == xxx.rjwSextype.None)
 | 
			
		||||
			{
 | 
			
		||||
				yield return "<sextype> is not filled or has value \"None\"";
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.SexSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class CanBeImpregnated : SexSelector
 | 
			
		||||
    {
 | 
			
		||||
        public override bool SexSatisfies(SexProps sexProps) => sexProps.hasPartner() && PregnancyHelper.CanImpregnate(sexProps.partner, sexProps.pawn, sexProps.sexType);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/CanImpregnate.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/CanImpregnate.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.SexSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class CanImpregnate : SexSelector
 | 
			
		||||
    {
 | 
			
		||||
        public override bool SexSatisfies(SexProps sexProps) => sexProps.hasPartner() && PregnancyHelper.CanImpregnate(sexProps.pawn, sexProps.partner, sexProps.sexType);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/Clothed.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/Clothed.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.SexSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class Clothed : SexSelector
 | 
			
		||||
	{
 | 
			
		||||
		public override bool SexSatisfies(SexProps sexProps) => !sexProps.pawn.apparel.PsychologicallyNude;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/ISexSelector.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/ISexSelector.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.SexSelectors
 | 
			
		||||
{
 | 
			
		||||
    public interface ISexSelector : Shared.IDefPart
 | 
			
		||||
    {
 | 
			
		||||
        void SetParent(QuirkDef quirkDef);
 | 
			
		||||
        bool SexSatisfies(SexProps sexProps);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/LogicalAnd.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/LogicalAnd.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.SexSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class LogicalAnd : LogicalMultipart
 | 
			
		||||
    {
 | 
			
		||||
        public override bool SexSatisfies(SexProps sexProps)
 | 
			
		||||
        {
 | 
			
		||||
            for (int i = 0; i < parts.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (!parts[i].SexSatisfies(sexProps))
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/LogicalMultipart.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/LogicalMultipart.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.SexSelectors
 | 
			
		||||
{
 | 
			
		||||
    public abstract class LogicalMultipart : SexSelector
 | 
			
		||||
    {
 | 
			
		||||
        public List<ISexSelector> parts = new List<ISexSelector>();
 | 
			
		||||
 | 
			
		||||
        public override void SetParent(QuirkDef quirkDef)
 | 
			
		||||
        {
 | 
			
		||||
            base.SetParent(quirkDef);
 | 
			
		||||
            parts.ForEach(selector => selector.SetParent(quirkDef));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (parts.Count < 2)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<parts> should have at least 2 elements";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (var part in parts)
 | 
			
		||||
            {
 | 
			
		||||
                foreach (string error in part.ConfigErrors())
 | 
			
		||||
                {
 | 
			
		||||
                    yield return error;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/LogicalNot.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/LogicalNot.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.SexSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class LogicalNot : SexSelector
 | 
			
		||||
    {
 | 
			
		||||
        public ISexSelector negated;
 | 
			
		||||
 | 
			
		||||
        public override bool SexSatisfies(SexProps sexProps) => !negated.SexSatisfies(sexProps);
 | 
			
		||||
 | 
			
		||||
        public override void SetParent(QuirkDef quirkDef)
 | 
			
		||||
        {
 | 
			
		||||
            base.SetParent(quirkDef);
 | 
			
		||||
            negated.SetParent(quirkDef);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (negated == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<negated> is empty";
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                foreach (string error in negated.ConfigErrors())
 | 
			
		||||
                {
 | 
			
		||||
                    yield return error;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/LogicalOr.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/LogicalOr.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.SexSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class LogicalOr : LogicalMultipart
 | 
			
		||||
	{
 | 
			
		||||
		public override bool SexSatisfies(SexProps sexProps)
 | 
			
		||||
		{
 | 
			
		||||
			for (int i = 0; i < parts.Count; i++)
 | 
			
		||||
			{
 | 
			
		||||
				if (parts[i].SexSatisfies(sexProps))
 | 
			
		||||
				{
 | 
			
		||||
					return true;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/Seen.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/Seen.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using Verse;
 | 
			
		||||
using Verse.AI;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.SexSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class Seen : SexSelector
 | 
			
		||||
    {
 | 
			
		||||
        // Current implementation works only if somebody sees pawn exactly at the moment quirks are evaluated
 | 
			
		||||
        public override bool SexSatisfies(SexProps sexProps) => sexProps.hasPartner() && SexSeen(sexProps);
 | 
			
		||||
 | 
			
		||||
        public static bool SexSeen(SexProps sexProps)
 | 
			
		||||
        {
 | 
			
		||||
            bool isZoophile = xxx.is_zoophile(sexProps.pawn);
 | 
			
		||||
            return sexProps.pawn.Map.mapPawns.AllPawnsSpawned.Any(x =>
 | 
			
		||||
                x != sexProps.pawn
 | 
			
		||||
                && x != sexProps.partner
 | 
			
		||||
                && !x.Dead
 | 
			
		||||
                && (isZoophile || !xxx.is_animal(x))
 | 
			
		||||
                && x.CanSee(sexProps.pawn));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/SexSelector.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								RJW-Quirks/Modules/Quirks/SexSelectors/SexSelector.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.SexSelectors
 | 
			
		||||
{
 | 
			
		||||
    public abstract class SexSelector : ISexSelector
 | 
			
		||||
    {
 | 
			
		||||
        protected QuirkDef parentDef;
 | 
			
		||||
 | 
			
		||||
        public abstract bool SexSatisfies(SexProps sexProps);
 | 
			
		||||
 | 
			
		||||
        public virtual void SetParent(QuirkDef quirkDef) => parentDef = quirkDef;
 | 
			
		||||
 | 
			
		||||
        public virtual IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            yield break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Quirks.SexSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class WithPreferedPartner : SexSelector
 | 
			
		||||
    {
 | 
			
		||||
        public override bool SexSatisfies(SexProps sexProps) => sexProps.hasPartner() && parentDef.partnerPreference?.PartnerSatisfies(sexProps.pawn, sexProps.partner) == true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								RJW-Quirks/Modules/Shared/Events/RjwEvent.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								RJW-Quirks/Modules/Shared/Events/RjwEvent.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.Events
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Copy of the HistoryEvent.
 | 
			
		||||
    /// Made it it's own thing because it use cases are different
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public struct RjwEvent
 | 
			
		||||
	{
 | 
			
		||||
		public RjwEventDef def;
 | 
			
		||||
		public SignalArgs args;
 | 
			
		||||
 | 
			
		||||
		public RjwEvent(RjwEventDef def, params NamedArgument[] args)
 | 
			
		||||
		{
 | 
			
		||||
			this.def = def;
 | 
			
		||||
			this.args = new SignalArgs(args);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								RJW-Quirks/Modules/Shared/Events/RjwEventArgNames.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								RJW-Quirks/Modules/Shared/Events/RjwEventArgNames.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
namespace rjwquirks.Modules.Shared.Events
 | 
			
		||||
{
 | 
			
		||||
    public static class RjwEventArgNames
 | 
			
		||||
    {
 | 
			
		||||
        public static readonly string Pawn = "Pawn";
 | 
			
		||||
        public static readonly string SexProps = "SexProps";
 | 
			
		||||
        public static readonly string Quirk = "Quirk";
 | 
			
		||||
        public static readonly string Record = "Record";
 | 
			
		||||
        public static readonly string Satisfaction = "Satisfaction";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								RJW-Quirks/Modules/Shared/Events/RjwEventDef.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								RJW-Quirks/Modules/Shared/Events/RjwEventDef.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.Events
 | 
			
		||||
{
 | 
			
		||||
    public class RjwEventDef : Def
 | 
			
		||||
    {
 | 
			
		||||
        public List<string> obligatoryArgs;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								RJW-Quirks/Modules/Shared/Events/RjwEventDefOf.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								RJW-Quirks/Modules/Shared/Events/RjwEventDefOf.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.Events
 | 
			
		||||
{
 | 
			
		||||
    [DefOf]
 | 
			
		||||
    public static class RjwEventDefOf
 | 
			
		||||
    {
 | 
			
		||||
        public static readonly RjwEventDef QuirkAddedTo;
 | 
			
		||||
        public static readonly RjwEventDef QuirkRemovedFrom;
 | 
			
		||||
        public static readonly RjwEventDef Orgasm;
 | 
			
		||||
        public static readonly RjwEventDef RecordChanged;
 | 
			
		||||
        public static readonly RjwEventDef PawnSexualized;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								RJW-Quirks/Modules/Shared/Events/RjwEventHandler.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								RJW-Quirks/Modules/Shared/Events/RjwEventHandler.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
namespace rjwquirks.Modules.Shared.Events
 | 
			
		||||
{
 | 
			
		||||
    public abstract class RjwEventHandler
 | 
			
		||||
    {
 | 
			
		||||
        public RjwEventHandlerDef def;
 | 
			
		||||
        public abstract void HandleEvent(RjwEvent ev);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										45
									
								
								RJW-Quirks/Modules/Shared/Events/RjwEventHandlerDef.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								RJW-Quirks/Modules/Shared/Events/RjwEventHandlerDef.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.Events
 | 
			
		||||
{
 | 
			
		||||
    public class RjwEventHandlerDef : Def
 | 
			
		||||
    {
 | 
			
		||||
        public Type workerClass;
 | 
			
		||||
        public List<RjwEventDef> handlesEvents;
 | 
			
		||||
 | 
			
		||||
        private RjwEventHandler _worker;
 | 
			
		||||
 | 
			
		||||
        public RjwEventHandler Worker
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if (_worker == null)
 | 
			
		||||
                {
 | 
			
		||||
                    _worker = (RjwEventHandler)Activator.CreateInstance(workerClass);
 | 
			
		||||
                    _worker.def = this;
 | 
			
		||||
                }
 | 
			
		||||
                return _worker;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (workerClass == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<workerClass> is empty";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (handlesEvents == null || handlesEvents.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<handlesEvents> is empty";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										97
									
								
								RJW-Quirks/Modules/Shared/Events/RjwEventManager.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								RJW-Quirks/Modules/Shared/Events/RjwEventManager.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,97 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using rjw.Modules.Shared.Logs;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.Events
 | 
			
		||||
{
 | 
			
		||||
    public static class RjwEventManager
 | 
			
		||||
    {
 | 
			
		||||
        private static readonly Dictionary<RjwEventDef, List<RjwEventHandler>> _handlers = BuildHandlerDictionary();
 | 
			
		||||
        private static readonly ILog _logger = LogManager.GetLogger("RjwEventManager");
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Routes RJW events to the relevant event handlers based on the def subscriptions
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static void NotifyEvent(RjwEvent ev)
 | 
			
		||||
        {
 | 
			
		||||
            //implement own settings later
 | 
			
		||||
            if (Prefs.DevMode)
 | 
			
		||||
            {
 | 
			
		||||
                _logger.Message($"RJW Event {ev.def}{SignalArgsToString(ev.args)}");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!_handlers.TryGetValue(ev.def, out List<RjwEventHandler> eventHandlers))
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (Prefs.DevMode)
 | 
			
		||||
            {
 | 
			
		||||
                // Since event args are filled in C#, no reason to waste time checking them outside of the actual mod developement
 | 
			
		||||
                CheckObligatoryArgs(ev);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (RjwEventHandler handler in eventHandlers)
 | 
			
		||||
            {
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    handler.HandleEvent(ev);
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception e)
 | 
			
		||||
                {
 | 
			
		||||
                    // suppress exceptions so one bad mod wouldn't break everything
 | 
			
		||||
                    _logger.Error($"Handler exception when handling {ev.def}", e);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static Dictionary<RjwEventDef, List<RjwEventHandler>> BuildHandlerDictionary()
 | 
			
		||||
        {
 | 
			
		||||
            Dictionary<RjwEventDef, List<RjwEventHandler>> handlers = new Dictionary<RjwEventDef, List<RjwEventHandler>>();
 | 
			
		||||
 | 
			
		||||
            foreach (RjwEventHandlerDef handlerDef in DefDatabase<RjwEventHandlerDef>.AllDefsListForReading)
 | 
			
		||||
            {
 | 
			
		||||
                foreach (RjwEventDef eventDef in handlerDef.handlesEvents)
 | 
			
		||||
                {
 | 
			
		||||
                    if (handlers.ContainsKey(eventDef))
 | 
			
		||||
                    {
 | 
			
		||||
                        handlers[eventDef].Add(handlerDef.Worker);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        handlers[eventDef] = new List<RjwEventHandler> { handlerDef.Worker };
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return handlers;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static void CheckObligatoryArgs(RjwEvent ev)
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string argName in ev.def.obligatoryArgs)
 | 
			
		||||
            {
 | 
			
		||||
                if (!ev.args.TryGetArg(argName, out _))
 | 
			
		||||
                {
 | 
			
		||||
                    _logger.Error($"Got a {ev.def} event without the obligatory argument '{argName}'");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static string SignalArgsToString(SignalArgs args)
 | 
			
		||||
        {
 | 
			
		||||
            StringBuilder message = new StringBuilder();
 | 
			
		||||
 | 
			
		||||
            foreach (var arg in args.Args)
 | 
			
		||||
            {
 | 
			
		||||
                message.Append(", ");
 | 
			
		||||
                message.Append(arg);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return message.ToString();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								RJW-Quirks/Modules/Shared/IDefPart.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								RJW-Quirks/Modules/Shared/IDefPart.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// This interface designates that a class is ment to be included in a def and
 | 
			
		||||
    /// instantiated by the Rimworld when the def is loaded
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public interface IDefPart
 | 
			
		||||
	{
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Needed to be called explicidly in the def's ConfigErrors()
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		IEnumerable<string> ConfigErrors();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								RJW-Quirks/Modules/Shared/Selectors/IPartnerSelector.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								RJW-Quirks/Modules/Shared/Selectors/IPartnerSelector.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Partner selectors are similar to the pawn selectors, but can define relations between two pawns.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public interface IPartnerSelector : IDefPart
 | 
			
		||||
	{
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Returns true if the partner satisfies all XML-defined conditions in relation to the pawn.
 | 
			
		||||
		/// Non-commutative
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		bool PartnerSatisfies(Pawn pawn, Pawn partner);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								RJW-Quirks/Modules/Shared/Selectors/IPawnSelector.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								RJW-Quirks/Modules/Shared/Selectors/IPawnSelector.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Pawn selectors are designed to provide a flexible way to define pawn requirements in the defs
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public interface IPawnSelector : IDefPart
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Returns true if pawn satisfies all XML-defined conditions
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        bool PawnSatisfies(Pawn pawn);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PartnerSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class CanBeImpregnatedBy : PartnerSelector
 | 
			
		||||
	{
 | 
			
		||||
		public override bool PartnerSatisfies(Pawn pawn, Pawn partner) => PregnancyHelper.CanImpregnate(partner, pawn);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								RJW-Quirks/Modules/Shared/Selectors/Partner/CanImpregnate.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								RJW-Quirks/Modules/Shared/Selectors/Partner/CanImpregnate.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PartnerSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class CanImpregnate : PartnerSelector
 | 
			
		||||
    {
 | 
			
		||||
        public override bool PartnerSatisfies(Pawn pawn, Pawn partner) => PregnancyHelper.CanImpregnate(pawn, partner);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,48 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PartnerSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class HasOneOfRelations : PartnerSelector
 | 
			
		||||
    {
 | 
			
		||||
        public List<PawnRelationDef> relations;
 | 
			
		||||
 | 
			
		||||
        private HashSet<PawnRelationDef> relationsHashSet;
 | 
			
		||||
 | 
			
		||||
        public override bool PartnerSatisfies(Pawn pawn, Pawn partner)
 | 
			
		||||
        {
 | 
			
		||||
            if (relationsHashSet == null)
 | 
			
		||||
            {
 | 
			
		||||
                relationsHashSet = new HashSet<PawnRelationDef>(relations);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            IEnumerable<PawnRelationDef> pawnRelations = pawn.GetRelations(partner);
 | 
			
		||||
 | 
			
		||||
            if (pawnRelations.EnumerableNullOrEmpty())
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!relationsHashSet.Overlaps(pawnRelations))
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (relations.NullOrEmpty())
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<relations> is empty";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								RJW-Quirks/Modules/Shared/Selectors/Partner/LogicalAnd.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								RJW-Quirks/Modules/Shared/Selectors/Partner/LogicalAnd.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PartnerSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class LogicalAnd : LogicalMultipart
 | 
			
		||||
    {
 | 
			
		||||
        public override bool PartnerSatisfies(Pawn pawn, Pawn partner)
 | 
			
		||||
        {
 | 
			
		||||
            if (partner == null)
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < parts.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (!parts[i].PartnerSatisfies(pawn, partner))
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
using rjwquirks.Modules.Shared.PawnSelectors;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PartnerSelectors
 | 
			
		||||
{
 | 
			
		||||
    public abstract class LogicalMultipart : PartnerSelector
 | 
			
		||||
    {
 | 
			
		||||
        public List<IPartnerSelector> parts = new List<IPartnerSelector>();
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (parts.Count < 2)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<parts> should have at least 2 elements";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (var part in parts)
 | 
			
		||||
            {
 | 
			
		||||
                foreach (string error in part.ConfigErrors())
 | 
			
		||||
                {
 | 
			
		||||
                    yield return error;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								RJW-Quirks/Modules/Shared/Selectors/Partner/LogicalNot.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								RJW-Quirks/Modules/Shared/Selectors/Partner/LogicalNot.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
using rjwquirks.Modules.Shared.PawnSelectors;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PartnerSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class LogicalNot : PartnerSelector
 | 
			
		||||
    {
 | 
			
		||||
        public IPartnerSelector negated;
 | 
			
		||||
 | 
			
		||||
        public override bool PartnerSatisfies(Pawn pawn, Pawn partner) => !negated.PartnerSatisfies(pawn, partner);
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (negated == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<negated> is empty";
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                foreach (string error in negated.ConfigErrors())
 | 
			
		||||
                {
 | 
			
		||||
                    yield return error;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								RJW-Quirks/Modules/Shared/Selectors/Partner/LogicalOr.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								RJW-Quirks/Modules/Shared/Selectors/Partner/LogicalOr.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PartnerSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class LogicalOr : LogicalMultipart
 | 
			
		||||
    {
 | 
			
		||||
        public override bool PartnerSatisfies(Pawn pawn, Pawn partner)
 | 
			
		||||
        {
 | 
			
		||||
            if (partner == null)
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < parts.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (parts[i].PartnerSatisfies(pawn, partner))
 | 
			
		||||
                {
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
using rjwquirks.Modules.Shared.PawnSelectors;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PartnerSelectors
 | 
			
		||||
{
 | 
			
		||||
    public abstract class PartnerSelector : IPartnerSelector
 | 
			
		||||
    {
 | 
			
		||||
        public abstract bool PartnerSatisfies(Pawn pawn, Pawn partner);
 | 
			
		||||
 | 
			
		||||
        public virtual IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            yield break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasBodyType.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasBodyType.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class HasBodyType : PawnSelector
 | 
			
		||||
	{
 | 
			
		||||
		public BodyTypeDef bodyType;
 | 
			
		||||
 | 
			
		||||
		public override bool PawnSatisfies(Pawn pawn) => pawn.story?.bodyType == bodyType;
 | 
			
		||||
 | 
			
		||||
		public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
		{
 | 
			
		||||
			foreach (string error in base.ConfigErrors())
 | 
			
		||||
			{
 | 
			
		||||
				yield return error;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (bodyType == null)
 | 
			
		||||
			{
 | 
			
		||||
				yield return "<bodyType> is empty";
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasDegreeOfTrait.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasDegreeOfTrait.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class HasDegreeOfTrait : PawnSelector
 | 
			
		||||
    {
 | 
			
		||||
        public TraitDef trait;
 | 
			
		||||
        public int degree = 0;
 | 
			
		||||
 | 
			
		||||
        public override bool PawnSatisfies(Pawn pawn) => pawn.story?.traits?.HasTrait(trait, degree) == true;
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (trait == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<trait> is empty";
 | 
			
		||||
            }
 | 
			
		||||
            else if (trait.degreeDatas.Find(d => d.degree == degree) == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return $"{trait.defName} has no data for a degree {degree}";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasFertility.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasFertility.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class HasFertility : PawnSelector
 | 
			
		||||
    {
 | 
			
		||||
        public override bool PawnSatisfies(Pawn pawn) => pawn.RaceHasFertility();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasGender.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasGender.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class HasGender : PawnSelector
 | 
			
		||||
    {
 | 
			
		||||
        public Gender gender = Gender.None;
 | 
			
		||||
 | 
			
		||||
        public override bool PawnSatisfies(Pawn pawn) => pawn.gender == gender;
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (gender == Gender.None)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<gender> is empty";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasHumanScaleAge.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasHumanScaleAge.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class HasHumanScaleAge : PawnSelector
 | 
			
		||||
    {
 | 
			
		||||
        public int min = 0;
 | 
			
		||||
        public int max = 1000;
 | 
			
		||||
 | 
			
		||||
        public override bool PawnSatisfies(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            int humanScaleAge = SexUtility.ScaleToHumanAge(pawn);
 | 
			
		||||
            return min <= humanScaleAge && humanScaleAge <= max;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (min == 0 && max == 1000)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<min> and/or <max> should be filled";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasRaceTag.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasRaceTag.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using rjwquirks.Data;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class HasRaceTag : PawnSelector
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// For def load only. Use RaceTag property
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string raceTag;
 | 
			
		||||
 | 
			
		||||
        public RaceTags RaceTag
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if (RaceTags.TryParse(raceTag, out RaceTags tag))
 | 
			
		||||
                    return tag;
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override bool PawnSatisfies(Pawn pawn) => pawn.HasRaceTag(RaceTag);
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (raceTag.NullOrEmpty())
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<raceTag> is empty";
 | 
			
		||||
            }
 | 
			
		||||
            else if (!RaceTags.TryParse(raceTag, out _))
 | 
			
		||||
			{
 | 
			
		||||
				yield return $"\"{raceTag}\" is not a valid RaceTag";
 | 
			
		||||
			}
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasSkillLevel.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasSkillLevel.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class HasSkillLevel : PawnSelector
 | 
			
		||||
    {
 | 
			
		||||
        public SkillDef skill;
 | 
			
		||||
        public int minLevel = 0;
 | 
			
		||||
        public int maxLevel = 200; // mods can unlock levels past 20
 | 
			
		||||
 | 
			
		||||
        public override bool PawnSatisfies(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            int skillLevel = pawn.skills?.GetSkill(skill)?.levelInt ?? -1;
 | 
			
		||||
            return minLevel <= skillLevel && skillLevel <= maxLevel;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (skill == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<skill> is empty";
 | 
			
		||||
            }
 | 
			
		||||
            if (minLevel == 0 && maxLevel == 200)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<minLevel> and/or <maxLevel> should be filled";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasStatValue.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasStatValue.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class HasStatValue : PawnSelector
 | 
			
		||||
    {
 | 
			
		||||
        public StatDef stat;
 | 
			
		||||
        public float minValue = float.MinValue;
 | 
			
		||||
        public float maxValue = float.MaxValue;
 | 
			
		||||
 | 
			
		||||
        public override bool PawnSatisfies(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            float statValue = pawn.GetStatValue(stat);
 | 
			
		||||
            return minValue <= statValue && statValue <= maxValue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (stat == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<stat> is empty";
 | 
			
		||||
            }
 | 
			
		||||
            if (minValue == float.MinValue && maxValue == float.MaxValue)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<minValue> and/or <maxValue> should be filled";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasTrait.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/HasTrait.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class HasTrait : PawnSelector
 | 
			
		||||
    {
 | 
			
		||||
        public TraitDef trait;
 | 
			
		||||
 | 
			
		||||
        public override bool PawnSatisfies(Pawn pawn) => pawn.story?.traits?.HasTrait(trait) == true;
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (trait == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<trait> is empty";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/IsDisfigured.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/IsDisfigured.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class IsDisfigured : PawnSelector
 | 
			
		||||
    {
 | 
			
		||||
        public override bool PawnSatisfies(Pawn pawn) => RelationsUtility.IsDisfigured(pawn);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/IsHumanlike.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/IsHumanlike.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class IsHumanlike : PawnSelector
 | 
			
		||||
    {
 | 
			
		||||
        public override bool PawnSatisfies(Pawn pawn) => pawn?.RaceProps?.Humanlike == true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										10
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/IsSleeping.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/IsSleeping.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class IsSleeping : PawnSelector
 | 
			
		||||
    {
 | 
			
		||||
        public override bool PawnSatisfies(Pawn pawn) => !pawn.Awake();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
using rjw;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class IsVisiblyPregnant : PawnSelector
 | 
			
		||||
    {
 | 
			
		||||
        public override bool PawnSatisfies(Pawn pawn) => pawn.IsVisiblyPregnant();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/LogicalAnd.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/LogicalAnd.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class LogicalAnd : LogicalMultipart
 | 
			
		||||
    {
 | 
			
		||||
        public override bool PawnSatisfies(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            for (int i = 0; i < parts.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (!parts[i].PawnSatisfies(pawn))
 | 
			
		||||
                {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/LogicalMultipart.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/LogicalMultipart.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public abstract class LogicalMultipart : PawnSelector
 | 
			
		||||
    {
 | 
			
		||||
        public List<IPawnSelector> parts = new List<IPawnSelector>();
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (parts.Count < 2)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<parts> should have at least 2 elements";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach (var part in parts)
 | 
			
		||||
            {
 | 
			
		||||
                foreach (string error in part.ConfigErrors())
 | 
			
		||||
                {
 | 
			
		||||
                    yield return error;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/LogicalNot.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								RJW-Quirks/Modules/Shared/Selectors/Pawn/LogicalNot.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwquirks.Modules.Shared.PawnSelectors
 | 
			
		||||
{
 | 
			
		||||
    public class LogicalNot : PawnSelector
 | 
			
		||||
    {
 | 
			
		||||
        public IPawnSelector negated;
 | 
			
		||||
 | 
			
		||||
        public override bool PawnSatisfies(Pawn pawn) => !negated.PawnSatisfies(pawn);
 | 
			
		||||
 | 
			
		||||
        public override IEnumerable<string> ConfigErrors()
 | 
			
		||||
        {
 | 
			
		||||
            foreach (string error in base.ConfigErrors())
 | 
			
		||||
            {
 | 
			
		||||
                yield return error;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (negated == null)
 | 
			
		||||
            {
 | 
			
		||||
                yield return "<negated> is empty";
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                foreach (string error in negated.ConfigErrors())
 | 
			
		||||
                {
 | 
			
		||||
                    yield return error;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue