1.0.2.0
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 | 
			
		||||
<Manifest>
 | 
			
		||||
	<identifier>RJW Sexperience</identifier>
 | 
			
		||||
	<version>1.0.1.11b</version>
 | 
			
		||||
	<version>1.0.2.0</version>
 | 
			
		||||
	<dependencies>
 | 
			
		||||
	</dependencies>
 | 
			
		||||
	<incompatibleWith />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										
											BIN
										
									
								
								Assemblies/UnityEngine.TextCoreModule.dll
									
										
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								Assemblies/UnityEngine.TextRenderingModule.dll
									
										
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										10
									
								
								Defs/JobDefs/Jobs_CleanSelfwithBucket.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
 | 
			
		||||
<Defs>
 | 
			
		||||
	<JobDef>
 | 
			
		||||
		<defName>CleanSelfwithBucket</defName>
 | 
			
		||||
		<driverClass>RJWSexperience.JobDriver_CleanSelfWithBucket</driverClass>
 | 
			
		||||
		<reportString>collecting cum</reportString>
 | 
			
		||||
		<casualInterruptible>true</casualInterruptible>
 | 
			
		||||
	</JobDef>
 | 
			
		||||
</Defs>
 | 
			
		||||
							
								
								
									
										8
									
								
								Defs/KeyBindings/KeyBindings_Sexperience.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
 | 
			
		||||
<Defs>
 | 
			
		||||
  <KeyBindingDef ParentName="GameKeyBinding">
 | 
			
		||||
    <defName>OpenSexStatistics</defName>
 | 
			
		||||
    <label>sexperience: open sex history</label>
 | 
			
		||||
  </KeyBindingDef>
 | 
			
		||||
</Defs>
 | 
			
		||||
							
								
								
									
										38
									
								
								Defs/Recipe_Surgery/Recipes_Surgery_Hymen.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
<Defs>
 | 
			
		||||
  <RecipeDef>
 | 
			
		||||
    <defName>Surgery_RestoreHymen</defName>
 | 
			
		||||
    <label>hymenoplasty</label>
 | 
			
		||||
    <description>Disguises as virgin.</description>
 | 
			
		||||
    <workerClass>RJWSexperience.Recipe_HymenSurgery</workerClass>
 | 
			
		||||
    <jobString>restoring hymen</jobString>
 | 
			
		||||
    <effectWorking>Surgery</effectWorking>
 | 
			
		||||
    <soundWorking>Recipe_Surgery</soundWorking>
 | 
			
		||||
    <workSpeedStat>MedicalOperationSpeed</workSpeedStat>
 | 
			
		||||
    <workSkill>Medicine</workSkill>
 | 
			
		||||
    <workSkillLearnFactor>0.2</workSkillLearnFactor>
 | 
			
		||||
    <workAmount>400</workAmount>
 | 
			
		||||
	<anesthetize>false</anesthetize>
 | 
			
		||||
	<recipeUsers>
 | 
			
		||||
		<li>Human</li>
 | 
			
		||||
	</recipeUsers>
 | 
			
		||||
    <surgerySuccessChanceFactor>100</surgerySuccessChanceFactor>
 | 
			
		||||
    <ingredients>
 | 
			
		||||
      <li>
 | 
			
		||||
        <filter>
 | 
			
		||||
          <categories>
 | 
			
		||||
            <li>Medicine</li>
 | 
			
		||||
          </categories>
 | 
			
		||||
        </filter>
 | 
			
		||||
        <count>1</count>
 | 
			
		||||
      </li>
 | 
			
		||||
    </ingredients>
 | 
			
		||||
    <fixedIngredientFilter>
 | 
			
		||||
      <categories>
 | 
			
		||||
        <li>Medicine</li>
 | 
			
		||||
      </categories>
 | 
			
		||||
    </fixedIngredientFilter>
 | 
			
		||||
  </RecipeDef>
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
</Defs>
 | 
			
		||||
| 
						 | 
				
			
			@ -4,7 +4,14 @@
 | 
			
		|||
	<RecordDef>
 | 
			
		||||
		<defName>NumofEatenCum</defName>
 | 
			
		||||
		<label>swallowed cum</label>
 | 
			
		||||
		<description>The number of times that i swalloed cum.</description>
 | 
			
		||||
		<description>The number of times that i swallowed cum.</description>
 | 
			
		||||
		<type>Int</type>
 | 
			
		||||
	</RecordDef>
 | 
			
		||||
 | 
			
		||||
	<RecordDef>
 | 
			
		||||
		<defName>AmountofEatenCum</defName>
 | 
			
		||||
		<label>swallowed cum(mL)</label>
 | 
			
		||||
		<description>The amount of cum that i swallowed.</description>
 | 
			
		||||
		<type>Int</type>
 | 
			
		||||
	</RecordDef>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,7 @@
 | 
			
		|||
	</RecordDef>
 | 
			
		||||
 | 
			
		||||
	<RecordDef>
 | 
			
		||||
		<defName>HadnjobCount</defName>
 | 
			
		||||
		<defName>HandjobCount</defName>
 | 
			
		||||
		<label>handjobs</label>
 | 
			
		||||
		<description>The number of times of handjob.</description>
 | 
			
		||||
		<type>Int</type>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
<Defs>
 | 
			
		||||
  <ThingDef Name ="GatheredCum" ParentName="OrganicProductBase">
 | 
			
		||||
	<ThingDef Name="GatheredCum" ParentName="OrganicProductBase">
 | 
			
		||||
		<defName>GatheredCum</defName>
 | 
			
		||||
		<label>cum</label>
 | 
			
		||||
		<description>Gathered cum.</description>
 | 
			
		||||
| 
						 | 
				
			
			@ -39,6 +39,7 @@
 | 
			
		|||
				<li Class="IngestionOutcomeDoer_OffsetPsyfocus">
 | 
			
		||||
					<offset>0.05</offset>
 | 
			
		||||
				</li>
 | 
			
		||||
				<li Class="RJWSexperience.CumOutcomeDoers"/>
 | 
			
		||||
			</outcomeDoers>
 | 
			
		||||
		</ingestible>
 | 
			
		||||
		<comps>
 | 
			
		||||
| 
						 | 
				
			
			@ -53,61 +54,6 @@
 | 
			
		|||
		</comps>
 | 
			
		||||
	</ThingDef>
 | 
			
		||||
 | 
			
		||||
	<ThingDef ParentName="PlantFoodRawBase">
 | 
			
		||||
		<defName>UsedCondom</defName>
 | 
			
		||||
		<label>Used Condom</label>
 | 
			
		||||
		<description>A condom filled with sperm. MMMM So good and tasty!</description>
 | 
			
		||||
		<graphicData>
 | 
			
		||||
			<texPath>Things/Item/UsedCondom</texPath>
 | 
			
		||||
			<graphicClass>Graphic_StackCount</graphicClass>
 | 
			
		||||
		</graphicData>
 | 
			
		||||
		<stackLimit>50</stackLimit>
 | 
			
		||||
		<useHitPoints>true</useHitPoints>
 | 
			
		||||
		<selectable>true</selectable>
 | 
			
		||||
		<generateCommonality>0.0</generateCommonality>
 | 
			
		||||
		<techLevel>Industrial</techLevel>
 | 
			
		||||
		<statBases>
 | 
			
		||||
			<Beauty>-10</Beauty>
 | 
			
		||||
			<MarketValue>1</MarketValue>
 | 
			
		||||
			<Mass>0.05</Mass>
 | 
			
		||||
      		<Nutrition>0.05</Nutrition>
 | 
			
		||||
		</statBases>
 | 
			
		||||
		<ingestible>
 | 
			
		||||
			<foodType>Fluid, AnimalProduct</foodType>
 | 
			
		||||
			<preferability>DesperateOnlyForHumanlikes</preferability>
 | 
			
		||||
	    <tasteThought>AteCum</tasteThought>
 | 
			
		||||
	    <specialThoughtAsIngredient>AteCum</specialThoughtAsIngredient>
 | 
			
		||||
		<outcomeDoers>
 | 
			
		||||
			<li Class="IngestionOutcomeDoer_GiveHediff">
 | 
			
		||||
				<hediffDef>CumTolerance</hediffDef>
 | 
			
		||||
				<severity>0.032</severity>
 | 
			
		||||
				<divideByBodySize>true</divideByBodySize>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li Class="IngestionOutcomeDoer_OffsetPsyfocus">
 | 
			
		||||
				<offset>0.05</offset>
 | 
			
		||||
			</li>
 | 
			
		||||
		</outcomeDoers>
 | 
			
		||||
		</ingestible>
 | 
			
		||||
		<altitudeLayer>Item</altitudeLayer>
 | 
			
		||||
		<tickerType>Never</tickerType>
 | 
			
		||||
		<tradeTags>
 | 
			
		||||
			<li>Exotic</li>
 | 
			
		||||
		</tradeTags>
 | 
			
		||||
		<tradeability>Sellable</tradeability>
 | 
			
		||||
		<thingCategories>
 | 
			
		||||
			<li>AnimalProductRaw</li>
 | 
			
		||||
		</thingCategories>
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="CompProperties_Drug">
 | 
			
		||||
				<chemical>Cum</chemical>
 | 
			
		||||
				<addictiveness>0.050</addictiveness>
 | 
			
		||||
				<minToleranceToAddict>0.8</minToleranceToAddict>
 | 
			
		||||
				<existingAddictionSeverityOffset>0.1</existingAddictionSeverityOffset>
 | 
			
		||||
				<needLevelOffset>1</needLevelOffset>
 | 
			
		||||
				<listOrder>30</listOrder>
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>
 | 
			
		||||
	</ThingDef>
 | 
			
		||||
 | 
			
		||||
	<ChemicalDef>
 | 
			
		||||
		<defName>Cum</defName>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,10 +7,13 @@
 | 
			
		|||
		<commonalityFemale>0.0</commonalityFemale>
 | 
			
		||||
		<degreeDatas>
 | 
			
		||||
			<li>
 | 
			
		||||
				<label>virgin</label>
 | 
			
		||||
				<description>[PAWN_nameDef] has no experience.</description>
 | 
			
		||||
				<labelMale>BUGGED! MALE CANNOT HAS THIS TRAIT</labelMale>
 | 
			
		||||
				<labelFemale>damaged virgin</labelFemale>
 | 
			
		||||
				<description>[PAWN_nameDef] never experienced. However, her hymen had damaged for some reason.</description>
 | 
			
		||||
				<degree>-1</degree>
 | 
			
		||||
				<marketValueFactorOffset>0.05</marketValueFactorOffset>
 | 
			
		||||
				<statOffsets>
 | 
			
		||||
					<SexFrequency>0.1</SexFrequency>
 | 
			
		||||
					<SexFrequency>0.2</SexFrequency>
 | 
			
		||||
				</statOffsets>
 | 
			
		||||
				<skillGains>
 | 
			
		||||
					<li>
 | 
			
		||||
| 
						 | 
				
			
			@ -19,6 +22,43 @@
 | 
			
		|||
					</li>
 | 
			
		||||
				</skillGains>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li>
 | 
			
		||||
				<label>virgin</label>
 | 
			
		||||
				<description>[PAWN_nameDef] never experienced.</description>
 | 
			
		||||
				<degree>0</degree>
 | 
			
		||||
				<statOffsets>
 | 
			
		||||
					<SexFrequency>0.2</SexFrequency>
 | 
			
		||||
				</statOffsets>
 | 
			
		||||
				<skillGains>
 | 
			
		||||
					<li>
 | 
			
		||||
						<key>Sex</key>
 | 
			
		||||
						<value>-4</value>
 | 
			
		||||
					</li>
 | 
			
		||||
				</skillGains>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li>
 | 
			
		||||
				<labelMale>BUGGED! MALE CANNOT HAS THIS TRAIT</labelMale>
 | 
			
		||||
				<labelFemale>virgin?</labelFemale>
 | 
			
		||||
				<description>[PAWN_nameDef] looks experienced. But the hymen is still threre.</description>
 | 
			
		||||
				<marketValueFactorOffset>0.10</marketValueFactorOffset>
 | 
			
		||||
				<degree>1</degree>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li>
 | 
			
		||||
				<labelMale>BUGGED! MALE CANNOT HAS THIS TRAIT</labelMale>
 | 
			
		||||
				<labelFemale>virgin</labelFemale>
 | 
			
		||||
				<description>[PAWN_nameDef] never experienced.</description>
 | 
			
		||||
				<degree>2</degree>
 | 
			
		||||
				<statOffsets>
 | 
			
		||||
					<SexFrequency>0.2</SexFrequency>
 | 
			
		||||
				</statOffsets>
 | 
			
		||||
				<skillGains>
 | 
			
		||||
					<li>
 | 
			
		||||
						<key>Sex</key>
 | 
			
		||||
						<value>-4</value>
 | 
			
		||||
					</li>
 | 
			
		||||
				</skillGains>
 | 
			
		||||
				<marketValueFactorOffset>0.20</marketValueFactorOffset>
 | 
			
		||||
			</li>
 | 
			
		||||
		</degreeDatas>
 | 
			
		||||
	</TraitDef>
 | 
			
		||||
</Defs>
 | 
			
		||||
| 
						 | 
				
			
			@ -13,6 +13,48 @@
 | 
			
		|||
  <RSShouldCanFuck>capable of sex is required</RSShouldCanFuck>
 | 
			
		||||
  <RSTotalGatheredCum>Total gathered cum: </RSTotalGatheredCum>
 | 
			
		||||
  <RS_LostVirgin>{1} took {0}'s virginity.</RS_LostVirgin>
 | 
			
		||||
  <RS_FloatMenu_CleanSelf>Gather cums on body</RS_FloatMenu_CleanSelf>
 | 
			
		||||
  <RS_Best_Sextype>Best sextype</RS_Best_Sextype>
 | 
			
		||||
  <RS_Recent_Sextype>Recent sextype</RS_Recent_Sextype>
 | 
			
		||||
  <RS_Sex_Partners>Sex partners</RS_Sex_Partners>
 | 
			
		||||
  <RS_Cum_Swallowed>Cum swallowed</RS_Cum_Swallowed>
 | 
			
		||||
  <RS_Selected_Partner>Selected Partner's Info</RS_Selected_Partner>
 | 
			
		||||
  <RS_Sex_Info>{0}: {1} times</RS_Sex_Info>
 | 
			
		||||
  <RS_SAT_AVG>Avg: {0}</RS_SAT_AVG>
 | 
			
		||||
  <RS_Sex_Count>Sex count: </RS_Sex_Count>
 | 
			
		||||
  <RS_Orgasms>Orgasms: </RS_Orgasms>
 | 
			
		||||
  <RS_Recent_Sex_Partner>Recent Sex Partner</RS_Recent_Sex_Partner>
 | 
			
		||||
  <RS_Recent_Sex_Partner_ToolTip>A recent sex partner.</RS_Recent_Sex_Partner_ToolTip>
 | 
			
		||||
  <RS_First_Sex_Partner>First Sex Partner</RS_First_Sex_Partner>
 | 
			
		||||
  <RS_First_Sex_Partner_ToolTip>The first sex partner.</RS_First_Sex_Partner_ToolTip>
 | 
			
		||||
  <RS_Most_Sex_Partner>Most Sex Partner</RS_Most_Sex_Partner>
 | 
			
		||||
  <RS_Most_Sex_Partner_ToolTip>The most sex partner.</RS_Most_Sex_Partner_ToolTip>
 | 
			
		||||
  <RS_Best_Sex_Partner>Best Sex Partner</RS_Best_Sex_Partner>
 | 
			
		||||
  <RS_Best_Sex_Partner_ToolTip>The partner who had most satisfying sex.</RS_Best_Sex_Partner_ToolTip>
 | 
			
		||||
  <RS_VirginsTaken>Taken virgins</RS_VirginsTaken>
 | 
			
		||||
  <RS_VirginsTaken_ToolTip>The number of partners who i taken first.</RS_VirginsTaken_ToolTip>
 | 
			
		||||
  <RS_TotalSexHad>Total sex had</RS_TotalSexHad>
 | 
			
		||||
  <RS_TotalSexHad_ToolTip>Total number of sex.</RS_TotalSexHad_ToolTip>
 | 
			
		||||
  <RS_Raped>Raped: </RS_Raped>
 | 
			
		||||
  <RS_RapedMe>Raped me: </RS_RapedMe>
 | 
			
		||||
  <RS_Sex_History>Sex History</RS_Sex_History>
 | 
			
		||||
  <RS_Statistics>Sex Statistics</RS_Statistics>
 | 
			
		||||
  <RS_PartnerList>Partner List</RS_PartnerList>
 | 
			
		||||
  <RS_Sexuality>Sexuality</RS_Sexuality>
 | 
			
		||||
  <RS_BeenRaped>Had been raped</RS_BeenRaped>
 | 
			
		||||
  <RS_RapedSomeone>Raped someone</RS_RapedSomeone>
 | 
			
		||||
  <RS_PreferRace>Prefer Race</RS_PreferRace>
 | 
			
		||||
  <RS_Bestiality>Bestiality</RS_Bestiality>
 | 
			
		||||
  <RS_Interspecies>Interspecies</RS_Interspecies>
 | 
			
		||||
  <RS_Normal>Normal</RS_Normal>
 | 
			
		||||
  <RS_Necrophile>Necrophile</RS_Necrophile>
 | 
			
		||||
  <RS_GatherCum>Gather cum</RS_GatherCum>
 | 
			
		||||
  <RS_SexSkill>Sex skill</RS_SexSkill>
 | 
			
		||||
  <RS_CumAddiction>Cum addiction</RS_CumAddiction>
 | 
			
		||||
  <RS_CumAddiction_Tooltip>Addicted to cum.</RS_CumAddiction_Tooltip>
 | 
			
		||||
  <RS_CumAddictiveness>Cum addictiveness</RS_CumAddictiveness>
 | 
			
		||||
  <RS_CumAddictiveness_Tooltip>More likely to get addicted to cum.</RS_CumAddictiveness_Tooltip>
 | 
			
		||||
  <RS_NumofTimes>times</RS_NumofTimes>
 | 
			
		||||
 | 
			
		||||
  <RSOption_1_Label>Enable record randomizer</RSOption_1_Label>
 | 
			
		||||
  <RSOption_1_Desc>Randomize pawn's sex records.</RSOption_1_Desc>
 | 
			
		||||
| 
						 | 
				
			
			@ -37,4 +79,40 @@
 | 
			
		|||
  <RSOption_11_Label></RSOption_11_Label>
 | 
			
		||||
  <RSOption_11_Desc> </RSOption_11_Desc>
 | 
			
		||||
 | 
			
		||||
  <Vaginal>Vaginal</Vaginal>
 | 
			
		||||
  <Anal>Anal</Anal>
 | 
			
		||||
  <Oral>Oral</Oral>
 | 
			
		||||
  <Masturbation>Masturbation</Masturbation>
 | 
			
		||||
  <DoublePenetration>Double penetration</DoublePenetration>
 | 
			
		||||
  <Boobjob>Boobjob</Boobjob>
 | 
			
		||||
  <Handjob>Handjob</Handjob>
 | 
			
		||||
  <Footjob>Footjob</Footjob>
 | 
			
		||||
  <Fingering>Fingering</Fingering>
 | 
			
		||||
  <Scissoring>Scissoring</Scissoring>
 | 
			
		||||
  <MutualMasturbation>Mutual masturbation</MutualMasturbation>
 | 
			
		||||
  <Fisting>Fisting</Fisting>
 | 
			
		||||
  <MechImplant>Mech implant</MechImplant>
 | 
			
		||||
  <Rimming>Rimming</Rimming>
 | 
			
		||||
  <Fellatio>Fellatio</Fellatio>
 | 
			
		||||
  <Cunnilingus>Cunnilingus</Cunnilingus>
 | 
			
		||||
  <Sixtynine>Sixtynine</Sixtynine>
 | 
			
		||||
 | 
			
		||||
  <None>None</None>
 | 
			
		||||
  <Asexual>Asexual</Asexual>
 | 
			
		||||
  <Pansexual>Pansexual</Pansexual>
 | 
			
		||||
  <Heterosexual>Hetero</Heterosexual>
 | 
			
		||||
  <MostlyHeterosexual>Mostly hetero</MostlyHeterosexual>
 | 
			
		||||
  <LeaningHeterosexual>Bisexual, leaning hetero</LeaningHeterosexual>
 | 
			
		||||
  <Bisexual>Bisexual</Bisexual>
 | 
			
		||||
  <LeaningHomosexual>Bisexual, leaning gay</LeaningHomosexual>
 | 
			
		||||
  <MostlyHomosexual>Mostly gay</MostlyHomosexual>
 | 
			
		||||
  <Homosexual>Gay</Homosexual>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  <Lust>lust</Lust>
 | 
			
		||||
  <Unknown>unknown</Unknown>
 | 
			
		||||
  <Virgin>virgin</Virgin>
 | 
			
		||||
  <Incest>incest</Incest>
 | 
			
		||||
 | 
			
		||||
</LanguageData>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<LanguageData>
 | 
			
		||||
  <Bastard.label>사생아</Bastard.label>
 | 
			
		||||
  <Bastard.labelFemale>사생아</Bastard.labelFemale>
 | 
			
		||||
</LanguageData>
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +11,8 @@
 | 
			
		|||
  <RSNotHuman>사람이 아님</RSNotHuman>
 | 
			
		||||
  <RSNotAnimal>동물이 아님</RSNotAnimal>
 | 
			
		||||
  <RSShouldCanFuck>성관계가 가능해야 합니다.</RSShouldCanFuck>
 | 
			
		||||
  <RSTotalGatheredCum>수집한 정액 양: </RSTotalGatheredCum>
 | 
			
		||||
  <RS_LostVirgin>{1}이(가) {0}의 아다를 뗐습니다.</RS_LostVirgin>
 | 
			
		||||
 | 
			
		||||
  <RSOption_1_Label>기록 생성기 활성화</RSOption_1_Label>
 | 
			
		||||
  <RSOption_1_Desc>폰의 섹스기록을 무작위로 생성합니다.</RSOption_1_Desc>
 | 
			
		||||
| 
						 | 
				
			
			@ -28,4 +30,8 @@
 | 
			
		|||
  <RSOption_7_Desc>활성화할 경우 노예는 강간당한 경험을 가집니다.</RSOption_7_Desc>
 | 
			
		||||
  <RSOption_8_Label>음란함 한계</RSOption_8_Label>
 | 
			
		||||
  <RSOption_8_Desc>음란함의 한계치를 설정합니다.
음란함의 절대값이 이 값에 가까워지거나 클수록, 음란함이 적게 변합니다.</RSOption_8_Desc>
 | 
			
		||||
  <RSOption_9_Label>섹스가능 최소나이</RSOption_9_Label>
 | 
			
		||||
  <RSOption_9_Desc>섹스 가능한 최소나이를 설정합니다.
이 값은 RJW의 최소 나이 설정과 관계가 없고 기록을 생성하는데만 사용됩니다.</RSOption_9_Desc>
 | 
			
		||||
  <RSOption_10_Label>동정 비율</RSOption_10_Label>
 | 
			
		||||
  <RSOption_10_Desc>나이 상관없이 동정일 확률을 설정합니다.</RSOption_10_Desc>
 | 
			
		||||
</LanguageData>
 | 
			
		||||
							
								
								
									
										75
									
								
								Patches/RJW_ThingDefs.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,75 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
 | 
			
		||||
<Patch>
 | 
			
		||||
 | 
			
		||||
	<Operation Class="PatchOperationConditional">
 | 
			
		||||
		<xpath>Defs/ThingDef[defName="UsedCondom"]/ingestible/outcomeDoers</xpath>
 | 
			
		||||
		<nomatch Class="PatchOperationAdd">
 | 
			
		||||
			<xpath>Defs/ThingDef[defName="UsedCondom"]/ingestible</xpath>
 | 
			
		||||
			<value>
 | 
			
		||||
				<outcomeDoers>
 | 
			
		||||
					<li Class="IngestionOutcomeDoer_GiveHediff">
 | 
			
		||||
						<hediffDef>CumTolerance</hediffDef>
 | 
			
		||||
						<severity>0.032</severity>
 | 
			
		||||
						<divideByBodySize>true</divideByBodySize>
 | 
			
		||||
					</li>
 | 
			
		||||
					<li Class="IngestionOutcomeDoer_OffsetPsyfocus">
 | 
			
		||||
						<offset>0.05</offset>
 | 
			
		||||
					</li>
 | 
			
		||||
					<li Class="RJWSexperience.CumOutcomeDoers">
 | 
			
		||||
						<unitAmount>5.2</unitAmount>
 | 
			
		||||
					</li>
 | 
			
		||||
				</outcomeDoers>
 | 
			
		||||
			</value>
 | 
			
		||||
		</nomatch>
 | 
			
		||||
		<match Class="PatchOperationAdd">
 | 
			
		||||
			<xpath>Defs/ThingDef[defName="UsedCondom"]/ingestible/outcomeDoers</xpath>
 | 
			
		||||
			<value>
 | 
			
		||||
				<li Class="IngestionOutcomeDoer_GiveHediff">
 | 
			
		||||
					<hediffDef>CumTolerance</hediffDef>
 | 
			
		||||
					<severity>0.032</severity>
 | 
			
		||||
					<divideByBodySize>true</divideByBodySize>
 | 
			
		||||
				</li>
 | 
			
		||||
				<li Class="IngestionOutcomeDoer_OffsetPsyfocus">
 | 
			
		||||
					<offset>0.05</offset>
 | 
			
		||||
				</li>
 | 
			
		||||
				<li Class="RJWSexperience.CumOutcomeDoers">
 | 
			
		||||
					<unitAmount>5.2</unitAmount>
 | 
			
		||||
				</li>
 | 
			
		||||
			</value>
 | 
			
		||||
		</match>
 | 
			
		||||
	</Operation>
 | 
			
		||||
 | 
			
		||||
	<Operation Class="PatchOperationConditional">
 | 
			
		||||
		<xpath>Defs/ThingDef[defName="UsedCondom"]/comps</xpath>
 | 
			
		||||
		<nomatch Class="PatchOperationAdd">
 | 
			
		||||
			<xpath>Defs/ThingDef[defName="UsedCondom"]</xpath>
 | 
			
		||||
			<value>
 | 
			
		||||
				<comps>
 | 
			
		||||
					<li Class="CompProperties_Drug">
 | 
			
		||||
						<chemical>Cum</chemical>
 | 
			
		||||
						<addictiveness>0.050</addictiveness>
 | 
			
		||||
						<minToleranceToAddict>0.8</minToleranceToAddict>
 | 
			
		||||
						<existingAddictionSeverityOffset>0.1</existingAddictionSeverityOffset>
 | 
			
		||||
						<needLevelOffset>1</needLevelOffset>
 | 
			
		||||
						<listOrder>30</listOrder>
 | 
			
		||||
					</li>
 | 
			
		||||
				</comps>
 | 
			
		||||
			</value>
 | 
			
		||||
		</nomatch>
 | 
			
		||||
		<match Class="PatchOperationAdd">
 | 
			
		||||
			<xpath>Defs/ThingDef[defName="UsedCondom"]/comps</xpath>
 | 
			
		||||
			<value>
 | 
			
		||||
				<li Class="CompProperties_Drug">
 | 
			
		||||
					<chemical>Cum</chemical>
 | 
			
		||||
					<addictiveness>0.050</addictiveness>
 | 
			
		||||
					<minToleranceToAddict>0.8</minToleranceToAddict>
 | 
			
		||||
					<existingAddictionSeverityOffset>0.1</existingAddictionSeverityOffset>
 | 
			
		||||
					<needLevelOffset>1</needLevelOffset>
 | 
			
		||||
					<listOrder>30</listOrder>
 | 
			
		||||
				</li>
 | 
			
		||||
			</value>
 | 
			
		||||
		</match>
 | 
			
		||||
	</Operation>
 | 
			
		||||
 | 
			
		||||
</Patch>
 | 
			
		||||
| 
						 | 
				
			
			@ -19,16 +19,21 @@ namespace RJWSexperience.Ideology
 | 
			
		|||
		public const string Incestous = "[Incestuos]";
 | 
			
		||||
		public const string BeenRaped = "[BeenRaped]";
 | 
			
		||||
		public const string Rape = "[Rape]";
 | 
			
		||||
		public const string Spouse = "[Spouse]";
 | 
			
		||||
		public const string NotSpouse = "[NotSpouse]";
 | 
			
		||||
 | 
			
		||||
		public static string Gender(Pawn pawn) => "[" + pawn.gender + "]";
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	public class PreceptComp_SelfTookThoughtTagged : PreceptComp_SelfTookMemoryThought
 | 
			
		||||
	{
 | 
			
		||||
		public string tag;
 | 
			
		||||
		public bool exclusive = false;
 | 
			
		||||
		public RecordDef recordDef;
 | 
			
		||||
		public float? recordoffset;
 | 
			
		||||
		//public RecordDef recordDef;
 | 
			
		||||
		//public float? recordoffset;
 | 
			
		||||
 | 
			
		||||
		public PreceptComp_SelfTookThoughtTagged() { }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -41,28 +46,28 @@ namespace RJWSexperience.Ideology
 | 
			
		|||
					if (tags.ContainAll(tag.Replace(" ","").Split(',')) ^ exclusive)
 | 
			
		||||
                    {
 | 
			
		||||
						TookThought(ev, precept, canApplySelfTookThoughts);
 | 
			
		||||
						if (ev.args.TryGetArg(HistoryEventArgsNames.Doer, out Pawn pawn))
 | 
			
		||||
                        {
 | 
			
		||||
							AdjustRecord(pawn);
 | 
			
		||||
                        }
 | 
			
		||||
						//if (ev.args.TryGetArg(HistoryEventArgsNames.Doer, out Pawn pawn))
 | 
			
		||||
                        //{
 | 
			
		||||
						//	AdjustRecord(pawn);
 | 
			
		||||
                        //}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				else if (exclusive)
 | 
			
		||||
				{
 | 
			
		||||
					TookThought(ev, precept, canApplySelfTookThoughts);
 | 
			
		||||
					if (ev.args.TryGetArg(HistoryEventArgsNames.Doer, out Pawn pawn))
 | 
			
		||||
					{
 | 
			
		||||
						AdjustRecord(pawn);
 | 
			
		||||
					}
 | 
			
		||||
					//if (ev.args.TryGetArg(HistoryEventArgsNames.Doer, out Pawn pawn))
 | 
			
		||||
					//{
 | 
			
		||||
					//	AdjustRecord(pawn);
 | 
			
		||||
					//}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
				TookThought(ev, precept, canApplySelfTookThoughts);
 | 
			
		||||
				if (ev.args.TryGetArg(HistoryEventArgsNames.Doer, out Pawn pawn))
 | 
			
		||||
				{
 | 
			
		||||
					AdjustRecord(pawn);
 | 
			
		||||
				}
 | 
			
		||||
				//if (ev.args.TryGetArg(HistoryEventArgsNames.Doer, out Pawn pawn))
 | 
			
		||||
				//{
 | 
			
		||||
				//	AdjustRecord(pawn);
 | 
			
		||||
				//}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -99,13 +104,13 @@ namespace RJWSexperience.Ideology
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		protected void AdjustRecord(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
			if (recordDef != null)
 | 
			
		||||
            {
 | 
			
		||||
				pawn.records.AddTo(recordDef, recordoffset ?? 1f);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
		//protected void AdjustRecord(Pawn pawn)
 | 
			
		||||
        //{
 | 
			
		||||
		//	if (recordDef != null)
 | 
			
		||||
        //    {
 | 
			
		||||
		//		pawn.records.AddTo(recordDef, recordoffset ?? 1f);
 | 
			
		||||
        //    }
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience.Ideology
 | 
			
		||||
{
 | 
			
		||||
    public class PreceptDef_RequirementExtended : PreceptDef
 | 
			
		||||
    {
 | 
			
		||||
        public List<MemeDef> requiredAllMemes = new List<MemeDef>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -59,8 +59,8 @@ namespace RJWSexperience.Ideology
 | 
			
		|||
 | 
			
		||||
        public static float BestialityByPrecept(Ideo ideo)
 | 
			
		||||
        {
 | 
			
		||||
            if (ideo.HasPrecept(VariousDefOf.Bestiality_Honorable)) return 0.3f;
 | 
			
		||||
            else if (ideo.HasPrecept(VariousDefOf.Bestiality_OnlyVenerated)) return 0.6f;
 | 
			
		||||
            if (ideo.HasPrecept(VariousDefOf.Bestiality_Honorable)) return 0.5f;
 | 
			
		||||
            else if (ideo.HasPrecept(VariousDefOf.Bestiality_OnlyVenerated)) return 0.65f;
 | 
			
		||||
            else if (ideo.HasPrecept(VariousDefOf.Bestiality_Acceptable)) return 0.75f;
 | 
			
		||||
            else if (ideo.HasPrecept(VariousDefOf.Bestiality_Disapproved)) return 1.0f;
 | 
			
		||||
            else return 5f;
 | 
			
		||||
| 
						 | 
				
			
			@ -78,13 +78,30 @@ namespace RJWSexperience.Ideology
 | 
			
		|||
 | 
			
		||||
        public static float RapeByPrecept(Ideo ideo)
 | 
			
		||||
        {
 | 
			
		||||
            if (ideo.HasPrecept(VariousDefOf.Rape_Honorable)) return 0.25f;
 | 
			
		||||
            else if (ideo.HasPrecept(VariousDefOf.Rape_Acceptable)) return 0.5f;
 | 
			
		||||
            if (ideo.HasPrecept(VariousDefOf.Rape_Honorable)) return 0.5f;
 | 
			
		||||
            else if (ideo.HasPrecept(VariousDefOf.Rape_Acceptable)) return 0.75f;
 | 
			
		||||
            else if (ideo.HasPrecept(VariousDefOf.Rape_Disapproved)) return 1.0f;
 | 
			
		||||
            else return 3f;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(ThinkNode_ChancePerHour_Necro), "MtbHours")]
 | 
			
		||||
    public static class RJW_Patch_ThinkNode_ChancePerHour_Necro
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(Pawn pawn, ref float __result)
 | 
			
		||||
        {
 | 
			
		||||
            Ideo ideo = pawn.Ideo;
 | 
			
		||||
            if (ideo != null) __result *= NecroByPrecept(ideo); // ideo is null if don't have dlc
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static float NecroByPrecept(Ideo ideo)
 | 
			
		||||
        {
 | 
			
		||||
            if (ideo.HasPrecept(VariousDefOf.Necrophilia_Approved)) return 0.5f;
 | 
			
		||||
            else if (ideo.HasPrecept(VariousDefOf.Necrophilia_Acceptable)) return 0.75f;
 | 
			
		||||
            else if (ideo.HasPrecept(VariousDefOf.Necrophilia_Disapproved)) return 1.0f;
 | 
			
		||||
            else return 8f;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(xxx), "is_rapist")]
 | 
			
		||||
    public static class RJW_Patch_is_rapist
 | 
			
		||||
| 
						 | 
				
			
			@ -371,6 +388,19 @@ namespace RJWSexperience.Ideology
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(PawnDesignations_Comfort), "UpdateCanDesignateComfort")]
 | 
			
		||||
    public static class RJW_PatchUpdateCanDesignateComfort
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(Pawn pawn, ref bool __result)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.IsSubmissive())
 | 
			
		||||
            {
 | 
			
		||||
                SaveStorage.DataStore.GetPawnData(pawn).CanDesignateComfort = true;
 | 
			
		||||
                __result = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(Hediff_BasePregnancy), "PostBirth")]
 | 
			
		||||
    public static class RJW_Patch_PostBirth
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,5 +55,36 @@ namespace RJWSexperience.Ideology
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(IdeoFoundation), "CanAdd")]
 | 
			
		||||
    public static class Rimworld_Patch_IdeoFoundation
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(PreceptDef precept, bool checkDuplicates, ref IdeoFoundation __instance, ref AcceptanceReport __result)
 | 
			
		||||
        {
 | 
			
		||||
            if (precept is PreceptDef_RequirementExtended)
 | 
			
		||||
            {
 | 
			
		||||
                PreceptDef_RequirementExtended def = precept as PreceptDef_RequirementExtended;
 | 
			
		||||
                if (!def.requiredAllMemes.NullOrEmpty())
 | 
			
		||||
                {
 | 
			
		||||
                    for (int i=0; i< def.requiredAllMemes.Count; i++)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (!__instance.ideo.memes.Contains(def.requiredAllMemes[i]))
 | 
			
		||||
                        {
 | 
			
		||||
                            List<string> report = new List<string>();
 | 
			
		||||
                            foreach (MemeDef meme in def.requiredAllMemes) report.Add(meme.LabelCap);
 | 
			
		||||
 | 
			
		||||
                            __result = new AcceptanceReport("RequiresMeme".Translate() + ": " + report.ToCommaList());
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,162 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
using Verse.AI;
 | 
			
		||||
using Verse.AI.Group;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience.Ideology
 | 
			
		||||
{
 | 
			
		||||
    public class JobGiver_GangbangConsensual : ThinkNode_JobGiver
 | 
			
		||||
    {
 | 
			
		||||
        protected override Job TryGiveJob(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.Drafted) return null;
 | 
			
		||||
            DutyDef dutyDef = null;
 | 
			
		||||
            PawnDuty duty = null;
 | 
			
		||||
            if (pawn.mindState != null)
 | 
			
		||||
            {
 | 
			
		||||
                duty = pawn.mindState.duty;
 | 
			
		||||
                dutyDef = duty.def;
 | 
			
		||||
            }
 | 
			
		||||
            else return null;
 | 
			
		||||
 | 
			
		||||
            if (dutyDef == DutyDefOf.TravelOrLeave || !xxx.can_fuck(pawn))
 | 
			
		||||
            {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Pawn target = duty.focusSecond.Pawn;
 | 
			
		||||
 | 
			
		||||
            if (!pawn.CanReach(target, PathEndMode.ClosestTouch, Danger.None)) return null;
 | 
			
		||||
 | 
			
		||||
            return JobMaker.MakeJob(VariousDefOf.Gangbang, target);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	public class JobDriver_Gangbang : JobDriver_SexBaseInitiator
 | 
			
		||||
	{
 | 
			
		||||
		public override bool TryMakePreToilReservations(bool errorOnFailed)
 | 
			
		||||
		{
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		protected override IEnumerable<Toil> MakeNewToils()
 | 
			
		||||
		{
 | 
			
		||||
			//ModLog.Message("" + this.GetType().ToString() + "::MakeNewToils() called");
 | 
			
		||||
			setup_ticks();
 | 
			
		||||
 | 
			
		||||
			this.FailOnDespawnedNullOrForbidden(iTarget);
 | 
			
		||||
			this.FailOn(() => Partner == null);
 | 
			
		||||
			this.FailOn(() => pawn.Drafted);
 | 
			
		||||
			this.FailOn(() => Partner.Drafted);
 | 
			
		||||
			yield return Toils_Goto.GotoThing(iTarget, PathEndMode.OnCell);
 | 
			
		||||
 | 
			
		||||
			Toil StartPartnerJob = new Toil();
 | 
			
		||||
			StartPartnerJob.defaultCompleteMode = ToilCompleteMode.Instant;
 | 
			
		||||
			StartPartnerJob.socialMode = RandomSocialMode.Off;
 | 
			
		||||
			StartPartnerJob.initAction = delegate
 | 
			
		||||
			{
 | 
			
		||||
 | 
			
		||||
				var dri = Partner.jobs.curDriver as JobDriver_SexBaseRecieverRaped;
 | 
			
		||||
				if (dri == null)
 | 
			
		||||
                {
 | 
			
		||||
					Job gettin_loved = JobMaker.MakeJob(VariousDefOf.GettinGangbang, pawn, Bed);
 | 
			
		||||
					Partner.jobs.StartJob(gettin_loved, JobCondition.InterruptForced);
 | 
			
		||||
				}
 | 
			
		||||
			};
 | 
			
		||||
			yield return StartPartnerJob;
 | 
			
		||||
 | 
			
		||||
			Toil SexToil = new Toil();
 | 
			
		||||
			SexToil.defaultCompleteMode = ToilCompleteMode.Never;
 | 
			
		||||
			SexToil.defaultDuration = duration;
 | 
			
		||||
			SexToil.handlingFacing = true;
 | 
			
		||||
			SexToil.FailOn(() => Partner.CurJob.def != VariousDefOf.GettinGangbang);
 | 
			
		||||
			SexToil.initAction = delegate
 | 
			
		||||
			{
 | 
			
		||||
				Start();
 | 
			
		||||
				Sexprops.usedCondom = CondomUtility.TryUseCondom(pawn) || CondomUtility.TryUseCondom(Partner);
 | 
			
		||||
			};
 | 
			
		||||
			SexToil.AddPreTickAction(delegate
 | 
			
		||||
			{
 | 
			
		||||
				SexTick(pawn, Partner);
 | 
			
		||||
				SexUtility.reduce_rest(Partner, 1);
 | 
			
		||||
				SexUtility.reduce_rest(pawn, 2);
 | 
			
		||||
				if (ticks_left <= 0)
 | 
			
		||||
					ReadyForNextToil();
 | 
			
		||||
			});
 | 
			
		||||
			SexToil.AddFinishAction(delegate
 | 
			
		||||
			{
 | 
			
		||||
				End();
 | 
			
		||||
			});
 | 
			
		||||
			yield return SexToil;
 | 
			
		||||
 | 
			
		||||
			yield return new Toil
 | 
			
		||||
			{
 | 
			
		||||
				initAction = delegate
 | 
			
		||||
				{
 | 
			
		||||
					// Trying to add some interactions and social logs
 | 
			
		||||
					SexUtility.ProcessSex(Sexprops);
 | 
			
		||||
				},
 | 
			
		||||
				defaultCompleteMode = ToilCompleteMode.Instant
 | 
			
		||||
			};
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public class JobDriver_GangbangReceiver : JobDriver_SexBaseRecieverLoved
 | 
			
		||||
    {
 | 
			
		||||
		protected override IEnumerable<Toil> MakeNewToils()
 | 
			
		||||
		{
 | 
			
		||||
			setup_ticks();
 | 
			
		||||
			parteners.Add(Partner);// add job starter, so this wont fail, before Initiator starts his job
 | 
			
		||||
 | 
			
		||||
			Toil get_banged = new Toil();
 | 
			
		||||
			get_banged.defaultCompleteMode = ToilCompleteMode.Never;
 | 
			
		||||
			get_banged.handlingFacing = true;
 | 
			
		||||
			get_banged.initAction = delegate
 | 
			
		||||
			{
 | 
			
		||||
				pawn.pather.StopDead();
 | 
			
		||||
				pawn.jobs.curDriver.asleep = false;
 | 
			
		||||
			};
 | 
			
		||||
			get_banged.tickAction = delegate
 | 
			
		||||
			{
 | 
			
		||||
				if ((parteners.Count > 0) && (pawn.IsHashIntervalTick(ticks_between_hearts / parteners.Count)))
 | 
			
		||||
					if (pawn.IsHashIntervalTick(ticks_between_hearts))
 | 
			
		||||
							ThrowMetaIconF(pawn.Position, pawn.Map, FleckDefOf.Heart);
 | 
			
		||||
			};
 | 
			
		||||
			get_banged.AddEndCondition(new Func<JobCondition>(() =>
 | 
			
		||||
			{
 | 
			
		||||
				if (parteners.Count <= 0)
 | 
			
		||||
				{
 | 
			
		||||
					return JobCondition.Succeeded;
 | 
			
		||||
				}
 | 
			
		||||
				return JobCondition.Ongoing;
 | 
			
		||||
			}));
 | 
			
		||||
			get_banged.AddFinishAction(delegate
 | 
			
		||||
			{
 | 
			
		||||
				if (xxx.is_human(pawn))
 | 
			
		||||
					pawn.Drawer.renderer.graphics.ResolveApparelGraphics();
 | 
			
		||||
				GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(pawn);
 | 
			
		||||
 | 
			
		||||
				if (Bed != null && pawn.Downed)
 | 
			
		||||
				{
 | 
			
		||||
					Job tobed = JobMaker.MakeJob(JobDefOf.Rescue, pawn, Bed);
 | 
			
		||||
					tobed.count = 1;
 | 
			
		||||
					Partner.jobs.jobQueue.EnqueueFirst(tobed);
 | 
			
		||||
					//Log.Message(xxx.get_pawnname(Initiator) + ": job tobed:" + tobed);
 | 
			
		||||
				}
 | 
			
		||||
				else if (pawn.HostileTo(Partner))
 | 
			
		||||
					pawn.health.AddHediff(xxx.submitting);
 | 
			
		||||
			});
 | 
			
		||||
			get_banged.socialMode = RandomSocialMode.Off;
 | 
			
		||||
			yield return get_banged;
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ namespace RJWSexperience.Ideology
 | 
			
		|||
            }
 | 
			
		||||
            else return null;
 | 
			
		||||
 | 
			
		||||
			if (dutyDef == DutyDefOf.TravelOrLeave || !xxx.can_rape(pawn, true))
 | 
			
		||||
			if (dutyDef == DutyDefOf.TravelOrLeave || !xxx.can_fuck(pawn))
 | 
			
		||||
            {
 | 
			
		||||
                return null;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -57,7 +57,6 @@ namespace RJWSexperience.Ideology
 | 
			
		|||
			var PartnerJob = xxx.gettin_raped;
 | 
			
		||||
 | 
			
		||||
			this.FailOnDespawnedNullOrForbidden(iTarget);
 | 
			
		||||
			//this.FailOn(() => (!Partner.health.capacities.CanBeAwake) || (!comfort_prisoners.is_designated(Partner)));//this is wrong
 | 
			
		||||
			this.FailOn(() => Partner == null);
 | 
			
		||||
			this.FailOn(() => pawn.Drafted);
 | 
			
		||||
			this.FailOn(() => Partner.Drafted);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,11 +14,11 @@ namespace RJWSexperience.Ideology
 | 
			
		|||
    {
 | 
			
		||||
		public LordJob_Ritual_Gangbang() { }
 | 
			
		||||
 | 
			
		||||
		public LordJob_Ritual_Gangbang(TargetInfo selectedTarget, Precept_Ritual ritual, RitualObligation obligation, List<RitualStage> allStages, RitualRoleAssignments assignments, Pawn organizer = null) : base(selectedTarget, ritual, obligation, allStages, assignments, organizer)
 | 
			
		||||
		public LordJob_Ritual_Gangbang(string targetID ,TargetInfo selectedTarget, Precept_Ritual ritual, RitualObligation obligation, List<RitualStage> allStages, RitualRoleAssignments assignments, Pawn organizer = null) : base(selectedTarget, ritual, obligation, allStages, assignments, organizer)
 | 
			
		||||
		{ 
 | 
			
		||||
			foreach (RitualRole ritualRole in assignments.AllRolesForReading)
 | 
			
		||||
			{
 | 
			
		||||
				if (ritualRole != null && ritualRole.id.Contains("victim"))
 | 
			
		||||
				if (ritualRole != null && ritualRole.id.Contains(targetID))
 | 
			
		||||
				{
 | 
			
		||||
					Pawn item = assignments.FirstAssignedPawn(ritualRole);
 | 
			
		||||
					pawnsDeathIgnored.Add(item);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,15 +23,25 @@ namespace RJWSexperience.Ideology
 | 
			
		|||
			{
 | 
			
		||||
				WorkGiver_Warden_TakeToBed.TryTakePrisonerToBed(pawn, warden);
 | 
			
		||||
				pawn.guest.WaitInsteadOfEscapingFor(1250);
 | 
			
		||||
				
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        protected override LordJob CreateLordJob(TargetInfo target, Pawn organizer, Precept_Ritual ritual, RitualObligation obligation, RitualRoleAssignments assignments)
 | 
			
		||||
        {
 | 
			
		||||
            return new LordJob_Ritual_Gangbang(target, ritual, obligation, def.stages, assignments, organizer);
 | 
			
		||||
            return new LordJob_Ritual_Gangbang("victim", target, ritual, obligation, def.stages, assignments, organizer);
 | 
			
		||||
		}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	public class RitualBehaviorWorker_Gangbang_Consensual : RitualBehaviorWorker
 | 
			
		||||
	{
 | 
			
		||||
		public RitualBehaviorWorker_Gangbang_Consensual() { }
 | 
			
		||||
 | 
			
		||||
		public RitualBehaviorWorker_Gangbang_Consensual(RitualBehaviorDef def) : base(def) { }
 | 
			
		||||
 | 
			
		||||
		protected override LordJob CreateLordJob(TargetInfo target, Pawn organizer, Precept_Ritual ritual, RitualObligation obligation, RitualRoleAssignments assignments)
 | 
			
		||||
		{
 | 
			
		||||
			return new LordJob_Ritual_Gangbang("initiator", target, ritual, obligation, def.stages, assignments, organizer);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public class RitualStage_InteractWithVictim : RitualStage
 | 
			
		||||
| 
						 | 
				
			
			@ -49,5 +59,11 @@ namespace RJWSexperience.Ideology
 | 
			
		|||
			return ritual.assignments.AssignedPawns("victim").FirstOrDefault();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public class RitualStage_InteractWithInitiator : RitualStage
 | 
			
		||||
	{
 | 
			
		||||
		public override TargetInfo GetSecondFocus(LordJob_Ritual ritual)
 | 
			
		||||
		{
 | 
			
		||||
			return ritual.assignments.AssignedPawns("initiator").FirstOrDefault();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										75
									
								
								RJWSexperience/IdeologyAddon/Ideology/Sexperience_Patch.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,75 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using HarmonyLib;
 | 
			
		||||
using rjw;
 | 
			
		||||
using RJWSexperience;
 | 
			
		||||
using Verse;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience.Ideology
 | 
			
		||||
{
 | 
			
		||||
    [HarmonyPatch(typeof(RJWUtility), "ThrowVirginHIstoryEvent")]
 | 
			
		||||
    public static class Sexperience_Patch_ThrowVirginHIstoryEvent
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(Pawn pawn, Pawn partner, SexProps props, int degree)
 | 
			
		||||
        {
 | 
			
		||||
            string tag = "";
 | 
			
		||||
            if (props.isRape)
 | 
			
		||||
            {
 | 
			
		||||
                if (pawn == props.pawn && props.isRapist) tag += HETag.Rape;
 | 
			
		||||
                else tag += HETag.BeenRaped;
 | 
			
		||||
            }
 | 
			
		||||
            if (!pawn.relations.DirectRelationExists(PawnRelationDefOf.Spouse, partner))
 | 
			
		||||
            {
 | 
			
		||||
                tag += HETag.NotSpouse;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            
 | 
			
		||||
            if (pawn.gender == Gender.Male)
 | 
			
		||||
            {
 | 
			
		||||
                if (degree > 1) Find.HistoryEventsManager.RecordEvent(VariousDefOf.Virgin_TakenM.TaggedEvent(pawn, tag + HETag.Gender(pawn), partner));
 | 
			
		||||
                Find.HistoryEventsManager.RecordEvent(VariousDefOf.Virgin_TookM.TaggedEvent(partner, tag + HETag.Gender(pawn), pawn));
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (degree > 1) Find.HistoryEventsManager.RecordEvent(VariousDefOf.Virgin_TakenF.TaggedEvent(pawn, tag + HETag.Gender(pawn), partner));
 | 
			
		||||
                Find.HistoryEventsManager.RecordEvent(VariousDefOf.Virgin_TookF.TaggedEvent(partner, tag + HETag.Gender(pawn), pawn));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(Utility), "IsIncest")]
 | 
			
		||||
    public static class Sexperience_Patch_IsIncest
 | 
			
		||||
    {
 | 
			
		||||
        public static bool Prefix(Pawn pawn, Pawn otherpawn, ref bool __result)
 | 
			
		||||
        {
 | 
			
		||||
            __result = IsIncest(pawn, otherpawn);
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static bool IsIncest(Pawn pawn, Pawn partner)
 | 
			
		||||
        {
 | 
			
		||||
            IEnumerable<PawnRelationDef> relations = pawn.GetRelations(partner);
 | 
			
		||||
            Ideo ideo = pawn.Ideo;
 | 
			
		||||
            bool wide = false;
 | 
			
		||||
            if (ideo != null) wide = ideo.HasPrecept(VariousDefOf.Incestuos_Disapproved_CloseOnly);
 | 
			
		||||
            if (!relations.EnumerableNullOrEmpty()) foreach (PawnRelationDef relation in relations)
 | 
			
		||||
                {
 | 
			
		||||
                    if (wide)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (relation.incestOpinionOffset < 0) return true;
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (relation.familyByBloodRelation) return true;
 | 
			
		||||
                }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -10,25 +10,9 @@ using UnityEngine;
 | 
			
		|||
 | 
			
		||||
namespace RJWSexperience.Ideology
 | 
			
		||||
{
 | 
			
		||||
    public static class Utility
 | 
			
		||||
    public static class IdeoUtility
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        public static bool IsIncest(this Pawn pawn, Pawn partner)
 | 
			
		||||
        {
 | 
			
		||||
            IEnumerable<PawnRelationDef> relations = pawn.GetRelations(partner);
 | 
			
		||||
            Ideo ideo = pawn.Ideo;
 | 
			
		||||
            bool wide = false;
 | 
			
		||||
            if (ideo != null) wide = ideo.HasPrecept(VariousDefOf.Incestuos_Disapproved_CloseOnly);
 | 
			
		||||
            if (!relations.EnumerableNullOrEmpty()) foreach (PawnRelationDef relation in relations)
 | 
			
		||||
                {
 | 
			
		||||
                    if (wide)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (relation.incestOpinionOffset < 0) return true;
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (relation.familyByBloodRelation) return true;
 | 
			
		||||
                }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool IsSubmissive(this Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -95,9 +95,12 @@
 | 
			
		|||
  <ItemGroup>
 | 
			
		||||
    <Compile Include="Ideology\GoodwillSituationWorker_MemeCompatibility.cs" />
 | 
			
		||||
    <Compile Include="Harmony.cs" />
 | 
			
		||||
    <Compile Include="Ideology\PreceptDef_RequirementExtended.cs" />
 | 
			
		||||
    <Compile Include="Ideology\Rituals\JobGiver_GangbangConsensual.cs" />
 | 
			
		||||
    <Compile Include="Ideology\Rituals\LordJob_Rituals.cs" />
 | 
			
		||||
    <Compile Include="Ideology\RJW_Patch_Ideo.cs" />
 | 
			
		||||
    <Compile Include="Ideology\PreceptComp_SelftTookThoughtExtended.cs" />
 | 
			
		||||
    <Compile Include="Ideology\Sexperience_Patch.cs" />
 | 
			
		||||
    <Compile Include="Properties\AssemblyInfo.cs" />
 | 
			
		||||
    <Compile Include="Ideology\Rimworld_Patch.cs" />
 | 
			
		||||
    <Compile Include="Ideology\Rituals\JobGiver_DrugOrgy.cs" />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,8 @@ namespace RJWSexperience.Ideology
 | 
			
		|||
    public static class VariousDefOf
 | 
			
		||||
    {
 | 
			
		||||
        public static readonly JobDef RapeVictim = DefDatabase<JobDef>.GetNamed("RapeVictim");
 | 
			
		||||
        public static readonly JobDef Gangbang = DefDatabase<JobDef>.GetNamed("Gangbang");
 | 
			
		||||
        public static readonly JobDef GettinGangbang = DefDatabase<JobDef>.GetNamed("GettinGangbang");
 | 
			
		||||
        public static readonly JobDef DrugSex = DefDatabase<JobDef>.GetNamed("DrugSex");
 | 
			
		||||
        public static readonly JobDef GettinDrugSex = DefDatabase<JobDef>.GetNamed("GettinDrugSex");
 | 
			
		||||
        public static readonly JobDef DrugMasturbate = DefDatabase<JobDef>.GetNamed("DrugMasturbate");
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +36,10 @@ namespace RJWSexperience.Ideology
 | 
			
		|||
        [MayRequireIdeology] public static readonly HistoryEventDef PromiscuousSex = DefDatabase<HistoryEventDef>.GetNamed("PromiscuousSex");
 | 
			
		||||
        [MayRequireIdeology] public static readonly HistoryEventDef Incestuos_Marriage = DefDatabase<HistoryEventDef>.GetNamed("Incestuos_Marriage");
 | 
			
		||||
        [MayRequireIdeology] public static readonly HistoryEventDef SexWithCorpse = DefDatabase<HistoryEventDef>.GetNamed("SexWithCorpse");
 | 
			
		||||
        [MayRequireIdeology] public static readonly HistoryEventDef Virgin_TakenF = DefDatabase<HistoryEventDef>.GetNamed("Virgin_TakenF");
 | 
			
		||||
        [MayRequireIdeology] public static readonly HistoryEventDef Virgin_TakenM = DefDatabase<HistoryEventDef>.GetNamed("Virgin_TakenM");
 | 
			
		||||
        [MayRequireIdeology] public static readonly HistoryEventDef Virgin_TookF = DefDatabase<HistoryEventDef>.GetNamed("Virgin_TookF");
 | 
			
		||||
        [MayRequireIdeology] public static readonly HistoryEventDef Virgin_TookM = DefDatabase<HistoryEventDef>.GetNamed("Virgin_TookM");
 | 
			
		||||
        [MayRequireIdeology] public static readonly PreceptDef Bestiality_Abhorrent = DefDatabase<PreceptDef>.GetNamed("Bestiality_Abhorrent");
 | 
			
		||||
        [MayRequireIdeology] public static readonly PreceptDef Bestiality_Horrible = DefDatabase<PreceptDef>.GetNamed("Bestiality_Horrible");
 | 
			
		||||
        [MayRequireIdeology] public static readonly PreceptDef Bestiality_Disapproved = DefDatabase<PreceptDef>.GetNamed("Bestiality_Disapproved");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ using System.Text;
 | 
			
		|||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +44,11 @@ namespace RJWSexperience
 | 
			
		|||
            int num = (int)storedcum;
 | 
			
		||||
 | 
			
		||||
            cum.stackCount = num;
 | 
			
		||||
            if (cum.stackCount > 0) GenPlace.TryPlaceThing(cum, PositionHeld, Map, ThingPlaceMode.Direct, out Thing res);
 | 
			
		||||
            if (cum.stackCount > 0)
 | 
			
		||||
            {
 | 
			
		||||
                if (!GenPlace.TryPlaceThing(cum, PositionHeld, Map, ThingPlaceMode.Direct, out Thing res))
 | 
			
		||||
                    FilthMaker.TryMakeFilth(PositionHeld, Map, VariousDefOf.FilthCum, num);
 | 
			
		||||
            }
 | 
			
		||||
            storedcum -= num;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -36,6 +36,8 @@ namespace RJWSexperience
 | 
			
		|||
        public static float MinSexablePercent = MinSexablePercentDefault;
 | 
			
		||||
        public static float VirginRatio = VirginRatioDefault;
 | 
			
		||||
 | 
			
		||||
        public static bool SelectionLocked = false;
 | 
			
		||||
 | 
			
		||||
        public static void ResettoDefault()
 | 
			
		||||
        {
 | 
			
		||||
            MaxLustDeviation = MaxInitialLustDefault;
 | 
			
		||||
| 
						 | 
				
			
			@ -62,6 +64,7 @@ namespace RJWSexperience
 | 
			
		|||
            Scribe_Values.Look(ref LustLimit, "LustLimit", LustLimit, true);
 | 
			
		||||
            Scribe_Values.Look(ref MinSexablePercent, "MinSexablePercent", MinSexablePercent, true);
 | 
			
		||||
            Scribe_Values.Look(ref VirginRatio, "VirginRatio", VirginRatio, true);
 | 
			
		||||
            Scribe_Values.Look(ref SelectionLocked, "SelectionLocked", SelectionLocked, true);
 | 
			
		||||
            base.ExposeData();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,25 @@ namespace RJWSexperience
 | 
			
		|||
{
 | 
			
		||||
    public static class DebugToolsSexperience
 | 
			
		||||
    {
 | 
			
		||||
        [DebugAction("RJW Sexperience", "Reset pawn's record", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.PlayingOnMap)]
 | 
			
		||||
        private static void ResetRecords(Pawn p)
 | 
			
		||||
        {
 | 
			
		||||
            Trait virgin = p.story?.traits?.GetTrait(VariousDefOf.Virgin);
 | 
			
		||||
            if (virgin != null) p.story.traits.RemoveTrait(virgin);
 | 
			
		||||
            p.ResetRecord(true);
 | 
			
		||||
            p.ResetRecord(false);
 | 
			
		||||
            MoteMaker.ThrowText(p.TrueCenter(), p.Map, "Records resetted!");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [DebugAction("RJW Sexperience", "Reset pawn's record(virgin)", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.PlayingOnMap)]
 | 
			
		||||
        private static void ResetRecordsZero(Pawn p)
 | 
			
		||||
        {
 | 
			
		||||
            p.ResetRecord(true);
 | 
			
		||||
            p.AddVirginTrait();
 | 
			
		||||
            MoteMaker.ThrowText(p.TrueCenter(), p.Map, "Records resetted!\nVirginified!");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        [DebugAction("RJW Sexperience", "Reset lust", false, false, actionType = DebugActionType.ToolMapForPawns, allowedGameStates = AllowedGameStates.PlayingOnMap)]
 | 
			
		||||
        private static void ResetLust(Pawn p)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										23
									
								
								RJWSexperience/RJWSexperience/IngestionOutcomeDoers.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using rjw;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
    public class CumOutcomeDoers : IngestionOutcomeDoer
 | 
			
		||||
    {
 | 
			
		||||
        public float unitAmount = 1.0f;
 | 
			
		||||
 | 
			
		||||
        protected override void DoIngestionOutcomeSpecial(Pawn pawn, Thing ingested)
 | 
			
		||||
        {
 | 
			
		||||
            pawn.AteCum(ingested.stackCount * unitAmount);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										108
									
								
								RJWSexperience/RJWSexperience/JobDrivers.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,108 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
using Verse.AI;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
    public class JobGiver_UseBucket : ThinkNode_JobGiver
 | 
			
		||||
    {
 | 
			
		||||
        protected override Job TryGiveJob(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class JobDriver_CleanSelfWithBucket : JobDriver
 | 
			
		||||
    {
 | 
			
		||||
        const int UNITTIME = 240;//ticks - 120 = 2 real seconds, 3 in-game minutes
 | 
			
		||||
        protected float progress = 0;
 | 
			
		||||
        protected float severitycache = 1;
 | 
			
		||||
        protected Hediff hediffcache;
 | 
			
		||||
        protected float CleaningTime
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return severitycache * UNITTIME;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        protected Building_CumBucket Bucket => TargetB.Thing as Building_CumBucket;
 | 
			
		||||
 | 
			
		||||
        public override bool TryMakePreToilReservations(bool errorOnFailed)
 | 
			
		||||
        {
 | 
			
		||||
            return pawn.Reserve(pawn, job, 1, -1, null, errorOnFailed);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override IEnumerable<Toil> MakeNewToils()
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            this.FailOn(delegate
 | 
			
		||||
            {
 | 
			
		||||
                List<Hediff> hediffs = pawn.health.hediffSet.hediffs;
 | 
			
		||||
                return !hediffs.Exists(x => x.def == RJW_SemenoOverlayHediffDefOf.Hediff_Bukkake);
 | 
			
		||||
            });
 | 
			
		||||
            yield return Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch);
 | 
			
		||||
            Toil cleaning = new Toil();
 | 
			
		||||
            cleaning.initAction = CleaningInit;
 | 
			
		||||
            cleaning.tickAction = CleaningTick;
 | 
			
		||||
            cleaning.AddFinishAction(Finish);
 | 
			
		||||
            cleaning.defaultCompleteMode = ToilCompleteMode.Never;
 | 
			
		||||
            cleaning.WithProgressBar(TargetIndex.A, () => progress/CleaningTime);
 | 
			
		||||
 | 
			
		||||
            yield return cleaning;
 | 
			
		||||
            yield break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void CleaningInit()
 | 
			
		||||
        {
 | 
			
		||||
            hediffcache = pawn.health.hediffSet.hediffs.Find(x => (x.def == RJW_SemenoOverlayHediffDefOf.Hediff_Semen || x.def == RJW_SemenoOverlayHediffDefOf.Hediff_InsectSpunk));
 | 
			
		||||
            if (hediffcache == null)
 | 
			
		||||
            {
 | 
			
		||||
                pawn.jobs.EndCurrentJob(JobCondition.Succeeded);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                progress = 0;
 | 
			
		||||
                severitycache = hediffcache.Severity;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void CleaningTick()
 | 
			
		||||
        {
 | 
			
		||||
            progress += 1;
 | 
			
		||||
            if (progress > CleaningTime)
 | 
			
		||||
            {
 | 
			
		||||
                Cleaned();
 | 
			
		||||
            } 
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void Cleaned()
 | 
			
		||||
        {
 | 
			
		||||
            if (hediffcache != null)
 | 
			
		||||
            {
 | 
			
		||||
                float cumamount = hediffcache.Severity * 10;
 | 
			
		||||
                hediffcache.Severity = 0;
 | 
			
		||||
                Bucket.AddCum(cumamount);
 | 
			
		||||
            }
 | 
			
		||||
            CleaningInit();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void Finish()
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.CurJobDef == JobDefOf.Wait_MaintainPosture)
 | 
			
		||||
            {
 | 
			
		||||
                pawn.jobs.EndCurrentJob(JobCondition.InterruptForced);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -5,7 +5,8 @@ using System.Text;
 | 
			
		|||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
 | 
			
		||||
using rjw;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +15,9 @@ namespace RJWSexperience
 | 
			
		|||
        public static string LustStatFactor(string value) => "LustStatFactor".Translate(value);
 | 
			
		||||
        public static string SlaveStatFactor(string value) => "SlaveStatFactor".Translate(value);
 | 
			
		||||
        public static string MemeStatFactor(string value) => "MemeStatFactor".Translate(value);
 | 
			
		||||
        public static string RS_LostVirgin(string pawn, string partner) => "RS_LostVirgin".Translate(pawn,partner);
 | 
			
		||||
        public static string RS_LostVirgin(string pawn, string partner) => "RS_LostVirgin".Translate(pawn.Colorize(Color.yellow),partner.Colorize(Color.yellow));
 | 
			
		||||
        public static string RS_Sex_Info(string sextype, string sexcount) => "RS_Sex_Info".Translate(sextype, sexcount);
 | 
			
		||||
        public static string RS_SAT_AVG(string avgsat) => "RS_SAT_AVG".Translate(avgsat);
 | 
			
		||||
 | 
			
		||||
        public static readonly string Mod_Title = "RS_Mod_Title".Translate();
 | 
			
		||||
        public static readonly string SlaveStatFactorDefault = "SlaveStatFactorDefault".Translate();
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +27,50 @@ namespace RJWSexperience
 | 
			
		|||
        public static readonly string RSNotAnimal = "RSNotAnimal".Translate();
 | 
			
		||||
        public static readonly string RSShouldCanFuck = "RSShouldCanFuck".Translate();
 | 
			
		||||
        public static readonly string RSTotalGatheredCum = "RSTotalGatheredCum".Translate();
 | 
			
		||||
        public static readonly string RS_FloatMenu_CleanSelf = "RS_FloatMenu_CleanSelf".Translate();
 | 
			
		||||
        public static readonly string RS_Best_Sextype = "RS_Best_Sextype".Translate();
 | 
			
		||||
        public static readonly string RS_Recent_Sextype = "RS_Recent_Sextype".Translate();
 | 
			
		||||
        public static readonly string RS_Sex_Partners = "RS_Sex_Partners".Translate();
 | 
			
		||||
        public static readonly string RS_Cum_Swallowed = "RS_Cum_Swallowed".Translate();
 | 
			
		||||
        public static readonly string RS_Selected_Partner = "RS_Selected_Partner".Translate();
 | 
			
		||||
        public static readonly string RS_Sex_Count = "RS_Sex_Count".Translate();
 | 
			
		||||
        public static readonly string RS_Orgasms = "RS_Orgasms".Translate();
 | 
			
		||||
        public static readonly string RS_Recent_Sex_Partner = "RS_Recent_Sex_Partner".Translate();
 | 
			
		||||
        public static readonly string RS_First_Sex_Partner = "RS_First_Sex_Partner".Translate();
 | 
			
		||||
        public static readonly string RS_Most_Sex_Partner = "RS_Most_Sex_Partner".Translate();
 | 
			
		||||
        public static readonly string RS_Best_Sex_Partner = "RS_Best_Sex_Partner".Translate();
 | 
			
		||||
        public static readonly string RS_VirginsTaken = "RS_VirginsTaken".Translate();
 | 
			
		||||
        public static readonly string RS_TotalSexHad = "RS_TotalSexHad".Translate();
 | 
			
		||||
        public static readonly string RS_Recent_Sex_Partner_ToolTip = "RS_Recent_Sex_Partner_ToolTip".Translate();
 | 
			
		||||
        public static readonly string RS_First_Sex_Partner_ToolTip = "RS_First_Sex_Partner_ToolTip".Translate();
 | 
			
		||||
        public static readonly string RS_Most_Sex_Partner_ToolTip = "RS_Most_Sex_Partner_ToolTip".Translate();
 | 
			
		||||
        public static readonly string RS_Best_Sex_Partner_ToolTip = "RS_Best_Sex_Partner_ToolTip".Translate();
 | 
			
		||||
        public static readonly string RS_VirginsTaken_ToolTip = "RS_VirginsTaken_ToolTip".Translate();
 | 
			
		||||
        public static readonly string RS_TotalSexHad_ToolTip = "RS_TotalSexHad_ToolTip".Translate();
 | 
			
		||||
        public static readonly string RS_Raped = "RS_Raped".Translate();
 | 
			
		||||
        public static readonly string RS_RapedMe = "RS_RapedMe".Translate();
 | 
			
		||||
        public static readonly string RS_Sex_History = "RS_Sex_History".Translate();
 | 
			
		||||
        public static readonly string RS_Statistics = "RS_Statistics".Translate();
 | 
			
		||||
        public static readonly string RS_PartnerList = "RS_PartnerList".Translate();
 | 
			
		||||
        public static readonly string RS_Sexuality = "RS_Sexuality".Translate();
 | 
			
		||||
        public static readonly string RS_BeenRaped = "RS_BeenRaped".Translate();
 | 
			
		||||
        public static readonly string RS_RapedSomeone = "RS_RapedSomeone".Translate();
 | 
			
		||||
        public static readonly string RS_PreferRace = "RS_PreferRace".Translate();
 | 
			
		||||
        public static readonly string Lust = "Lust".Translate();
 | 
			
		||||
        public static readonly string Unknown = "Unknown".Translate();
 | 
			
		||||
        public static readonly string Incest = "Incest".Translate();
 | 
			
		||||
        public static readonly string None = "None".Translate();
 | 
			
		||||
        public static readonly string RS_Bestiality = "RS_Bestiality".Translate();
 | 
			
		||||
        public static readonly string RS_Interspecies = "RS_Interspecies".Translate();
 | 
			
		||||
        public static readonly string RS_Normal = "RS_Normal".Translate();
 | 
			
		||||
        public static readonly string RS_Necrophile = "RS_Necrophile".Translate();
 | 
			
		||||
        public static readonly string RS_GatherCum = "RS_GatherCum".Translate();
 | 
			
		||||
        public static readonly string RS_SexSkill = "RS_SexSkill".Translate();
 | 
			
		||||
        public static readonly string RS_CumAddiction = "RS_CumAddiction".Translate();
 | 
			
		||||
        public static readonly string RS_CumAddiction_Tooltip = "RS_CumAddiction_Tooltip".Translate();
 | 
			
		||||
        public static readonly string RS_CumAddictiveness = "RS_CumAddictiveness".Translate();
 | 
			
		||||
        public static readonly string RS_CumAddictiveness_Tooltip = "RS_CumAddictiveness_Tooltip".Translate();
 | 
			
		||||
        public static readonly string RS_NumofTimes = "RS_NumofTimes".Translate();
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        public static readonly string Option_1_Label = "RSOption_1_Label".Translate();
 | 
			
		||||
| 
						 | 
				
			
			@ -49,5 +96,46 @@ namespace RJWSexperience
 | 
			
		|||
        public static readonly string Option_11_Label = "RSOption_11_Label".Translate();
 | 
			
		||||
        public static readonly string Option_11_Desc = "RSOption_11_Desc".Translate();
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        public static readonly string[] Sextype =
 | 
			
		||||
        {
 | 
			
		||||
            ((xxx.rjwSextype)0).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)1).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)2).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)3).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)4).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)5).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)6).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)7).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)8).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)9).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)10).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)11).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)12).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)13).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)14).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)15).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)16).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)17).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)18).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)19).ToString().Translate(),
 | 
			
		||||
            ((xxx.rjwSextype)20).ToString().Translate()
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        public static readonly string[] Sexuality =
 | 
			
		||||
        {
 | 
			
		||||
            ((Orientation)0).ToString().Translate(),
 | 
			
		||||
            ((Orientation)1).ToString().Translate(),
 | 
			
		||||
            ((Orientation)2).ToString().Translate(),
 | 
			
		||||
            ((Orientation)3).ToString().Translate(),
 | 
			
		||||
            ((Orientation)4).ToString().Translate(),
 | 
			
		||||
            ((Orientation)5).ToString().Translate(),
 | 
			
		||||
            ((Orientation)6).ToString().Translate(),
 | 
			
		||||
            ((Orientation)7).ToString().Translate(),
 | 
			
		||||
            ((Orientation)8).ToString().Translate(),
 | 
			
		||||
            ((Orientation)9).ToString().Translate(),
 | 
			
		||||
            ((Orientation)10).ToString().Translate()
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										35
									
								
								RJWSexperience/RJWSexperience/Patches/DefInjection.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
using HarmonyLib;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
    [StaticConstructorOnStartup]
 | 
			
		||||
    public static class DefInjection
 | 
			
		||||
    {
 | 
			
		||||
        static DefInjection()
 | 
			
		||||
        {
 | 
			
		||||
            InjectRaces();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static void InjectRaces()
 | 
			
		||||
        {
 | 
			
		||||
            List<ThingDef> PawnDefs = DefDatabase<ThingDef>.AllDefs.Where(x => x.race != null).ToList();
 | 
			
		||||
            InjectComp(PawnDefs);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static void InjectComp(List<ThingDef> PawnDefs)
 | 
			
		||||
        {
 | 
			
		||||
            CompProperties comp = new CompProperties(typeof(SexPartnerHistory));
 | 
			
		||||
            if (!PawnDefs.NullOrEmpty()) foreach(ThingDef def in PawnDefs)
 | 
			
		||||
            {
 | 
			
		||||
                    def.comps.Add(comp);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								RJWSexperience/RJWSexperience/Patches/GetGizmos.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
using HarmonyLib;
 | 
			
		||||
using rjw;
 | 
			
		||||
using RJWSexperience.UI;
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
    [HarmonyPatch(typeof(Pawn),"GetGizmos")]
 | 
			
		||||
    public class Pawn_GetGizmos
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(ref IEnumerable<Gizmo> __result, Pawn __instance)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            List<Gizmo> gizmoList = __result.ToList();
 | 
			
		||||
 | 
			
		||||
            AddHistoryGizmo(__instance, ref gizmoList);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            __result = gizmoList;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static void AddHistoryGizmo(Pawn pawn, ref List<Gizmo> gizmos)
 | 
			
		||||
        {
 | 
			
		||||
            SexPartnerHistory history = pawn.GetPartnerHistory();
 | 
			
		||||
            if (history != null) gizmos.Add(CreateHIstoryGizmo(pawn,history));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static Gizmo CreateHIstoryGizmo(Pawn pawn, SexPartnerHistory history)
 | 
			
		||||
        {
 | 
			
		||||
            Gizmo gizmo = new Command_Action
 | 
			
		||||
            {
 | 
			
		||||
                defaultLabel = Keyed.RS_Sex_History,
 | 
			
		||||
                icon = HistoryUtility.HistoryIcon,
 | 
			
		||||
                defaultIconColor = HistoryUtility.HistoryColor,
 | 
			
		||||
                hotKey = VariousDefOf.OpenSexStatistics,
 | 
			
		||||
                action = delegate
 | 
			
		||||
                {
 | 
			
		||||
                    SexStatusWindow.ToggleWindow(pawn, history);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            return gizmo;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										207
									
								
								RJWSexperience/RJWSexperience/Patches/RJW_Patch.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,207 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using HarmonyLib;
 | 
			
		||||
using rjw;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
using Verse.AI;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(JobDriver_Sex), "Orgasm")]
 | 
			
		||||
    public static class RJW_Patch_Orgasm
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(JobDriver_Sex __instance)
 | 
			
		||||
        {
 | 
			
		||||
            if (__instance.Sexprops.sexType != xxx.rjwSextype.Masturbation && !(__instance is JobDriver_Masturbate))
 | 
			
		||||
            {
 | 
			
		||||
                if (__instance.Sexprops.isRape)
 | 
			
		||||
                {
 | 
			
		||||
                    __instance.pawn?.skills?.Learn(VariousDefOf.SexSkill, 0.05f, true);
 | 
			
		||||
                }
 | 
			
		||||
                {   
 | 
			
		||||
                    __instance.pawn?.skills?.Learn(VariousDefOf.SexSkill, 0.35f, true);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(WhoringHelper), "WhoreAbilityAdjustmentMin")]
 | 
			
		||||
    public static class RJW_Patch_WhoreAbilityAdjustmentMin
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(Pawn whore, ref float __result)
 | 
			
		||||
        {
 | 
			
		||||
            __result *= whore.GetSexStat();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(WhoringHelper), "WhoreAbilityAdjustmentMax")]
 | 
			
		||||
    public static class RJW_Patch_WhoreAbilityAdjustmentMax
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(Pawn whore, ref float __result)
 | 
			
		||||
        {
 | 
			
		||||
            __result *= whore.GetSexStat();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(SexUtility), "SatisfyPersonal")]
 | 
			
		||||
    public static class RJW_Patch_SatisfyPersonal
 | 
			
		||||
    {
 | 
			
		||||
        private const float base_sat_per_fuck = 0.4f;
 | 
			
		||||
 | 
			
		||||
        public static void Prefix(SexProps props, ref float satisfaction)
 | 
			
		||||
        {
 | 
			
		||||
            Pawn pawn = props.pawn;
 | 
			
		||||
            Pawn partner = props.partner;
 | 
			
		||||
            satisfaction = Mathf.Max(base_sat_per_fuck, satisfaction * partner.GetSexStat());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void Postfix(SexProps props, ref float satisfaction)
 | 
			
		||||
        {
 | 
			
		||||
            Pawn pawn = props.pawn;
 | 
			
		||||
            Pawn partner = props.partner;
 | 
			
		||||
            float? lust = pawn.records?.GetValue(VariousDefOf.Lust);
 | 
			
		||||
            xxx.rjwSextype sextype = props.sexType;
 | 
			
		||||
            if (lust != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (sextype != xxx.rjwSextype.Masturbation || partner != null) pawn.records.AddTo(VariousDefOf.Lust, Mathf.Clamp((satisfaction - base_sat_per_fuck) * RJWUtility.LustIncrementFactor(lust ?? 0), -0.5f, 0.5f)); // If the sex is satisfactory, lust grows up. Declines at the opposite.
 | 
			
		||||
                else pawn.records.AddTo(VariousDefOf.Lust, Mathf.Clamp(satisfaction * satisfaction * RJWUtility.LustIncrementFactor(lust ?? 0), 0, 0.5f));                                             // Masturbation always increases lust.
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (sextype == xxx.rjwSextype.Masturbation || partner == null)
 | 
			
		||||
            {
 | 
			
		||||
                Building_CumBucket cumbucket = (Building_CumBucket)pawn.GetAdjacentBuilding<Building_CumBucket>();
 | 
			
		||||
                if (cumbucket != null)
 | 
			
		||||
                {
 | 
			
		||||
                    cumbucket.AddCum(pawn.GetCumVolume());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            RJWUtility.UpdateSatisfactionHIstory(pawn, partner, props, satisfaction);
 | 
			
		||||
            pawn.records?.Increment(VariousDefOf.OrgasmCount);
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(SexUtility), "TransferNutrition")]
 | 
			
		||||
    public static class RJW_Patch_TransferNutrition
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            Pawn pawn = props.pawn;
 | 
			
		||||
            Pawn partner = props.partner;
 | 
			
		||||
            xxx.rjwSextype sextype = props.sexType;
 | 
			
		||||
            Pawn giver = null;
 | 
			
		||||
            Pawn receiver = null;
 | 
			
		||||
 | 
			
		||||
            if (Genital_Helper.has_penis_fertile(pawn))
 | 
			
		||||
            {
 | 
			
		||||
                giver = pawn;
 | 
			
		||||
                receiver = partner;
 | 
			
		||||
            }
 | 
			
		||||
            else if (Genital_Helper.has_penis_fertile(partner))
 | 
			
		||||
            {
 | 
			
		||||
                giver = partner;
 | 
			
		||||
                receiver = pawn;
 | 
			
		||||
            }
 | 
			
		||||
    
 | 
			
		||||
            if (receiver != null && (
 | 
			
		||||
                sextype == xxx.rjwSextype.Oral ||
 | 
			
		||||
                sextype == xxx.rjwSextype.Fellatio ||
 | 
			
		||||
                sextype == xxx.rjwSextype.Sixtynine))
 | 
			
		||||
            {
 | 
			
		||||
                receiver.AteCum(giver.GetCumVolume(), true);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(Nymph_Generator), "set_skills")]
 | 
			
		||||
    public static class RJW_Patch_Nymph_set_skills
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            SkillRecord sexskill = pawn.skills.GetSkill(VariousDefOf.SexSkill);
 | 
			
		||||
            if (sexskill != null)
 | 
			
		||||
            {
 | 
			
		||||
                sexskill.passion = Passion.Major;
 | 
			
		||||
                sexskill.Level = (int)Utility.RandGaussianLike(7f, 20.99f);
 | 
			
		||||
                sexskill.xpSinceLastLevel = sexskill.XpRequiredForLevelUp * Rand.Range(0.10f, 0.90f);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(AfterSexUtility), "UpdateRecords")]
 | 
			
		||||
    public static class RJW_Patch_UpdateRecords
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            RJWUtility.UpdateSextypeRecords(props);
 | 
			
		||||
            RJWUtility.UpdatePartnerHistory(props.pawn, props.partner, props);
 | 
			
		||||
            RJWUtility.UpdatePartnerHistory(props.partner, props.pawn, props);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(JobDriver_SexBaseInitiator), "Start")]
 | 
			
		||||
    public static class RJW_Patch_LogSextype
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(JobDriver_SexBaseInitiator __instance)
 | 
			
		||||
        {
 | 
			
		||||
            if (__instance.Partner != null)
 | 
			
		||||
            {
 | 
			
		||||
                __instance.pawn.PoptheCherry(__instance.Partner, __instance.Sexprops);
 | 
			
		||||
                __instance.Partner.PoptheCherry(__instance.pawn, __instance.Sexprops);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(WorkGiver_CleanSelf), "JobOnThing")]
 | 
			
		||||
    public static class RJW_Patch_CleanSelf_JobOnThing
 | 
			
		||||
    {
 | 
			
		||||
        public static bool Prefix(Pawn pawn, Thing t, bool forced, ref Job __result)
 | 
			
		||||
        {
 | 
			
		||||
            Building_CumBucket bucket = pawn.GetAdjacentBuilding<Building_CumBucket>();
 | 
			
		||||
            if (bucket == null) bucket = pawn.FindClosestBucket();
 | 
			
		||||
            if (bucket != null)
 | 
			
		||||
            {
 | 
			
		||||
                __result = JobMaker.MakeJob(VariousDefOf.CleanSelfwithBucket, null, bucket, bucket.Position);
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(JobGiver_Masturbate), "TryGiveJob")]
 | 
			
		||||
    public static class RJW_Patch_Masturabte_TryGiveJob
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(Pawn pawn, ref Job __result)
 | 
			
		||||
        {
 | 
			
		||||
            if (RJWPreferenceSettings.FapEverywhere && __result != null)
 | 
			
		||||
            {
 | 
			
		||||
                Building_CumBucket bucket = pawn.FindClosestBucket();
 | 
			
		||||
                if (bucket != null)
 | 
			
		||||
                {
 | 
			
		||||
                    __result.Clear();
 | 
			
		||||
                    __result = JobMaker.MakeJob(xxx.Masturbate, null, null, bucket.RandomAdjacentCell8Way());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										145
									
								
								RJWSexperience/RJWSexperience/Patches/Rimworld_Patch.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,145 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using HarmonyLib;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
using rjw;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
    [HarmonyPatch(typeof(PawnGenerator), "GeneratePawn", new Type[] { typeof(PawnGenerationRequest) })]
 | 
			
		||||
    public static class Rimworld_Patch_GeneratePawn
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(PawnGenerationRequest request, ref Pawn __result)
 | 
			
		||||
        {
 | 
			
		||||
            if (Configurations.EnableRecordRandomizer && __result != null && !request.Newborn && xxx.is_human(__result))
 | 
			
		||||
            {
 | 
			
		||||
                int avgsex = -500;
 | 
			
		||||
                bool isvirgin = Rand.Chance(Configurations.VirginRatio);
 | 
			
		||||
                int totalsex = 0;
 | 
			
		||||
                int totalbirth = 0;
 | 
			
		||||
                int deviation = (int)Configurations.MaxSexCountDeviation;
 | 
			
		||||
                if (__result.story != null)
 | 
			
		||||
                {
 | 
			
		||||
                    float lust;
 | 
			
		||||
                    if (xxx.is_nympho(__result)) lust = __result.RecordRandomizer(VariousDefOf.Lust, Configurations.AvgLust, Configurations.MaxLustDeviation, 0);
 | 
			
		||||
                    else lust = __result.RecordRandomizer(VariousDefOf.Lust, Configurations.AvgLust, Configurations.MaxLustDeviation, float.MinValue);
 | 
			
		||||
 | 
			
		||||
                    int sexableage = 0;
 | 
			
		||||
                    int minsexage = (int)(__result.RaceProps.lifeExpectancy * Configurations.MinSexablePercent);
 | 
			
		||||
                    if (__result.ageTracker.AgeBiologicalYears > minsexage)
 | 
			
		||||
                    {
 | 
			
		||||
                        sexableage = __result.ageTracker.AgeBiologicalYears - minsexage;
 | 
			
		||||
                        avgsex = (int)(sexableage * Configurations.SexPerYear * __result.LustFactor());
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                    if (__result.relations != null && __result.gender == Gender.Female)
 | 
			
		||||
                    {
 | 
			
		||||
                        totalbirth += __result.relations.ChildrenCount;
 | 
			
		||||
                        totalsex += totalbirth;
 | 
			
		||||
                        __result.records?.AddTo(xxx.CountOfSexWithHumanlikes, totalbirth);
 | 
			
		||||
                        __result.records?.SetTo(xxx.CountOfBirthHuman, totalbirth);
 | 
			
		||||
                        if (totalbirth > 0) isvirgin = false;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (!isvirgin)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (xxx.is_rapist(__result))
 | 
			
		||||
                        {
 | 
			
		||||
                            if (xxx.is_zoophile(__result))
 | 
			
		||||
                            {
 | 
			
		||||
                                if (__result.Has(Quirk.ChitinLover)) totalsex += __result.RecordRandomizer(xxx.CountOfRapedInsects, avgsex, deviation);
 | 
			
		||||
                                else totalsex += __result.RecordRandomizer(xxx.CountOfRapedAnimals, avgsex, deviation);
 | 
			
		||||
                            }
 | 
			
		||||
                            else totalsex += __result.RecordRandomizer(xxx.CountOfRapedHumanlikes, avgsex, deviation);
 | 
			
		||||
                            avgsex /= 8;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if (xxx.is_zoophile(__result))
 | 
			
		||||
                        {
 | 
			
		||||
                            if (__result.Has(Quirk.ChitinLover)) totalsex += __result.RecordRandomizer(xxx.CountOfRapedInsects, avgsex, deviation);
 | 
			
		||||
                            else totalsex += __result.RecordRandomizer(xxx.CountOfSexWithAnimals, avgsex, deviation);
 | 
			
		||||
                            avgsex /= 10;
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (xxx.is_necrophiliac(__result))
 | 
			
		||||
                        {
 | 
			
		||||
                            totalsex += __result.RecordRandomizer(xxx.CountOfSexWithCorpse, avgsex, deviation);
 | 
			
		||||
                            avgsex /= 4;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if (__result.IsSlave)
 | 
			
		||||
                        {
 | 
			
		||||
                            totalsex += __result.RecordRandomizer(xxx.CountOfBeenRapedByAnimals, Rand.Range(-50, 10), Rand.Range(0, 10) * sexableage);
 | 
			
		||||
                            totalsex += __result.RecordRandomizer(xxx.CountOfBeenRapedByHumanlikes, 0, Rand.Range(0, 100) * sexableage);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                        totalsex += __result.RecordRandomizer(xxx.CountOfSexWithHumanlikes, avgsex, deviation);
 | 
			
		||||
                        
 | 
			
		||||
                        if (totalsex > 0) __result.records.AddTo(VariousDefOf.SexPartnerCount, Math.Max(1, Rand.Range(0, totalsex/7)));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                __result.records?.SetTo(xxx.CountOfSex, totalsex);
 | 
			
		||||
                RJWUtility.GenerateSextypeRecords(__result, totalsex);
 | 
			
		||||
            }
 | 
			
		||||
            if (__result.story?.traits != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (__result.IsVirgin())
 | 
			
		||||
                {
 | 
			
		||||
                    int degree = 0;
 | 
			
		||||
                    if (__result.gender == Gender.Female) degree = 2;
 | 
			
		||||
                    Trait virgin = new Trait(VariousDefOf.Virgin, degree ,true);
 | 
			
		||||
                    __result.story.traits.GainTrait(virgin);
 | 
			
		||||
                }
 | 
			
		||||
                else if (__result.gender == Gender.Female && Rand.Chance(0.05f))
 | 
			
		||||
                {
 | 
			
		||||
                    Trait virgin = new Trait(VariousDefOf.Virgin, 1, true);
 | 
			
		||||
                    __result.story.traits.GainTrait(virgin);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(FloatMenuMakerMap), "AddHumanlikeOrders")]
 | 
			
		||||
    public class HumanlikeOrder_Patch
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(Vector3 clickPos, Pawn pawn, List<FloatMenuOption> opts)
 | 
			
		||||
        {
 | 
			
		||||
            var targets = GenUI.TargetsAt(clickPos, TargetingParameters.ForBuilding());
 | 
			
		||||
 | 
			
		||||
            if (pawn.health.hediffSet.HasHediff(RJW_SemenoOverlayHediffDefOf.Hediff_Bukkake))
 | 
			
		||||
            foreach (LocalTargetInfo t in targets)
 | 
			
		||||
            {
 | 
			
		||||
                Building building = t.Thing as Building;
 | 
			
		||||
                if (building != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (building is Building_CumBucket)
 | 
			
		||||
                    {
 | 
			
		||||
                        opts.AddDistinct(MakeMenu(pawn, building));
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static FloatMenuOption MakeMenu(Pawn pawn, LocalTargetInfo target)
 | 
			
		||||
        {
 | 
			
		||||
            FloatMenuOption option = FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(Keyed.RS_FloatMenu_CleanSelf, delegate ()
 | 
			
		||||
            {
 | 
			
		||||
                pawn.jobs.TryTakeOrderedJob(new Verse.AI.Job(VariousDefOf.CleanSelfwithBucket, null, target, target.Cell));
 | 
			
		||||
            }, MenuOptionPriority.Low), pawn, target);
 | 
			
		||||
 | 
			
		||||
            return option;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -63,6 +63,12 @@
 | 
			
		|||
      <HintPath>..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.IMGUIModule.dll</HintPath>
 | 
			
		||||
      <Private>False</Private>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="UnityEngine.TextCoreModule">
 | 
			
		||||
      <HintPath>..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.TextCoreModule.dll</HintPath>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="UnityEngine.TextRenderingModule">
 | 
			
		||||
      <HintPath>..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.TextRenderingModule.dll</HintPath>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="UnityEngine.UI">
 | 
			
		||||
      <HintPath>..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.UI.dll</HintPath>
 | 
			
		||||
      <Private>False</Private>
 | 
			
		||||
| 
						 | 
				
			
			@ -77,20 +83,31 @@
 | 
			
		|||
    </Reference>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Compile Include="Buildings.cs" />
 | 
			
		||||
    <Compile Include="Building_Cumbucket.cs" />
 | 
			
		||||
    <Compile Include="Configurations.cs" />
 | 
			
		||||
    <Compile Include="DebugAction.cs" />
 | 
			
		||||
    <Compile Include="Harmony.cs" />
 | 
			
		||||
    <Compile Include="SexHistory.cs" />
 | 
			
		||||
    <Compile Include="IngestionOutcomeDoers.cs" />
 | 
			
		||||
    <Compile Include="JobDrivers.cs" />
 | 
			
		||||
    <Compile Include="Patches\DefInjection.cs" />
 | 
			
		||||
    <Compile Include="Patches\GetGizmos.cs" />
 | 
			
		||||
    <Compile Include="Recipe_HymenSurgery.cs" />
 | 
			
		||||
    <Compile Include="RJWUtility.cs" />
 | 
			
		||||
    <Compile Include="SexHistory\HistoryUtility.cs" />
 | 
			
		||||
    <Compile Include="SexHistory\SexHistory.cs" />
 | 
			
		||||
    <Compile Include="PawnRelationWorkers.cs" />
 | 
			
		||||
    <Compile Include="Keyed.cs" />
 | 
			
		||||
    <Compile Include="Rimworld_Patch.cs" />
 | 
			
		||||
    <Compile Include="RJW_Patch.cs" />
 | 
			
		||||
    <Compile Include="Patches\Rimworld_Patch.cs" />
 | 
			
		||||
    <Compile Include="Patches\RJW_Patch.cs" />
 | 
			
		||||
    <Compile Include="StatParts.cs" />
 | 
			
		||||
    <Compile Include="Thought_Opinionbased.cs" />
 | 
			
		||||
    <Compile Include="Thought_Recordbased.cs" />
 | 
			
		||||
    <Compile Include="Properties\AssemblyInfo.cs" />
 | 
			
		||||
    <Compile Include="UI\RJWUIUtility.cs" />
 | 
			
		||||
    <Compile Include="UI\SexStatus.cs" />
 | 
			
		||||
    <Compile Include="Utility.cs" />
 | 
			
		||||
    <Compile Include="VariousDefOf.cs" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup />
 | 
			
		||||
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 | 
			
		||||
</Project>
 | 
			
		||||
							
								
								
									
										409
									
								
								RJWSexperience/RJWSexperience/RJWUtility.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,409 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using rjw;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
using Verse.AI;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
    public static class RJWUtility
 | 
			
		||||
    {
 | 
			
		||||
        public static float GetSexStat(this Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            if (xxx.is_human(pawn) && !pawn.Dead)
 | 
			
		||||
            {
 | 
			
		||||
                return pawn.GetStatValue(xxx.sex_stat);
 | 
			
		||||
            }
 | 
			
		||||
            else return 1.0f;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static float LustIncrementFactor(float lust)
 | 
			
		||||
        {
 | 
			
		||||
            return Mathf.Exp(-Mathf.Pow(lust / Configurations.LustLimit, 2));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// If the pawn is virgin, return true.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static bool IsVirgin(this Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.records.GetValue(VariousDefOf.VaginalSexCount) == 0) return true;
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        public static bool HasHymen(this Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            Trait virgin = pawn.story?.traits?.GetTrait(VariousDefOf.Virgin);
 | 
			
		||||
            if (virgin != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (virgin.Degree > 0) return true;
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// If pawn is virgin, lose his/her virginity.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static void PoptheCherry(this Pawn pawn, Pawn partner, SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            if (props != null && props.sexType == xxx.rjwSextype.Vaginal)
 | 
			
		||||
            {
 | 
			
		||||
                if (pawn.IsVirgin())
 | 
			
		||||
                {
 | 
			
		||||
                    SexPartnerHistory history = pawn.GetPartnerHistory();
 | 
			
		||||
                    if (history != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        history.RecordFirst(partner, props);
 | 
			
		||||
                    }
 | 
			
		||||
                    if (RemoveVirginTrait(pawn, partner, props))
 | 
			
		||||
                    {
 | 
			
		||||
                        Messages.Message(Keyed.RS_LostVirgin(pawn.LabelShort, partner.LabelShort), MessageTypeDefOf.NeutralEvent, true);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    RemoveVirginTrait(pawn, partner, props);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool RemoveVirginTrait(Pawn pawn, Pawn partner, SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            int degree;
 | 
			
		||||
            Trait virgin = pawn.story?.traits?.GetTrait(VariousDefOf.Virgin);
 | 
			
		||||
            if (virgin != null)
 | 
			
		||||
            {
 | 
			
		||||
                degree = virgin.Degree;
 | 
			
		||||
                if (pawn.gender == Gender.Female && degree > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    FilthMaker.TryMakeFilth(pawn.Position, pawn.Map, ThingDefOf.Filth_Blood, pawn.LabelShort, 1, FilthSourceFlags.Pawn);
 | 
			
		||||
                }
 | 
			
		||||
                ThrowVirginHIstoryEvent(pawn, partner, props, degree);
 | 
			
		||||
                pawn.story.traits.RemoveTrait(virgin);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// For ideo patch
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static void ThrowVirginHIstoryEvent(Pawn pawn, Pawn partner, SexProps props, int degree)
 | 
			
		||||
        {
 | 
			
		||||
            //for non-ideo
 | 
			
		||||
            if (partner.Ideo == null)
 | 
			
		||||
            {
 | 
			
		||||
                partner.needs?.mood?.thoughts?.memories.TryGainMemory(xxx.took_virginity, pawn);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void UpdateSextypeRecords(SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            xxx.rjwSextype sextype = props.sexType;
 | 
			
		||||
            Pawn pawn = props.pawn;
 | 
			
		||||
            Pawn partner = props.partner;
 | 
			
		||||
            Pawn receiver = props.reciever;
 | 
			
		||||
            Pawn giver = props.giver;
 | 
			
		||||
 | 
			
		||||
            if (partner != null)
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
                switch (sextype)
 | 
			
		||||
                {
 | 
			
		||||
                    case xxx.rjwSextype.Vaginal:
 | 
			
		||||
                    case xxx.rjwSextype.Scissoring:
 | 
			
		||||
                        IncreaseSameRecords(pawn, partner, VariousDefOf.VaginalSexCount);
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Anal:
 | 
			
		||||
                        IncreaseSameRecords(pawn, partner, VariousDefOf.AnalSexCount);
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Oral:
 | 
			
		||||
                    case xxx.rjwSextype.Fellatio:
 | 
			
		||||
                        if (Genital_Helper.has_penis_fertile(giver) || Genital_Helper.has_penis_infertile(giver))
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.OralSexCount, VariousDefOf.BlowjobCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (Genital_Helper.has_penis_infertile(receiver) || Genital_Helper.has_penis_infertile(receiver))
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.BlowjobCount, VariousDefOf.OralSexCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Sixtynine:
 | 
			
		||||
                        IncreaseSameRecords(pawn, partner, VariousDefOf.OralSexCount);
 | 
			
		||||
                        RecordDef recordpawn, recordpartner;
 | 
			
		||||
                        if (Genital_Helper.has_penis_fertile(pawn) || Genital_Helper.has_penis_infertile(pawn))
 | 
			
		||||
                        {
 | 
			
		||||
                            recordpartner = VariousDefOf.BlowjobCount;
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            recordpartner = VariousDefOf.CunnilingusCount;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if (Genital_Helper.has_penis_fertile(partner) || Genital_Helper.has_penis_infertile(partner))
 | 
			
		||||
                        {
 | 
			
		||||
                            recordpawn = VariousDefOf.BlowjobCount;
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            recordpawn = VariousDefOf.CunnilingusCount;
 | 
			
		||||
                        }
 | 
			
		||||
                        IncreaseRecords(pawn, partner, recordpawn, recordpartner);
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Cunnilingus:
 | 
			
		||||
                        if (Genital_Helper.has_vagina(giver))
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.OralSexCount, VariousDefOf.CunnilingusCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (Genital_Helper.has_vagina(receiver))
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.CunnilingusCount, VariousDefOf.OralSexCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Masturbation:
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Handjob:
 | 
			
		||||
                        if (Genital_Helper.has_penis_fertile(giver) || Genital_Helper.has_penis_infertile(giver))
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.GenitalCaressCount, VariousDefOf.HandjobCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.HandjobCount, VariousDefOf.GenitalCaressCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Fingering:
 | 
			
		||||
                    case xxx.rjwSextype.Fisting:
 | 
			
		||||
                        if (Genital_Helper.has_vagina(giver))
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.GenitalCaressCount, VariousDefOf.FingeringCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.FingeringCount, VariousDefOf.GenitalCaressCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Footjob:
 | 
			
		||||
                        IncreaseSameRecords(pawn, partner, VariousDefOf.FootjobCount);
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        IncreaseSameRecords(pawn, partner, VariousDefOf.MiscSexualBehaviorCount);
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void UpdatePartnerHistory(Pawn pawn, Pawn partner, SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            if (partner != null)
 | 
			
		||||
            {
 | 
			
		||||
                SexPartnerHistory pawnshistory = pawn.TryGetComp<SexPartnerHistory>();
 | 
			
		||||
                pawnshistory?.RecordHistory(partner, props);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void UpdateSatisfactionHIstory(Pawn pawn, Pawn partner, SexProps props, float satisfaction)
 | 
			
		||||
        {
 | 
			
		||||
            if (partner != null)
 | 
			
		||||
            {
 | 
			
		||||
                SexPartnerHistory pawnshistory = pawn.TryGetComp<SexPartnerHistory>();
 | 
			
		||||
                pawnshistory?.RecordSatisfactionHistory(partner, props, satisfaction);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void IncreaseSameRecords(Pawn pawn, Pawn partner, RecordDef record)
 | 
			
		||||
        {
 | 
			
		||||
            pawn.records?.AddTo(record, 1);
 | 
			
		||||
            partner.records?.AddTo(record, 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void IncreaseRecords(Pawn pawn, Pawn partner, RecordDef recordforpawn, RecordDef recordforpartner)
 | 
			
		||||
        {
 | 
			
		||||
            pawn.records?.AddTo(recordforpawn, 1);
 | 
			
		||||
            partner.records?.AddTo(recordforpartner, 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void GenerateSextypeRecords(Pawn pawn, int totalsex)
 | 
			
		||||
        {
 | 
			
		||||
            float totalweight =
 | 
			
		||||
                RJWPreferenceSettings.vaginal +
 | 
			
		||||
                RJWPreferenceSettings.anal +
 | 
			
		||||
                RJWPreferenceSettings.fellatio +
 | 
			
		||||
                RJWPreferenceSettings.cunnilingus +
 | 
			
		||||
                RJWPreferenceSettings.rimming +
 | 
			
		||||
                RJWPreferenceSettings.double_penetration +
 | 
			
		||||
                RJWPreferenceSettings.breastjob +
 | 
			
		||||
                RJWPreferenceSettings.handjob +
 | 
			
		||||
                RJWPreferenceSettings.mutual_masturbation +
 | 
			
		||||
                RJWPreferenceSettings.fingering +
 | 
			
		||||
                RJWPreferenceSettings.footjob +
 | 
			
		||||
                RJWPreferenceSettings.scissoring +
 | 
			
		||||
                RJWPreferenceSettings.fisting +
 | 
			
		||||
                RJWPreferenceSettings.sixtynine;
 | 
			
		||||
            Gender prefer = pawn.PreferGender();
 | 
			
		||||
            int sex = (int)(totalsex * RJWPreferenceSettings.vaginal / totalweight);
 | 
			
		||||
            totalsex -= sex;
 | 
			
		||||
            pawn.records.AddTo(VariousDefOf.VaginalSexCount, sex);
 | 
			
		||||
 | 
			
		||||
            sex = (int)(totalsex * RJWPreferenceSettings.anal / totalweight);
 | 
			
		||||
            totalsex -= sex;
 | 
			
		||||
            pawn.records.AddTo(VariousDefOf.AnalSexCount, sex);
 | 
			
		||||
 | 
			
		||||
            sex = (int)(totalsex * RJWPreferenceSettings.fellatio / totalweight);
 | 
			
		||||
            totalsex -= sex;
 | 
			
		||||
            if (prefer == Gender.Male) pawn.records.AddTo(VariousDefOf.BlowjobCount, sex);
 | 
			
		||||
            else pawn.records.AddTo(VariousDefOf.OralSexCount, sex);
 | 
			
		||||
 | 
			
		||||
            sex = (int)(totalsex * RJWPreferenceSettings.cunnilingus / totalweight);
 | 
			
		||||
            totalsex -= sex;
 | 
			
		||||
            if (prefer == Gender.Male) pawn.records.AddTo(VariousDefOf.OralSexCount, sex);
 | 
			
		||||
            else pawn.records.AddTo(VariousDefOf.CunnilingusCount, sex);
 | 
			
		||||
 | 
			
		||||
            sex = (int)(totalsex * RJWPreferenceSettings.rimming / totalweight);
 | 
			
		||||
            totalsex -= sex;
 | 
			
		||||
            pawn.records.AddTo(VariousDefOf.MiscSexualBehaviorCount, sex);
 | 
			
		||||
 | 
			
		||||
            sex = (int)(totalsex * RJWPreferenceSettings.double_penetration / totalweight) / 2;
 | 
			
		||||
            totalsex -= sex;
 | 
			
		||||
            totalsex -= sex;
 | 
			
		||||
            pawn.records.AddTo(VariousDefOf.VaginalSexCount, sex);
 | 
			
		||||
            pawn.records.AddTo(VariousDefOf.AnalSexCount, sex);
 | 
			
		||||
 | 
			
		||||
            sex = (int)(totalsex * RJWPreferenceSettings.breastjob / totalweight);
 | 
			
		||||
            totalsex -= sex;
 | 
			
		||||
            pawn.records.AddTo(VariousDefOf.MiscSexualBehaviorCount, sex);
 | 
			
		||||
 | 
			
		||||
            sex = (int)(totalsex * RJWPreferenceSettings.handjob / totalweight);
 | 
			
		||||
            totalsex -= sex;
 | 
			
		||||
            if (prefer == Gender.Male) pawn.records.AddTo(VariousDefOf.HandjobCount, sex);
 | 
			
		||||
            else pawn.records.AddTo(VariousDefOf.GenitalCaressCount, sex);
 | 
			
		||||
 | 
			
		||||
            sex = (int)(totalsex * RJWPreferenceSettings.fingering / totalweight);
 | 
			
		||||
            totalsex -= sex;
 | 
			
		||||
            if (prefer == Gender.Female) pawn.records.AddTo(VariousDefOf.FingeringCount, sex);
 | 
			
		||||
            else pawn.records.AddTo(VariousDefOf.GenitalCaressCount, sex);
 | 
			
		||||
 | 
			
		||||
            sex = (int)(totalsex * RJWPreferenceSettings.mutual_masturbation / totalweight);
 | 
			
		||||
            totalsex -= sex;
 | 
			
		||||
            if (prefer == Gender.Male) pawn.records.AddTo(VariousDefOf.HandjobCount, sex);
 | 
			
		||||
            else pawn.records.AddTo(VariousDefOf.FingeringCount, sex);
 | 
			
		||||
            pawn.records.AddTo(VariousDefOf.GenitalCaressCount, sex);
 | 
			
		||||
 | 
			
		||||
            sex = (int)(totalsex * RJWPreferenceSettings.footjob / totalweight);
 | 
			
		||||
            totalsex -= sex;
 | 
			
		||||
            pawn.records.AddTo(VariousDefOf.FootjobCount, sex);
 | 
			
		||||
 | 
			
		||||
            sex = (int)(totalsex * RJWPreferenceSettings.scissoring / totalweight);
 | 
			
		||||
            totalsex -= sex;
 | 
			
		||||
            pawn.records.AddTo(VariousDefOf.MiscSexualBehaviorCount, sex);
 | 
			
		||||
 | 
			
		||||
            sex = (int)(totalsex * RJWPreferenceSettings.fisting / totalweight);
 | 
			
		||||
            totalsex -= sex;
 | 
			
		||||
            pawn.records.AddTo(VariousDefOf.MiscSexualBehaviorCount, sex);
 | 
			
		||||
 | 
			
		||||
            pawn.records.AddTo(VariousDefOf.OralSexCount, totalsex);
 | 
			
		||||
            if (prefer == Gender.Male) pawn.records.AddTo(VariousDefOf.BlowjobCount, totalsex);
 | 
			
		||||
            else pawn.records.AddTo(VariousDefOf.CunnilingusCount, totalsex);
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static Gender PreferGender(this Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.gender == Gender.Male)
 | 
			
		||||
            {
 | 
			
		||||
                if (xxx.is_homosexual(pawn)) return Gender.Male;
 | 
			
		||||
                else return Gender.Female;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (xxx.is_homosexual(pawn)) return Gender.Female;
 | 
			
		||||
                else return Gender.Male;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool GetRapist(this SexProps props, out Pawn rapist)
 | 
			
		||||
        {
 | 
			
		||||
            if (!props.isRape)
 | 
			
		||||
            {
 | 
			
		||||
                rapist = null;
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            rapist = props.pawn;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool IsBestiality(this SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            if (props.partner != null)
 | 
			
		||||
            {
 | 
			
		||||
                return props.pawn.IsAnimal() ^ props.partner.IsAnimal();
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static Building_CumBucket FindClosestBucket(this Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            List<Building> buckets = pawn.Map.listerBuildings.allBuildingsColonist.FindAll(x => x is Building_CumBucket);
 | 
			
		||||
            Dictionary<Building, float> targets = new Dictionary<Building, float>();
 | 
			
		||||
            if (!buckets.NullOrEmpty()) for (int i = 0; i < buckets.Count; i++)
 | 
			
		||||
                {
 | 
			
		||||
                    if (pawn.CanReach(buckets[i], PathEndMode.ClosestTouch, Danger.None))
 | 
			
		||||
                    {
 | 
			
		||||
                        targets.Add(buckets[i], pawn.Position.DistanceTo(buckets[i].Position));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            if (!targets.NullOrEmpty())
 | 
			
		||||
            {
 | 
			
		||||
                return (Building_CumBucket)targets.MinBy(x => x.Value).Key;
 | 
			
		||||
            }
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void AteCum(this Pawn pawn, float amount, bool doDrugEffect = false)
 | 
			
		||||
        {
 | 
			
		||||
            pawn.records.AddTo(VariousDefOf.NumofEatenCum, 1);
 | 
			
		||||
            pawn.records.AddTo(VariousDefOf.AmountofEatenCum, amount);
 | 
			
		||||
            if (doDrugEffect) pawn.CumDrugEffect();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void CumDrugEffect(this Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            Need need = pawn.needs?.TryGetNeed(VariousDefOf.Chemical_Cum);
 | 
			
		||||
            if (need != null) need.CurLevel += VariousDefOf.CumneedLevelOffset;
 | 
			
		||||
            Hediff addictive = HediffMaker.MakeHediff(VariousDefOf.CumTolerance, pawn);
 | 
			
		||||
            addictive.Severity = 0.032f;
 | 
			
		||||
            pawn.health.AddHediff(addictive);
 | 
			
		||||
            Hediff addiction = pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.CumAddiction);
 | 
			
		||||
            if (addiction != null) addiction.Severity += VariousDefOf.CumexistingAddictionSeverityOffset;
 | 
			
		||||
 | 
			
		||||
            pawn.needs?.mood?.thoughts?.memories?.TryGainMemoryFast(VariousDefOf.AteCum);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void AddVirginTrait(this Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.story?.traits != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (pawn.IsVirgin())
 | 
			
		||||
                {
 | 
			
		||||
                    int degree = 0;
 | 
			
		||||
                    if (pawn.gender == Gender.Female) degree = 2;
 | 
			
		||||
                    Trait virgin = new Trait(VariousDefOf.Virgin, degree, true);
 | 
			
		||||
                    pawn.story.traits.GainTrait(virgin);
 | 
			
		||||
                }
 | 
			
		||||
                else if (pawn.gender == Gender.Female && Rand.Chance(0.05f))
 | 
			
		||||
                {
 | 
			
		||||
                    Trait virgin = new Trait(VariousDefOf.Virgin, 1, true);
 | 
			
		||||
                    pawn.story.traits.GainTrait(virgin);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,305 +0,0 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using HarmonyLib;
 | 
			
		||||
using rjw;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
    public static class RJWUtility
 | 
			
		||||
    {
 | 
			
		||||
        public static float GetSexStat(this Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            if (xxx.is_human(pawn) && !pawn.Dead)
 | 
			
		||||
            {
 | 
			
		||||
                return pawn.GetStatValue(xxx.sex_stat);
 | 
			
		||||
            }
 | 
			
		||||
            else return 1.0f;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static float LustIncrementFactor(float lust)
 | 
			
		||||
        {
 | 
			
		||||
            return Mathf.Exp(-Mathf.Pow(lust / Configurations.LustLimit, 2));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// If the pawn is virgin, return true.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static bool IsVirgin(this Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.records.GetValue(xxx.CountOfSex) == 0) return true;
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// If pawn is virgin, lose his/her virginity.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public static void PoptheCherry(this Pawn pawn, Pawn partner, bool violent)
 | 
			
		||||
        {
 | 
			
		||||
            if (pawn.IsVirgin())
 | 
			
		||||
            {
 | 
			
		||||
                Messages.Message(Keyed.RS_LostVirgin(pawn.LabelShort, partner.LabelShort), MessageTypeDefOf.NeutralEvent, true);
 | 
			
		||||
                RemoveVirginTrait(pawn);
 | 
			
		||||
                FilthMaker.TryMakeFilth(pawn.Position, pawn.Map, ThingDefOf.Filth_Blood, 1, FilthSourceFlags.Pawn);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        public static void RemoveVirginTrait(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            Trait virgin = pawn.story?.traits?.GetTrait(VariousDefOf.Virgin);
 | 
			
		||||
            if (virgin != null)
 | 
			
		||||
            {
 | 
			
		||||
                pawn.story.traits.RemoveTrait(virgin);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void UpdateSextypeRecords(SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            xxx.rjwSextype sextype = props.sexType;
 | 
			
		||||
            Pawn pawn = props.pawn;
 | 
			
		||||
            Pawn partner = props.partner;
 | 
			
		||||
            Pawn receiver = props.reciever;
 | 
			
		||||
            Pawn giver = props.giver;
 | 
			
		||||
 | 
			
		||||
            if (partner != null)
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
                switch (sextype)
 | 
			
		||||
                {
 | 
			
		||||
                    case xxx.rjwSextype.Vaginal:
 | 
			
		||||
                    case xxx.rjwSextype.Scissoring:
 | 
			
		||||
                        IncreaseSameRecords(pawn, partner, VariousDefOf.VaginalSexCount);
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Anal:
 | 
			
		||||
                        IncreaseSameRecords(pawn, partner, VariousDefOf.AnalSexCount);
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Oral:
 | 
			
		||||
                    case xxx.rjwSextype.Fellatio:
 | 
			
		||||
                        if (Genital_Helper.has_penis_fertile(giver) || Genital_Helper.has_penis_infertile(giver))
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.OralSexCount, VariousDefOf.BlowjobCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (Genital_Helper.has_penis_infertile(receiver) || Genital_Helper.has_penis_infertile(receiver))
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.BlowjobCount, VariousDefOf.OralSexCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Sixtynine:
 | 
			
		||||
                        IncreaseSameRecords(pawn, partner, VariousDefOf.OralSexCount);
 | 
			
		||||
                        RecordDef recordpawn, recordpartner;
 | 
			
		||||
                        if (Genital_Helper.has_penis_fertile(pawn) || Genital_Helper.has_penis_infertile(pawn))
 | 
			
		||||
                        {
 | 
			
		||||
                            recordpartner = VariousDefOf.BlowjobCount;
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            recordpartner = VariousDefOf.CunnilingusCount;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if (Genital_Helper.has_penis_fertile(partner) || Genital_Helper.has_penis_infertile(partner))
 | 
			
		||||
                        {
 | 
			
		||||
                            recordpawn = VariousDefOf.BlowjobCount;
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            recordpawn = VariousDefOf.CunnilingusCount;
 | 
			
		||||
                        }
 | 
			
		||||
                        IncreaseRecords(pawn, partner, recordpawn, recordpartner);
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Cunnilingus:
 | 
			
		||||
                        if (Genital_Helper.has_vagina(giver))
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.OralSexCount, VariousDefOf.CunnilingusCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (Genital_Helper.has_vagina(receiver))
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.CunnilingusCount, VariousDefOf.OralSexCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Masturbation:
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Handjob:
 | 
			
		||||
                        if (Genital_Helper.has_penis_fertile(giver) || Genital_Helper.has_penis_infertile(giver))
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.GenitalCaressCount, VariousDefOf.HadnjobCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.HadnjobCount, VariousDefOf.GenitalCaressCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Fingering:
 | 
			
		||||
                    case xxx.rjwSextype.Fisting:
 | 
			
		||||
                        if (Genital_Helper.has_vagina(giver))
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.GenitalCaressCount, VariousDefOf.FingeringCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            IncreaseRecords(giver, receiver, VariousDefOf.FingeringCount, VariousDefOf.GenitalCaressCount);
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                    case xxx.rjwSextype.Footjob:
 | 
			
		||||
                        IncreaseSameRecords(pawn, partner, VariousDefOf.FootjobCount);
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        IncreaseSameRecords(pawn, partner, VariousDefOf.MiscSexualBehaviorCount);
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void UpdatePartnerHistory(Pawn pawn, Pawn partner, SexProps props, float satisfaction)
 | 
			
		||||
        {
 | 
			
		||||
            SexPartnerHistory pawnshistory = pawn.GetComp<SexPartnerHistory>();
 | 
			
		||||
            pawnshistory.RecordHistory(partner, props);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void IncreaseSameRecords(Pawn pawn, Pawn partner, RecordDef record)
 | 
			
		||||
        {
 | 
			
		||||
            pawn.records?.AddTo(record, 1);
 | 
			
		||||
            partner.records?.AddTo(record, 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void IncreaseRecords(Pawn pawn, Pawn partner, RecordDef recordforpawn, RecordDef recordforpartner)
 | 
			
		||||
        {
 | 
			
		||||
            pawn.records?.AddTo(recordforpawn, 1);
 | 
			
		||||
            partner.records?.AddTo(recordforpartner, 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(JobDriver_Sex), "Orgasm")]
 | 
			
		||||
    public static class RJW_Patch_Orgasm
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(JobDriver_Sex __instance)
 | 
			
		||||
        {
 | 
			
		||||
            if (__instance.Sexprops.sexType != xxx.rjwSextype.Masturbation && !(__instance is JobDriver_Masturbate))
 | 
			
		||||
            {
 | 
			
		||||
                if (__instance.Sexprops.isRape)
 | 
			
		||||
                {
 | 
			
		||||
                    __instance.pawn?.skills?.Learn(VariousDefOf.SexSkill, 0.05f, true);
 | 
			
		||||
                }
 | 
			
		||||
                {   
 | 
			
		||||
                    __instance.pawn?.skills?.Learn(VariousDefOf.SexSkill, 0.35f, true);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(WhoringHelper), "WhoreAbilityAdjustmentMin")]
 | 
			
		||||
    public static class RJW_Patch_WhoreAbilityAdjustmentMin
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(Pawn whore, ref float __result)
 | 
			
		||||
        {
 | 
			
		||||
            __result *= whore.GetSexStat();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(WhoringHelper), "WhoreAbilityAdjustmentMax")]
 | 
			
		||||
    public static class RJW_Patch_WhoreAbilityAdjustmentMax
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(Pawn whore, ref float __result)
 | 
			
		||||
        {
 | 
			
		||||
            __result *= whore.GetSexStat();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(SexUtility), "SatisfyPersonal")]
 | 
			
		||||
    public static class RJW_Patch_SatisfyPersonal
 | 
			
		||||
    {
 | 
			
		||||
        private const float base_sat_per_fuck = 0.4f;
 | 
			
		||||
 | 
			
		||||
        public static void Prefix(SexProps props, ref float satisfaction)
 | 
			
		||||
        {
 | 
			
		||||
            Pawn pawn = props.pawn;
 | 
			
		||||
            Pawn partner = props.partner;
 | 
			
		||||
            satisfaction = Mathf.Max(base_sat_per_fuck, satisfaction * partner.GetSexStat());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void Postfix(SexProps props, float satisfaction)
 | 
			
		||||
        {
 | 
			
		||||
            Pawn pawn = props.pawn;
 | 
			
		||||
            Pawn partner = props.partner;
 | 
			
		||||
            float? lust = pawn.records?.GetValue(VariousDefOf.Lust);
 | 
			
		||||
            xxx.rjwSextype sextype = props.sexType;
 | 
			
		||||
            if (lust != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (sextype != xxx.rjwSextype.Masturbation || partner != null) pawn.records.AddTo(VariousDefOf.Lust, Mathf.Clamp((satisfaction - base_sat_per_fuck) * RJWUtility.LustIncrementFactor(lust ?? 0), -0.5f, 0.5f)); // If the sex is satisfactory, lust grows up. Declines at the opposite.
 | 
			
		||||
                else pawn.records.AddTo(VariousDefOf.Lust, Mathf.Clamp(satisfaction * satisfaction * RJWUtility.LustIncrementFactor(lust ?? 0), 0, 0.5f));                                             // Masturbation always increases lust.
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (sextype == xxx.rjwSextype.Masturbation || partner == null)
 | 
			
		||||
            {
 | 
			
		||||
                Building_CumBucket cumbucket = (Building_CumBucket)pawn.GetAdjacentBuilding<Building_CumBucket>();
 | 
			
		||||
                if (cumbucket != null)
 | 
			
		||||
                {
 | 
			
		||||
                    cumbucket.AddCum(pawn.GetCumVolume());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(SexUtility), "TransferNutrition")]
 | 
			
		||||
    public static class RJW_Patch_TransferNutrition
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            Pawn pawn = props.pawn;
 | 
			
		||||
            Pawn partner = props.partner;
 | 
			
		||||
            xxx.rjwSextype sextype = props.sexType;
 | 
			
		||||
            Pawn receiver = null;
 | 
			
		||||
 | 
			
		||||
            if (Genital_Helper.has_penis_fertile(pawn)) receiver = partner;
 | 
			
		||||
            else if (Genital_Helper.has_penis_fertile(partner)) receiver = pawn;
 | 
			
		||||
    
 | 
			
		||||
            if (receiver != null && (
 | 
			
		||||
                sextype == xxx.rjwSextype.Oral ||
 | 
			
		||||
                sextype == xxx.rjwSextype.Fellatio ||
 | 
			
		||||
                sextype == xxx.rjwSextype.Sixtynine))
 | 
			
		||||
            {
 | 
			
		||||
                receiver.CumDrugEffect();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(Nymph_Generator), "set_skills")]
 | 
			
		||||
    public static class RJW_Patch_Nymph_set_skills
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            SkillRecord sexskill = pawn.skills.GetSkill(VariousDefOf.SexSkill);
 | 
			
		||||
            if (sexskill != null)
 | 
			
		||||
            {
 | 
			
		||||
                sexskill.passion = Passion.Major;
 | 
			
		||||
                sexskill.Level = (int)Utility.RandGaussianLike(7f, 20.99f);
 | 
			
		||||
                sexskill.xpSinceLastLevel = sexskill.XpRequiredForLevelUp * Rand.Range(0.10f, 0.90f);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HarmonyPatch(typeof(AfterSexUtility), "UpdateRecords")]
 | 
			
		||||
    public static class RJW_Patch_UpdateRecords
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            RJWUtility.UpdateSextypeRecords(props);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										55
									
								
								RJWSexperience/RJWSexperience/Recipe_HymenSurgery.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
    public class Recipe_HymenSurgery : Recipe_Surgery
 | 
			
		||||
    {
 | 
			
		||||
        public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn pawn, RecipeDef recipe)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            if (pawn.gender != Gender.Female)
 | 
			
		||||
            {
 | 
			
		||||
                yield break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            BodyPartRecord part = Genital_Helper.get_genitalsBPR(pawn);
 | 
			
		||||
            if (part != null)
 | 
			
		||||
            {
 | 
			
		||||
                List<Hediff> hediffs = Genital_Helper.get_PartsHediffList(pawn, part);
 | 
			
		||||
                if (Genital_Helper.has_vagina(pawn, hediffs) && !pawn.HasHymen())
 | 
			
		||||
                {
 | 
			
		||||
                    yield return part;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override void ApplyOnPawn(Pawn pawn, BodyPartRecord part, Pawn billDoer, List<Thing> ingredients, Bill bill)
 | 
			
		||||
        {
 | 
			
		||||
            if (billDoer != null)
 | 
			
		||||
            {
 | 
			
		||||
                TaleRecorder.RecordTale(TaleDefOf.DidSurgery, new object[]
 | 
			
		||||
                {
 | 
			
		||||
                    billDoer,
 | 
			
		||||
                    pawn
 | 
			
		||||
                });
 | 
			
		||||
                SurgeryResult(pawn);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void SurgeryResult(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            int degree = 1;
 | 
			
		||||
            if (pawn.IsVirgin()) degree = 2;
 | 
			
		||||
            Trait virgin = new Trait(VariousDefOf.Virgin, degree, true);
 | 
			
		||||
            pawn.story.traits.GainTrait(virgin);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,91 +0,0 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using HarmonyLib;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
using rjw;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
    [HarmonyPatch(typeof(PawnGenerator), "GeneratePawn", new Type[] { typeof(PawnGenerationRequest) })]
 | 
			
		||||
    public static class Rimworld_Patch_GeneratePawn
 | 
			
		||||
    {
 | 
			
		||||
        public static void Postfix(PawnGenerationRequest request, ref Pawn __result)
 | 
			
		||||
        {
 | 
			
		||||
            if (__result != null && !request.Newborn && xxx.is_human(__result))
 | 
			
		||||
            {
 | 
			
		||||
                float avgsex = -500;
 | 
			
		||||
                bool isvirgin = Rand.Chance(Configurations.VirginRatio);
 | 
			
		||||
                int totalsex = 0;
 | 
			
		||||
                float totalbirth = 0;
 | 
			
		||||
                if (__result.story != null)
 | 
			
		||||
                {
 | 
			
		||||
                    float lust;
 | 
			
		||||
                    if (xxx.is_nympho(__result)) lust = __result.RecordRandomizer(VariousDefOf.Lust, Configurations.AvgLust, Configurations.MaxLustDeviation, 0);
 | 
			
		||||
                    else lust = __result.RecordRandomizer(VariousDefOf.Lust, Configurations.AvgLust, Configurations.MaxLustDeviation, float.MinValue);
 | 
			
		||||
 | 
			
		||||
                    float sexableage = 0;
 | 
			
		||||
                    float minsexage = __result.RaceProps.lifeExpectancy * Configurations.MinSexablePercent;
 | 
			
		||||
                    if (__result.ageTracker.AgeBiologicalYears > minsexage)
 | 
			
		||||
                    {
 | 
			
		||||
                        sexableage = __result.ageTracker.AgeBiologicalYearsFloat - minsexage;
 | 
			
		||||
                        avgsex = sexableage * Configurations.SexPerYear * __result.LustFactor();
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                    if (__result.relations != null && __result.gender == Gender.Female)
 | 
			
		||||
                    {
 | 
			
		||||
                        totalbirth += __result.relations.ChildrenCount;
 | 
			
		||||
                        totalsex += (int)totalbirth;
 | 
			
		||||
                        __result.records?.AddTo(xxx.CountOfSexWithHumanlikes, totalbirth);
 | 
			
		||||
                        __result.records?.SetTo(xxx.CountOfBirthHuman, totalbirth);
 | 
			
		||||
                        if (totalbirth > 0) isvirgin = false;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (!isvirgin)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (xxx.is_rapist(__result))
 | 
			
		||||
                        {
 | 
			
		||||
                            if (xxx.is_zoophile(__result))
 | 
			
		||||
                            {
 | 
			
		||||
                                if (__result.Has(Quirk.ChitinLover)) totalsex += (int)__result.RecordRandomizer(xxx.CountOfRapedInsects, avgsex, Configurations.MaxSexCountDeviation);
 | 
			
		||||
                                else totalsex += (int)__result.RecordRandomizer(xxx.CountOfRapedAnimals, avgsex, Configurations.MaxSexCountDeviation);
 | 
			
		||||
                            }
 | 
			
		||||
                            else totalsex += (int)__result.RecordRandomizer(xxx.CountOfRapedHumanlikes, avgsex, Configurations.MaxSexCountDeviation);
 | 
			
		||||
                            avgsex /= 4;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if (xxx.is_zoophile(__result))
 | 
			
		||||
                        {
 | 
			
		||||
                            if (__result.Has(Quirk.ChitinLover)) totalsex += (int)__result.RecordRandomizer(xxx.CountOfRapedInsects, avgsex, Configurations.MaxSexCountDeviation);
 | 
			
		||||
                            else totalsex += (int)__result.RecordRandomizer(xxx.CountOfSexWithAnimals, avgsex, Configurations.MaxSexCountDeviation);
 | 
			
		||||
                            avgsex /= 2;
 | 
			
		||||
                        }
 | 
			
		||||
                        else if (xxx.is_necrophiliac(__result))
 | 
			
		||||
                        {
 | 
			
		||||
                            totalsex += (int)__result.RecordRandomizer(xxx.CountOfSexWithCorpse, avgsex, Configurations.MaxSexCountDeviation);
 | 
			
		||||
                            avgsex /= 2;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if (__result.IsSlave)
 | 
			
		||||
                        {
 | 
			
		||||
                            totalsex += (int)__result.RecordRandomizer(xxx.CountOfBeenRapedByAnimals, Rand.Range(-50, 10), Rand.Range(0, 10) * sexableage);
 | 
			
		||||
                            totalsex += (int)__result.RecordRandomizer(xxx.CountOfBeenRapedByHumanlikes, 0, Rand.Range(0, 100) * sexableage);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                        totalsex += (int)__result.RecordRandomizer(xxx.CountOfSexWithHumanlikes, avgsex, Configurations.MaxSexCountDeviation);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                __result.records?.SetTo(xxx.CountOfSex, totalsex);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,284 +0,0 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
using rjw;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
    public class SexPartnerHistory : ThingComp
 | 
			
		||||
    {
 | 
			
		||||
        public SexPartnerHistory() { }
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        //protected List<SexHistory> histories = new List<SexHistory>();
 | 
			
		||||
        protected Dictionary<string,SexHistory> histories = new Dictionary<string,SexHistory>();
 | 
			
		||||
        protected string first = "";
 | 
			
		||||
        protected bool dirty = true;
 | 
			
		||||
        protected string bestaffinity = "";
 | 
			
		||||
        protected float bestaffinitysat = 0;
 | 
			
		||||
        protected xxx.rjwSextype recentsex = xxx.rjwSextype.None;
 | 
			
		||||
        protected string recentpartner = "";
 | 
			
		||||
        protected int[] sextypecount = new int[20];
 | 
			
		||||
        protected float[] sextypesat = new float[20];
 | 
			
		||||
 | 
			
		||||
        protected string mostpartnercache = "";
 | 
			
		||||
        protected xxx.rjwSextype mostsextypecache = xxx.rjwSextype.None;
 | 
			
		||||
        protected xxx.rjwSextype mostsatsextypecache = xxx.rjwSextype.None;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public string FirstSexInfo
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                return
 | 
			
		||||
                    "Partner: " + histories.TryGetValue(first)?.Label ?? "Unknown" +
 | 
			
		||||
                    "";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public string MostSexPartner
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                return histories.TryGetValue(mostpartnercache)?.Label ?? "Unknown";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public xxx.rjwSextype MostSextype
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                return mostsextypecache;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public xxx.rjwSextype MostSatisfiedSex
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                return mostsatsextypecache;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public override void PostExposeData()
 | 
			
		||||
        {
 | 
			
		||||
            Scribe_Collections.Look(ref histories, "histories", LookMode.Deep);
 | 
			
		||||
            Scribe_Values.Look(ref first, "first", "", true);
 | 
			
		||||
            Scribe_Values.Look(ref bestaffinity, "bestaffinity", "", true);
 | 
			
		||||
            Scribe_Values.Look(ref bestaffinitysat, "bestaffinitysat", bestaffinitysat, true);
 | 
			
		||||
            Scribe_Values.Look(ref recentsex, "recentsex", recentsex, true);
 | 
			
		||||
            Scribe_Values.Look(ref recentpartner, "recentpartner", recentpartner, true);
 | 
			
		||||
            Scribe_Values.Look(ref sextypecount, "sextypecount", sextypecount, true);
 | 
			
		||||
            Scribe_Values.Look(ref sextypesat, "sextypesat", sextypesat, true);
 | 
			
		||||
            base.PostExposeData();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RecordHistory(Pawn partner, SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            TryAddHistory(partner);
 | 
			
		||||
            recentpartner = partner.ThingID;
 | 
			
		||||
            SexHistory history = histories[partner.ThingID];
 | 
			
		||||
            history?.RecordSex(props);
 | 
			
		||||
            recentsex = props.sexType;
 | 
			
		||||
            sextypecount[(int)props.sexType]++;
 | 
			
		||||
 | 
			
		||||
            dirty = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RecordSatisfactionHistory(Pawn partner, SexProps props, float satisfaction)
 | 
			
		||||
        {
 | 
			
		||||
            TryAddHistory(partner);
 | 
			
		||||
            RecordFirst(partner, props);
 | 
			
		||||
            SexHistory history = histories[partner.ThingID];
 | 
			
		||||
            history?.RecordSatisfaction(props, satisfaction);
 | 
			
		||||
            sextypesat[(int)props.sexType] += satisfaction;
 | 
			
		||||
            dirty = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected bool TryAddHistory(Pawn partner)
 | 
			
		||||
        {
 | 
			
		||||
            if (!histories.ContainsKey(partner.ThingID))
 | 
			
		||||
            {
 | 
			
		||||
                histories.Add(partner.ThingID, new SexHistory(partner));
 | 
			
		||||
                Pawn pawn = parent as Pawn;
 | 
			
		||||
                if (pawn != null)
 | 
			
		||||
                {
 | 
			
		||||
                    pawn.records.AddTo(VariousDefOf.SexPartnerCount, 1);
 | 
			
		||||
                }
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void RecordFirst(Pawn partner, SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            if (VirginCheck() && props.sexType == xxx.rjwSextype.Vaginal)
 | 
			
		||||
            {
 | 
			
		||||
                first = partner.ThingID;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void Update()
 | 
			
		||||
        {
 | 
			
		||||
            if (dirty)
 | 
			
		||||
            {
 | 
			
		||||
                UpdateStatistics();
 | 
			
		||||
                dirty = false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void UpdateStatistics()
 | 
			
		||||
        {
 | 
			
		||||
            int max = 0;
 | 
			
		||||
            float maxf = 0;
 | 
			
		||||
            int maxindex = 0;
 | 
			
		||||
            string mostID = "Unknown";
 | 
			
		||||
 | 
			
		||||
            foreach (KeyValuePair<string,SexHistory> element in histories)
 | 
			
		||||
            {
 | 
			
		||||
                SexHistory h = element.Value;
 | 
			
		||||
 | 
			
		||||
                //find most sex partner
 | 
			
		||||
                if (max < h.TotalSexCount)
 | 
			
		||||
                {
 | 
			
		||||
                    max = h.TotalSexCount;
 | 
			
		||||
                    mostID = element.Key;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            max = 0;
 | 
			
		||||
            for (int i=0; i < sextypecount.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                float avgsat = sextypesat[i] / sextypecount[i];
 | 
			
		||||
                if (maxf < avgsat)
 | 
			
		||||
                {
 | 
			
		||||
                    maxf = avgsat;
 | 
			
		||||
                    maxindex = i;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            mostsatsextypecache = (xxx.rjwSextype)maxindex;
 | 
			
		||||
            mostsextypecache = (xxx.rjwSextype)sextypecount.FirstIndexOf(x => x == sextypecount.Max());
 | 
			
		||||
            mostpartnercache = mostID;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected bool VirginCheck()
 | 
			
		||||
        {
 | 
			
		||||
            Pawn pawn = parent as Pawn;
 | 
			
		||||
            if (pawn != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (pawn.IsVirgin()) return true;
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public class SexHistory : IExposable
 | 
			
		||||
    {
 | 
			
		||||
        protected Pawn partner;
 | 
			
		||||
        protected string namecache;
 | 
			
		||||
        protected int totalsexhad = 0;
 | 
			
		||||
        protected int raped = 0;
 | 
			
		||||
        protected int rapedme = 0;
 | 
			
		||||
        protected int orgasms = 0;
 | 
			
		||||
        protected xxx.rjwSextype bestsextype = xxx.rjwSextype.None;
 | 
			
		||||
        protected float bestsatisfaction = 0; 
 | 
			
		||||
       
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public string Label
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if (partner != null)
 | 
			
		||||
                {
 | 
			
		||||
                    namecache = partner.Label;
 | 
			
		||||
                    return namecache;
 | 
			
		||||
                }
 | 
			
		||||
                else return namecache;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public xxx.rjwSextype BestSextype
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return bestsextype;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public float BestSatisfaction
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return bestsatisfaction;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public int TotalSexCount
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return totalsexhad;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public SexHistory() { }
 | 
			
		||||
 | 
			
		||||
        public SexHistory(Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            partner = pawn; 
 | 
			
		||||
            namecache = pawn.Label;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public void ExposeData()
 | 
			
		||||
        {
 | 
			
		||||
            Scribe_References.Look(ref partner, "partner", true);
 | 
			
		||||
            Scribe_Values.Look(ref namecache, "namecache", namecache, true);
 | 
			
		||||
            Scribe_Values.Look(ref totalsexhad, "totalsexhad", totalsexhad, true);
 | 
			
		||||
            Scribe_Values.Look(ref raped, "raped", raped, true);
 | 
			
		||||
            Scribe_Values.Look(ref rapedme, "rapedme", rapedme, true);
 | 
			
		||||
            Scribe_Values.Look(ref orgasms, "orgasms", orgasms, true);
 | 
			
		||||
            Scribe_Values.Look(ref bestsextype, "bestsextype", bestsextype, true);
 | 
			
		||||
            Scribe_Values.Look(ref bestsatisfaction, "bestsatisfaction", bestsatisfaction, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RecordSex(SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            totalsexhad++;
 | 
			
		||||
            if (props.isRape)
 | 
			
		||||
            {
 | 
			
		||||
                if (partner == props.giver)
 | 
			
		||||
                {
 | 
			
		||||
                    rapedme++;
 | 
			
		||||
                }
 | 
			
		||||
                else if (partner == props.reciever)
 | 
			
		||||
                {
 | 
			
		||||
                    raped++;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RecordSatisfaction(SexProps props, float satisfaction)
 | 
			
		||||
        {
 | 
			
		||||
            if (satisfaction > bestsatisfaction)
 | 
			
		||||
            {
 | 
			
		||||
                orgasms++;
 | 
			
		||||
                bestsextype = props.sexType;
 | 
			
		||||
                bestsatisfaction = satisfaction;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										73
									
								
								RJWSexperience/RJWSexperience/SexHistory/HistoryUtility.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,73 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
using rjw;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
    [StaticConstructorOnStartup]
 | 
			
		||||
    public static class HistoryUtility
 | 
			
		||||
    {
 | 
			
		||||
        public static readonly Texture2D HistoryIcon = ContentFinder<Texture2D>.Get("UI/buttons/OpenStatsReport");
 | 
			
		||||
        public static readonly Texture2D UnknownPawn = ContentFinder<Texture2D>.Get("UI/Icon/UnknownPawn");
 | 
			
		||||
        public static readonly Texture2D FirstOverlay = ContentFinder<Texture2D>.Get("UI/Icon/FirstBG");
 | 
			
		||||
        public static readonly Texture2D Heart = ContentFinder<Texture2D>.Get("Things/Mote/Heart");
 | 
			
		||||
        public static readonly Texture2D Incest = ContentFinder<Texture2D>.Get("UI/Icon/Incest");
 | 
			
		||||
        public static readonly Texture2D Locked = ContentFinder<Texture2D>.Get("UI/Icon/RSLocked");
 | 
			
		||||
        public static readonly Texture2D Unlocked = ContentFinder<Texture2D>.Get("UI/Icon/RSUnlocked");
 | 
			
		||||
        public static Texture2D Slaanesh = SolidColorMaterials.NewSolidColorTexture(0.686f, 0.062f, 0.698f, 1.0f);
 | 
			
		||||
        public static Texture2D Khorne = SolidColorMaterials.NewSolidColorTexture(0.415f, 0.0f, 0.003f, 1.0f);
 | 
			
		||||
        public static Texture2D Tzeentch = SolidColorMaterials.NewSolidColorTexture(0.082f, 0.453f, 0.6f, 1.0f);
 | 
			
		||||
        public static Texture2D Nurgle = SolidColorMaterials.NewSolidColorTexture(0.6f, 0.83f, 0.35f, 1.0f);
 | 
			
		||||
        public static Texture2D Partners = SolidColorMaterials.NewSolidColorTexture(0.843f, 0.474f, 0.6f, 1.0f);
 | 
			
		||||
        public static Texture2D TotalSex = SolidColorMaterials.NewSolidColorTexture(0.878f, 0.674f, 0.411f, 1.0f);
 | 
			
		||||
        public static Texture2D Satisfaction = SolidColorMaterials.NewSolidColorTexture(0.325f, 0.815f, 0.729f,1.0f);
 | 
			
		||||
        public static readonly Color HistoryColor = new Color(0.9f,0.5f,0.5f);
 | 
			
		||||
 | 
			
		||||
        public static readonly Texture2D[] SextypeColor = new Texture2D[]
 | 
			
		||||
        {
 | 
			
		||||
            Texture2D.linearGrayTexture,    //None = 0,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.900f, 0.500f, 0.500f, 1.0f),    //Vaginal = 1,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.529f, 0.313f, 0.113f, 1.0f),    //Anal = 2,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.529f, 0.113f, 0.305f, 1.0f),    //Oral = 3,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.000f, 0.819f, 0.219f, 1.0f),    //Masturbation = 4,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.000f, 0.560f, 0.090f, 1.0f),    //DoublePenetration 
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.839f, 0.850f, 0.505f, 1.0f),    //Boobjob = 6,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.858f, 0.886f, 0.113f, 1.0f),    //Handjob = 7,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.752f, 0.780f, 0.000f, 1.0f),    //Footjob = 8,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.484f, 0.500f, 0.241f, 1.0f),    //Fingering = 9,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.913f, 0.909f, 0.909f, 1.0f),    //Scissoring = 10,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.588f, 0.576f, 0.431f, 1.0f),    //MutualMasturbation
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.741f, 0.000f, 0.682f, 1.0f),    //Fisting = 12,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.121f, 0.929f, 1.000f, 1.0f),    //MechImplant = 13,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.478f, 0.274f, 0.160f, 1.0f),    //Rimming = 14,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.819f, 0.301f, 0.552f, 1.0f),    //Fellatio = 15,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.819f, 0.301f, 0.552f, 1.0f),    //Cunnilingus = 16,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.529f, 0.113f, 0.305f, 1.0f),    //Sixtynine = 17
 | 
			
		||||
            Texture2D.linearGrayTexture,    //? = 18
 | 
			
		||||
            Texture2D.linearGrayTexture,    //? = 19
 | 
			
		||||
            Texture2D.linearGrayTexture    //? = 20
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        public static readonly Texture2D[] PassionBG = new Texture2D[]
 | 
			
		||||
        {
 | 
			
		||||
            
 | 
			
		||||
            Texture2D.blackTexture,    //None = 0,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(0.800f, 0.800f, 0.800f, 1.0f),    //Minor = 1,
 | 
			
		||||
            SolidColorMaterials.NewSolidColorTexture(1.000f, 0.875f, 0.000f, 1.0f)     //Major = 2,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        public static SexPartnerHistory GetPartnerHistory(this Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            return pawn.TryGetComp<SexPartnerHistory>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										638
									
								
								RJWSexperience/RJWSexperience/SexHistory/SexHistory.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,638 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
using rjw;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
    public class SexPartnerHistory : ThingComp
 | 
			
		||||
    {
 | 
			
		||||
        public SexPartnerHistory() { }
 | 
			
		||||
        public const int ARRLEN = 20;
 | 
			
		||||
 | 
			
		||||
        //protected List<SexHistory> histories = new List<SexHistory>();
 | 
			
		||||
        protected Dictionary<string, SexHistory> histories = new Dictionary<string, SexHistory>();
 | 
			
		||||
        protected string first = "";
 | 
			
		||||
        protected bool dirty = true;
 | 
			
		||||
        protected xxx.rjwSextype recentsex = xxx.rjwSextype.None;
 | 
			
		||||
        protected float recentsat = 0;
 | 
			
		||||
        protected string recentpartner = "";
 | 
			
		||||
        protected int[] sextypecount = new int[ARRLEN];
 | 
			
		||||
        protected float[] sextypesat = new float[ARRLEN];
 | 
			
		||||
        protected int virginstaken = 0;
 | 
			
		||||
        protected int incestuous = 0;
 | 
			
		||||
        protected int bestiality = 0;
 | 
			
		||||
        protected int corpsefuck = 0;
 | 
			
		||||
        protected int interspecies = 0;
 | 
			
		||||
 | 
			
		||||
        protected string mostpartnercache = "";
 | 
			
		||||
        protected xxx.rjwSextype mostsextypecache = xxx.rjwSextype.None;
 | 
			
		||||
        protected xxx.rjwSextype mostsatsextypecache = xxx.rjwSextype.None;
 | 
			
		||||
        protected xxx.rjwSextype bestsextypecache = xxx.rjwSextype.None;
 | 
			
		||||
        protected float bestsextypesatcache = 0;
 | 
			
		||||
        protected string bestpartnercache = "";
 | 
			
		||||
        protected int totalsexcache = 0;
 | 
			
		||||
        protected int totalrapedcache = 0;
 | 
			
		||||
        protected int totalbeenrapedcache = 0;
 | 
			
		||||
        protected ThingDef preferracecache = null;
 | 
			
		||||
        protected int preferracesexcountcache = 0;
 | 
			
		||||
        protected Pawn preferracepawncache = null;
 | 
			
		||||
        protected float avtsatcache = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private List<SexHistory> partnerlistcache;
 | 
			
		||||
        private List<int> sextypecountsave;
 | 
			
		||||
        private List<float> sextypesatsave;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public SexHistory GetFirstPartnerHistory
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                return histories.TryGetValue(first);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public SexHistory GetMostPartnerHistory
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                return histories.TryGetValue(mostpartnercache);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public xxx.rjwSextype MostSextype
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                return mostsextypecache;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public xxx.rjwSextype MostSatisfiedSex
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                return mostsatsextypecache;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public SexHistory GetRecentPartnersHistory
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return histories.TryGetValue(recentpartner);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public SexHistory GetBestSexPartnerHistory
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                SexHistory history = histories.TryGetValue(bestpartnercache);
 | 
			
		||||
                return history;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public float TotalSexHad
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                return totalsexcache;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public int VirginsTaken
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return virginstaken;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public List<SexHistory> PartnerList
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                return partnerlistcache;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public int PartnerCount
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if (histories == null) histories = new Dictionary<string, SexHistory>();
 | 
			
		||||
                return histories.Count;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public int IncestuousCount
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return incestuous;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public int RapedCount
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                return totalrapedcache;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public int BeenRapedCount
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                return totalbeenrapedcache;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public ThingDef PreferRace
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                return preferracecache;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public int PreferRaceSexCount
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                return preferracesexcountcache;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public int BestialityCount
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return bestiality;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public int CorpseFuckCount
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return corpsefuck;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public int InterspeciesCount
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return interspecies;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public float AVGSat
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                Update();
 | 
			
		||||
                if (totalsexcache == 0) return 0;
 | 
			
		||||
                return sextypesat.Sum() / totalsexcache;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public Texture GetPreferRaceIcon(Vector2 size)
 | 
			
		||||
        {
 | 
			
		||||
            Update();
 | 
			
		||||
            if (preferracepawncache != null) return PortraitsCache.Get(preferracepawncache, size, Rot4.South, default, 1, true, true, false, false);
 | 
			
		||||
            else return HistoryUtility.UnknownPawn;
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public float GetBestSextype(out xxx.rjwSextype sextype)
 | 
			
		||||
        {
 | 
			
		||||
            if (dirty) Update();
 | 
			
		||||
            sextype = bestsextypecache;
 | 
			
		||||
            return bestsextypesatcache;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public float GetRecentSextype(out xxx.rjwSextype sextype)
 | 
			
		||||
        {
 | 
			
		||||
            if (dirty) Update();
 | 
			
		||||
            sextype = recentsex;
 | 
			
		||||
            return recentsat;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public SexHistory this[Pawn pawn]
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return histories.TryGetValue(pawn.ThingID);
 | 
			
		||||
            }
 | 
			
		||||
        } 
 | 
			
		||||
 | 
			
		||||
        public float GetAVGSat(xxx.rjwSextype sextype)
 | 
			
		||||
        {
 | 
			
		||||
            int index = (int)sextype;
 | 
			
		||||
            return GetAVGSat(index);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public float GetAVGSat(int index)
 | 
			
		||||
        {
 | 
			
		||||
            float res = sextypesat[index] / sextypecount[index];
 | 
			
		||||
            return float.IsNaN(res) ? 0f : res;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public int GetSexCount(int index)
 | 
			
		||||
        {
 | 
			
		||||
            return sextypecount[index];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public override void PostExposeData()
 | 
			
		||||
        {
 | 
			
		||||
            if (Scribe.mode == LoadSaveMode.Saving)
 | 
			
		||||
            {
 | 
			
		||||
                sextypecountsave = sextypecount.ToList();
 | 
			
		||||
                sextypesatsave = sextypesat.ToList();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Scribe_Collections.Look(ref histories, "histories", LookMode.Value, LookMode.Deep);
 | 
			
		||||
            Scribe_Values.Look(ref first, "first", "", true);
 | 
			
		||||
            Scribe_Values.Look(ref recentsex, "recentsex", recentsex, true);
 | 
			
		||||
            Scribe_Values.Look(ref recentsat, "recentsat", recentsat, true);
 | 
			
		||||
            Scribe_Values.Look(ref recentpartner, "recentpartner", recentpartner, true);
 | 
			
		||||
            Scribe_Values.Look(ref virginstaken, "virginstaken", virginstaken, true);
 | 
			
		||||
            Scribe_Values.Look(ref incestuous, "incestous", incestuous, true);
 | 
			
		||||
            Scribe_Values.Look(ref bestiality, "bestiality", bestiality, true);
 | 
			
		||||
            Scribe_Values.Look(ref corpsefuck, "corpsefuck", corpsefuck, true);
 | 
			
		||||
            Scribe_Values.Look(ref interspecies, "interspecies", interspecies, true);
 | 
			
		||||
            Scribe_Collections.Look(ref sextypecountsave, "sextypecountsave", LookMode.Value);
 | 
			
		||||
            Scribe_Collections.Look(ref sextypesatsave, "sextypesatsave", LookMode.Value);
 | 
			
		||||
            //Scribe_Values.Look(ref sextypecount, "sextypecount", new int[ARRLEN], true); // not work
 | 
			
		||||
            //Scribe_Values.Look(ref sextypesat, "sextypesat", new float[ARRLEN], true);
 | 
			
		||||
            if (Scribe.mode == LoadSaveMode.LoadingVars)
 | 
			
		||||
            {
 | 
			
		||||
                sextypecount = sextypecountsave?.ToArray() ?? new int[ARRLEN];
 | 
			
		||||
                sextypesat = sextypesatsave?.ToArray() ?? new float[ARRLEN];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (histories == null) histories = new Dictionary<string, SexHistory>();
 | 
			
		||||
 | 
			
		||||
            base.PostExposeData();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RecordHistory(Pawn partner, SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            Pawn pawn = parent as Pawn;
 | 
			
		||||
            TryAddHistory(partner);
 | 
			
		||||
            RecordFirst(partner, props);
 | 
			
		||||
            recentpartner = partner.ThingID;
 | 
			
		||||
            SexHistory history = histories[partner.ThingID];
 | 
			
		||||
            history?.RecordSex(props);
 | 
			
		||||
            recentsex = props.sexType;
 | 
			
		||||
            sextypecount[(int)props.sexType]++;
 | 
			
		||||
            if (partner.IsIncest(pawn)) incestuous++;
 | 
			
		||||
            if (partner.Dead) corpsefuck++;
 | 
			
		||||
            if (props.IsBestiality()) bestiality++;
 | 
			
		||||
            else if (pawn.def != partner.def) interspecies++;
 | 
			
		||||
            dirty = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RecordSatisfactionHistory(Pawn partner, SexProps props, float satisfaction)
 | 
			
		||||
        {
 | 
			
		||||
            TryAddHistory(partner);
 | 
			
		||||
            RecordFirst(partner, props);
 | 
			
		||||
            SexHistory history = histories[partner.ThingID];
 | 
			
		||||
            history?.RecordSatisfaction(props, satisfaction);
 | 
			
		||||
            recentsat = satisfaction;
 | 
			
		||||
            sextypesat[(int)props.sexType] += satisfaction;
 | 
			
		||||
            dirty = true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected bool TryAddHistory(Pawn partner)
 | 
			
		||||
        {
 | 
			
		||||
            if (!histories.ContainsKey(partner.ThingID))
 | 
			
		||||
            {
 | 
			
		||||
                SexHistory newhistory = new SexHistory(partner,partner.IsIncest(parent as Pawn));
 | 
			
		||||
                histories.Add(partner.ThingID, newhistory);
 | 
			
		||||
                Pawn pawn = parent as Pawn;
 | 
			
		||||
                if (pawn != null)
 | 
			
		||||
                {
 | 
			
		||||
                    pawn.records.AddTo(VariousDefOf.SexPartnerCount, 1);
 | 
			
		||||
                }
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RecordFirst(Pawn partner, SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            if (VirginCheck() && props.sexType == xxx.rjwSextype.Vaginal)
 | 
			
		||||
            {
 | 
			
		||||
                TryAddHistory(partner);
 | 
			
		||||
                first = partner.ThingID;
 | 
			
		||||
                SexPartnerHistory history = partner.GetPartnerHistory();
 | 
			
		||||
                if (history != null)
 | 
			
		||||
                {
 | 
			
		||||
                    history.TakeSomeonesVirgin(parent as Pawn);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void TakeSomeonesVirgin(Pawn partner)
 | 
			
		||||
        {
 | 
			
		||||
            TryAddHistory(partner);
 | 
			
		||||
            SexHistory history = histories[partner.ThingID];
 | 
			
		||||
            if (history != null) history.TookVirgin();
 | 
			
		||||
            virginstaken++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void Update()
 | 
			
		||||
        {
 | 
			
		||||
            if (dirty)
 | 
			
		||||
            {
 | 
			
		||||
                UpdateStatistics();
 | 
			
		||||
                UpdateBestSex();
 | 
			
		||||
                UpdatePartnerList();
 | 
			
		||||
                dirty = false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void UpdateStatistics()
 | 
			
		||||
        {
 | 
			
		||||
            int max = 0;
 | 
			
		||||
            float maxsat = 0;
 | 
			
		||||
            float maxf = 0;
 | 
			
		||||
            int maxindex = 0;
 | 
			
		||||
            string mostID = Keyed.Unknown;
 | 
			
		||||
            string bestID = Keyed.Unknown;
 | 
			
		||||
            totalsexcache = 0;
 | 
			
		||||
            totalrapedcache = 0;
 | 
			
		||||
            totalbeenrapedcache = 0;
 | 
			
		||||
            Dictionary<ThingDef, int> racetotalsat = new Dictionary<ThingDef, int>();
 | 
			
		||||
            List<Pawn> allpartners = new List<Pawn>();
 | 
			
		||||
 | 
			
		||||
            foreach (KeyValuePair<string,SexHistory> element in histories)
 | 
			
		||||
            {
 | 
			
		||||
                SexHistory h = element.Value;
 | 
			
		||||
 | 
			
		||||
                //find most sex partner
 | 
			
		||||
                if (max < h.TotalSexCount)
 | 
			
		||||
                {
 | 
			
		||||
                    max = h.TotalSexCount;
 | 
			
		||||
                    mostID = element.Key;
 | 
			
		||||
                }
 | 
			
		||||
                if (maxsat < h.BestSatisfaction)
 | 
			
		||||
                {
 | 
			
		||||
                    maxsat = h.BestSatisfaction;
 | 
			
		||||
                    bestID = element.Key;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (h.Partner != null)
 | 
			
		||||
                {
 | 
			
		||||
                    Pawn partner = h.Partner;
 | 
			
		||||
                    allpartners.Add(partner);
 | 
			
		||||
                    if (racetotalsat.ContainsKey(partner.def))
 | 
			
		||||
                    {
 | 
			
		||||
                        racetotalsat[partner.def] += h.TotalSexCount - h.RapedMe;
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        racetotalsat.Add(partner.def, h.TotalSexCount - h.RapedMe);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                totalsexcache += h.TotalSexCount;
 | 
			
		||||
                totalrapedcache += h.Raped;
 | 
			
		||||
                totalbeenrapedcache += h.RapedMe;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!racetotalsat.NullOrEmpty())
 | 
			
		||||
            {
 | 
			
		||||
                KeyValuePair<ThingDef, int> prefer = racetotalsat.MaxBy(x => x.Value);
 | 
			
		||||
                preferracecache = prefer.Key;
 | 
			
		||||
                preferracesexcountcache = prefer.Value;
 | 
			
		||||
                preferracepawncache = allpartners.FirstOrDefault(x => x.def == preferracecache);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            max = 0;
 | 
			
		||||
            for (int i=0; i < sextypecount.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                float avgsat = sextypesat[i] / sextypecount[i];
 | 
			
		||||
                if (maxf < avgsat)
 | 
			
		||||
                {
 | 
			
		||||
                    maxf = avgsat;
 | 
			
		||||
                    maxindex = i;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            mostsatsextypecache = (xxx.rjwSextype)maxindex;
 | 
			
		||||
            mostsextypecache = (xxx.rjwSextype)sextypecount.FirstIndexOf(x => x == sextypecount.Max());
 | 
			
		||||
            mostpartnercache = mostID;
 | 
			
		||||
            bestpartnercache = bestID;
 | 
			
		||||
 | 
			
		||||
            racetotalsat.Clear();
 | 
			
		||||
            allpartners.Clear();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void UpdateBestSex()
 | 
			
		||||
        {
 | 
			
		||||
            int bestindex = 0;
 | 
			
		||||
            float bestsat = 0;
 | 
			
		||||
            float avgsat;
 | 
			
		||||
            for(int i=0; i< sextypecount.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                avgsat = sextypesat[i] / sextypecount[i];
 | 
			
		||||
                if (bestsat < avgsat)
 | 
			
		||||
                {
 | 
			
		||||
                    bestindex = i;
 | 
			
		||||
                    bestsat = avgsat;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            bestsextypecache = (xxx.rjwSextype)bestindex;
 | 
			
		||||
            bestsextypesatcache = bestsat;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void UpdatePartnerList()
 | 
			
		||||
        {
 | 
			
		||||
            if (partnerlistcache == null) partnerlistcache = new List<SexHistory>();
 | 
			
		||||
            partnerlistcache.Clear();
 | 
			
		||||
            if (!histories.NullOrEmpty()) foreach (SexHistory history in histories.Values)
 | 
			
		||||
                {
 | 
			
		||||
                    if (history != null) partnerlistcache.Add(history);
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected bool VirginCheck()
 | 
			
		||||
        {
 | 
			
		||||
            if (histories.TryGetValue(first) != null) return false;
 | 
			
		||||
 | 
			
		||||
            Pawn pawn = parent as Pawn;
 | 
			
		||||
            if (pawn != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (pawn.IsVirgin()) return true;
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public class SexHistory : IExposable
 | 
			
		||||
    {
 | 
			
		||||
        protected Pawn partner = null;
 | 
			
		||||
        protected string namecache;
 | 
			
		||||
        protected int totalsexhad = 0;
 | 
			
		||||
        protected int raped = 0;
 | 
			
		||||
        protected int rapedme = 0;
 | 
			
		||||
        protected int orgasms = 0;
 | 
			
		||||
        protected xxx.rjwSextype bestsextype = xxx.rjwSextype.None;
 | 
			
		||||
        protected float bestsatisfaction = 0;
 | 
			
		||||
        protected bool itookvirgin = false;
 | 
			
		||||
        protected bool incest = false;
 | 
			
		||||
 | 
			
		||||
        public string Label
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                if (partner != null)
 | 
			
		||||
                {
 | 
			
		||||
                    namecache = partner.Label;
 | 
			
		||||
                    return namecache;
 | 
			
		||||
                }
 | 
			
		||||
                else return namecache;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public xxx.rjwSextype BestSextype
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return bestsextype;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public float BestSatisfaction
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return bestsatisfaction;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public int TotalSexCount
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return totalsexhad;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public Pawn Partner
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return partner;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public string RapeInfo
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                string res = "";
 | 
			
		||||
                if (raped > 0) res += Keyed.RS_Raped + raped + " ";
 | 
			
		||||
                if (rapedme > 0) res += Keyed.RS_RapedMe + rapedme + " ";
 | 
			
		||||
                return res;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public int OrgasmCount
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return orgasms;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public bool IamFirst
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return itookvirgin;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public bool Incest
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return incest;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public int Raped
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return raped;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public int RapedMe
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                return rapedme;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public SexHistory() { }
 | 
			
		||||
 | 
			
		||||
        public SexHistory(Pawn pawn, bool incest = false)
 | 
			
		||||
        {
 | 
			
		||||
            this.partner = pawn; 
 | 
			
		||||
            this.namecache = pawn.Label;
 | 
			
		||||
            this.incest = incest;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public void ExposeData()
 | 
			
		||||
        {
 | 
			
		||||
            Scribe_References.Look(ref partner, "partner", true);
 | 
			
		||||
            Scribe_Values.Look(ref namecache, "namecache", namecache, true);
 | 
			
		||||
            Scribe_Values.Look(ref totalsexhad, "totalsexhad", totalsexhad, true);
 | 
			
		||||
            Scribe_Values.Look(ref raped, "raped", raped, true);
 | 
			
		||||
            Scribe_Values.Look(ref rapedme, "rapedme", rapedme, true);
 | 
			
		||||
            Scribe_Values.Look(ref orgasms, "orgasms", orgasms, true);
 | 
			
		||||
            Scribe_Values.Look(ref bestsextype, "bestsextype", bestsextype, true);
 | 
			
		||||
            Scribe_Values.Look(ref bestsatisfaction, "bestsatisfaction", bestsatisfaction, true);
 | 
			
		||||
            Scribe_Values.Look(ref itookvirgin, "itookvirgin", itookvirgin, true);
 | 
			
		||||
            Scribe_Values.Look(ref incest, "incest", incest, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RecordSex(SexProps props)
 | 
			
		||||
        {
 | 
			
		||||
            totalsexhad++;
 | 
			
		||||
            if (props.isRape)
 | 
			
		||||
            {
 | 
			
		||||
                if (partner == props.giver)
 | 
			
		||||
                {
 | 
			
		||||
                    rapedme++;
 | 
			
		||||
                }
 | 
			
		||||
                else if (partner == props.reciever)
 | 
			
		||||
                {
 | 
			
		||||
                    raped++;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void RecordSatisfaction(SexProps props, float satisfaction)
 | 
			
		||||
        {
 | 
			
		||||
            if (satisfaction > bestsatisfaction)
 | 
			
		||||
            {
 | 
			
		||||
                orgasms++;
 | 
			
		||||
                bestsextype = props.sexType;
 | 
			
		||||
                bestsatisfaction = satisfaction;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void TookVirgin()
 | 
			
		||||
        {
 | 
			
		||||
            itookvirgin = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								RJWSexperience/RJWSexperience/Thought_Opinionbased.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// ThoughtDef using opinion
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class ThoughtDef_Opinionbased : ThoughtDef
 | 
			
		||||
    {
 | 
			
		||||
        public List<float> minimumValueforStage = new List<float>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Thought class using record.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class Thought_Opinionbased : Thought_Memory
 | 
			
		||||
    {
 | 
			
		||||
        protected ThoughtDef_Opinionbased Def => (ThoughtDef_Opinionbased)def;
 | 
			
		||||
        protected List<float> minimumValueforStage => Def.minimumValueforStage;
 | 
			
		||||
 | 
			
		||||
        public override int CurStageIndex
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                float value = 0f;
 | 
			
		||||
                if (otherPawn != null) value = pawn.relations?.OpinionOf(otherPawn) ?? 0f;
 | 
			
		||||
                for (int i = minimumValueforStage.Count - 1; i > 0; i--)
 | 
			
		||||
                {
 | 
			
		||||
                    if (minimumValueforStage[i] < value) return i;
 | 
			
		||||
                }
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -45,9 +45,6 @@ namespace RJWSexperience
 | 
			
		|||
 | 
			
		||||
    public class Thought_AteCum : Thought_Recordbased
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        protected int recordIncrement = 1;
 | 
			
		||||
 | 
			
		||||
        public override int CurStageIndex
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
| 
						 | 
				
			
			@ -60,21 +57,13 @@ namespace RJWSexperience
 | 
			
		|||
        public override void ExposeData()
 | 
			
		||||
        {
 | 
			
		||||
            base.ExposeData();
 | 
			
		||||
            Scribe_Values.Look(ref recordIncrement, "recordIncrement", recordIncrement, true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //There is no direct way to modify custom records via ingestion. So i increase it from thought.
 | 
			
		||||
        public override void ThoughtInterval()
 | 
			
		||||
        {
 | 
			
		||||
            base.ThoughtInterval();
 | 
			
		||||
            if (recordIncrement >= 1)
 | 
			
		||||
            {
 | 
			
		||||
                recordIncrement--;
 | 
			
		||||
                pawn.records.AddTo(VariousDefOf.NumofEatenCum, 1);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override bool TryMergeWithExistingMemory(out bool showBubble)
 | 
			
		||||
| 
						 | 
				
			
			@ -97,13 +86,11 @@ namespace RJWSexperience
 | 
			
		|||
        public override void Init()
 | 
			
		||||
        {
 | 
			
		||||
            base.Init();
 | 
			
		||||
            recordIncrement = 1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected virtual void Merged()
 | 
			
		||||
        {
 | 
			
		||||
            age = 0;
 | 
			
		||||
            recordIncrement += 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										89
									
								
								RJWSexperience/RJWSexperience/UI/RJWUIUtility.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,89 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Verse;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
using rjw;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience.UI
 | 
			
		||||
{
 | 
			
		||||
    public static class RJWUIUtility
 | 
			
		||||
	{
 | 
			
		||||
		public const float FONTHEIGHT = 22f;
 | 
			
		||||
		public const float CARDHEIGHT = 110f;
 | 
			
		||||
		public const float LISTPAWNSIZE = 100f;
 | 
			
		||||
		public const float BASESAT = 0.40f;
 | 
			
		||||
		public const float ICONSIZE = 30f;
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		public static void DrawQuirk(this Rect rect, Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            List<Quirk> quirks = Quirk.All.FindAll(x => pawn.Has(x));
 | 
			
		||||
            string quirkstr = quirks.Select(x => x.Key).ToCommaList();
 | 
			
		||||
			string tooltip = "";
 | 
			
		||||
 | 
			
		||||
			Widgets.Label(rect, "Quirks".Translate() + quirkstr);
 | 
			
		||||
 | 
			
		||||
			if (Mouse.IsOver(rect))
 | 
			
		||||
            {
 | 
			
		||||
				if (quirks.NullOrEmpty())
 | 
			
		||||
				{
 | 
			
		||||
					tooltip = "NoQuirks".Translate();
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					StringBuilder stringBuilder = new StringBuilder();
 | 
			
		||||
					foreach (var q in quirks)
 | 
			
		||||
					{
 | 
			
		||||
						stringBuilder.AppendLine(q.Key.Colorize(Color.yellow));
 | 
			
		||||
						stringBuilder.AppendLine(q.LocaliztionKey.Translate(pawn.Named("pawn")).AdjustedFor(pawn).Resolve());
 | 
			
		||||
						stringBuilder.AppendLine("");
 | 
			
		||||
					}
 | 
			
		||||
					tooltip = stringBuilder.ToString().TrimEndNewlines();
 | 
			
		||||
				}
 | 
			
		||||
				Widgets.DrawHighlight(rect);
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			TooltipHandler.TipRegion(rect, tooltip);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		public static void DrawSexuality(this Rect rect, CompRJW comp)
 | 
			
		||||
        {
 | 
			
		||||
			if (comp != null)
 | 
			
		||||
            {
 | 
			
		||||
				string sexuality = Keyed.Sexuality[(int)comp.orientation];
 | 
			
		||||
				Widgets.Label(rect, Keyed.RS_Sexuality + ": " + sexuality);
 | 
			
		||||
				Widgets.DrawHighlightIfMouseover(rect);
 | 
			
		||||
			}
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		public static string GetRelationsString(this Pawn pawn, Pawn otherpawn)
 | 
			
		||||
        {
 | 
			
		||||
			if (otherpawn != null)
 | 
			
		||||
            {
 | 
			
		||||
				IEnumerable<PawnRelationDef> relations = pawn.GetRelations(otherpawn);
 | 
			
		||||
				if (!relations.EnumerableNullOrEmpty()) return relations.Select(x => x.GetGenderSpecificLabel(otherpawn)).ToCommaList().CapitalizeFirst();
 | 
			
		||||
            }
 | 
			
		||||
			return "";
 | 
			
		||||
        }
 | 
			
		||||
		
 | 
			
		||||
		public static void DrawBorder(this Rect rect, Texture border, float thickness = 1f)
 | 
			
		||||
        {
 | 
			
		||||
			GUI.DrawTexture(new Rect(rect.x,rect.y,rect.width, thickness), border);
 | 
			
		||||
			GUI.DrawTexture(new Rect(rect.x+rect.width-thickness,rect.y, thickness, rect.height), border);
 | 
			
		||||
			GUI.DrawTexture(new Rect(rect.x,rect.y+rect.height - thickness,rect.width, thickness), border);
 | 
			
		||||
			GUI.DrawTexture(new Rect(rect.x, rect.y, thickness, rect.height), border);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static string GetStatExplanation(Pawn pawn, StatDef stat, float val)
 | 
			
		||||
        {
 | 
			
		||||
			return stat.description + "\n" +
 | 
			
		||||
				stat.Worker.GetExplanationFull(StatRequest.For(pawn), ToStringNumberSense.Undefined, val);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										608
									
								
								RJWSexperience/RJWSexperience/UI/SexStatus.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,608 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
using Verse;
 | 
			
		||||
using Verse.Sound;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using rjw;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace RJWSexperience.UI
 | 
			
		||||
{
 | 
			
		||||
    public class SexStatusWindow : Window
 | 
			
		||||
    {
 | 
			
		||||
        public const float FONTHEIGHT = RJWUIUtility.FONTHEIGHT;
 | 
			
		||||
        public const float CARDHEIGHT = RJWUIUtility.CARDHEIGHT;
 | 
			
		||||
        public const float LISTPAWNSIZE = RJWUIUtility.LISTPAWNSIZE;
 | 
			
		||||
        public const float BASESAT = RJWUIUtility.BASESAT;
 | 
			
		||||
        public const float ICONSIZE = RJWUIUtility.ICONSIZE;
 | 
			
		||||
 | 
			
		||||
        public static readonly int[] Sextype =
 | 
			
		||||
        {
 | 
			
		||||
            (int)xxx.rjwSextype.Vaginal,
 | 
			
		||||
            (int)xxx.rjwSextype.Anal,
 | 
			
		||||
            (int)xxx.rjwSextype.Oral,
 | 
			
		||||
            (int)xxx.rjwSextype.Fellatio,
 | 
			
		||||
            (int)xxx.rjwSextype.Cunnilingus,
 | 
			
		||||
            (int)xxx.rjwSextype.DoublePenetration,
 | 
			
		||||
            (int)xxx.rjwSextype.Boobjob,
 | 
			
		||||
            (int)xxx.rjwSextype.Handjob,
 | 
			
		||||
            (int)xxx.rjwSextype.Footjob,
 | 
			
		||||
            (int)xxx.rjwSextype.Fingering,
 | 
			
		||||
            (int)xxx.rjwSextype.Scissoring,
 | 
			
		||||
            (int)xxx.rjwSextype.MutualMasturbation,
 | 
			
		||||
            (int)xxx.rjwSextype.Fisting,
 | 
			
		||||
            (int)xxx.rjwSextype.Rimming,
 | 
			
		||||
            (int)xxx.rjwSextype.Sixtynine
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        protected Pawn pawn;
 | 
			
		||||
        protected SexHistory selectedPawn;
 | 
			
		||||
        protected SexPartnerHistory history;
 | 
			
		||||
        protected CompRJW rjwcomp;
 | 
			
		||||
 | 
			
		||||
        private static GUIStyleState fontstylestate = new GUIStyleState() { textColor = Color.white };
 | 
			
		||||
        private static GUIStyleState boxstylestate = GUI.skin.textArea.normal;
 | 
			
		||||
        private static GUIStyleState buttonstylestate = GUI.skin.button.normal;
 | 
			
		||||
        private static GUIStyle fontstylecenter = new GUIStyle() { alignment = TextAnchor.MiddleCenter, normal = fontstylestate };
 | 
			
		||||
        private static GUIStyle fontstyleright = new GUIStyle() { alignment = TextAnchor.MiddleRight, normal = fontstylestate };
 | 
			
		||||
        private static GUIStyle fontstyleleft = new GUIStyle() { alignment = TextAnchor.MiddleLeft, normal = fontstylestate };
 | 
			
		||||
        private static GUIStyle boxstyle = new GUIStyle(GUI.skin.textArea) { hover = boxstylestate, onHover = boxstylestate, onNormal = boxstylestate };
 | 
			
		||||
        private static GUIStyle buttonstyle = new GUIStyle(GUI.skin.button) { hover = buttonstylestate, onHover = buttonstylestate, onNormal = buttonstylestate };
 | 
			
		||||
 | 
			
		||||
        private static Vector2 pos;
 | 
			
		||||
        private static Vector2 scroll;
 | 
			
		||||
        private static bool opened;
 | 
			
		||||
 | 
			
		||||
        public SexStatusWindow(Pawn pawn, SexPartnerHistory history)
 | 
			
		||||
        {
 | 
			
		||||
            this.pawn = pawn;
 | 
			
		||||
            this.history = history;
 | 
			
		||||
            this.selectedPawn = null;
 | 
			
		||||
            this.rjwcomp = pawn.TryGetComp<CompRJW>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override void SetInitialSizeAndPosition()
 | 
			
		||||
        {
 | 
			
		||||
            Vector2 initialSize = InitialSize;
 | 
			
		||||
            if (!opened)
 | 
			
		||||
            {
 | 
			
		||||
                windowRect = new Rect((Verse.UI.screenWidth - initialSize.x) / 2f, ((float)Verse.UI.screenHeight - initialSize.y) / 2f, initialSize.x, initialSize.y);
 | 
			
		||||
                opened = true;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                windowRect = new Rect(pos, initialSize);
 | 
			
		||||
            }
 | 
			
		||||
            windowRect = windowRect.Rounded();
 | 
			
		||||
            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public override Vector2 InitialSize
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
            {
 | 
			
		||||
                float width = 900f;
 | 
			
		||||
                float height = 600f;
 | 
			
		||||
                soundClose = SoundDefOf.CommsWindow_Close;
 | 
			
		||||
                absorbInputAroundWindow = false;
 | 
			
		||||
                forcePause = false;
 | 
			
		||||
                preventCameraMotion = false;
 | 
			
		||||
                draggable = true;
 | 
			
		||||
                doCloseX = true;
 | 
			
		||||
                return new Vector2(width, height);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public override void DoWindowContents(Rect inRect)
 | 
			
		||||
        {
 | 
			
		||||
            pos = windowRect.position;
 | 
			
		||||
            if (!Configurations.SelectionLocked)
 | 
			
		||||
            {
 | 
			
		||||
                List<Pawn> selected = Find.Selector.SelectedPawns;
 | 
			
		||||
                if (selected.Count == 1)
 | 
			
		||||
                {
 | 
			
		||||
                    Pawn p = selected.First();
 | 
			
		||||
                    if (p != pawn)
 | 
			
		||||
                    {
 | 
			
		||||
                        SexPartnerHistory h = p.GetPartnerHistory();
 | 
			
		||||
                        if (h != null) ChangePawn(p, h);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            DrawSexStatus(inRect,history);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void ToggleWindow(Pawn pawn, SexPartnerHistory history)
 | 
			
		||||
        {
 | 
			
		||||
            SexStatusWindow window = (SexStatusWindow)Find.WindowStack.Windows.FirstOrDefault(x => x.GetType() == typeof(SexStatusWindow));
 | 
			
		||||
            if (window != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (window.pawn != pawn)
 | 
			
		||||
                {
 | 
			
		||||
                    SoundDefOf.TabOpen.PlayOneShotOnCamera();
 | 
			
		||||
                    window.ChangePawn(pawn, history);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                Find.WindowStack.Add(new SexStatusWindow(pawn, history));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void ChangePawn(Pawn pawn, SexPartnerHistory history)
 | 
			
		||||
        {
 | 
			
		||||
            List<Pawn> selected = Find.Selector.SelectedPawns;
 | 
			
		||||
            if (!selected.NullOrEmpty()) foreach(Pawn p in selected)
 | 
			
		||||
                {
 | 
			
		||||
                    Find.Selector.Deselect(p);
 | 
			
		||||
                }
 | 
			
		||||
            this.pawn = pawn;
 | 
			
		||||
            this.history = history;
 | 
			
		||||
            this.selectedPawn = null;
 | 
			
		||||
            this.rjwcomp = pawn.TryGetComp<CompRJW>();
 | 
			
		||||
            if (!pawn.DestroyedOrNull() && Find.CurrentMap == pawn.Map) Find.Selector.Select(pawn);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Main contents
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected void DrawSexStatus(Rect mainrect, SexPartnerHistory history)
 | 
			
		||||
        {
 | 
			
		||||
            float sectionwidth = mainrect.width / 3;
 | 
			
		||||
 | 
			
		||||
            Rect leftRect = new Rect(mainrect.x, mainrect.y, sectionwidth, mainrect.height);
 | 
			
		||||
            Rect centerRect = new Rect(mainrect.x + sectionwidth, mainrect.y, sectionwidth, mainrect.height);
 | 
			
		||||
            Rect rightRect = new Rect(mainrect.x + sectionwidth * 2, mainrect.y, sectionwidth, mainrect.height);
 | 
			
		||||
 | 
			
		||||
            if (history != null)
 | 
			
		||||
            {
 | 
			
		||||
                //Left section
 | 
			
		||||
                DrawBaseSexInfoLeft(leftRect.ContractedBy(4f));
 | 
			
		||||
 | 
			
		||||
                //Center section
 | 
			
		||||
                DrawBaseSexInfoCenter(centerRect.ContractedBy(4f),history.parent as Pawn);
 | 
			
		||||
 | 
			
		||||
                //Right section
 | 
			
		||||
                DrawBaseSexInfoRight(rightRect.ContractedBy(4f));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void DrawInfoWithPortrait(Rect rect, SexHistory history, string tooltip = "")
 | 
			
		||||
        {
 | 
			
		||||
            Widgets.DrawMenuSection(rect);
 | 
			
		||||
            string str = tooltip;
 | 
			
		||||
            Rect portraitRect = new Rect(rect.x, rect.y, rect.height - FONTHEIGHT, rect.height - FONTHEIGHT);
 | 
			
		||||
            Rect nameRect = new Rect(rect.x + portraitRect.width, rect.y, rect.width - portraitRect.width, FONTHEIGHT);
 | 
			
		||||
            Rect sexinfoRect = new Rect(rect.x + portraitRect.width, rect.y + FONTHEIGHT, rect.width - portraitRect.width, FONTHEIGHT);
 | 
			
		||||
            Rect sexinfoRect2 = new Rect(rect.x + portraitRect.width, rect.y + FONTHEIGHT * 2, rect.width - portraitRect.width, FONTHEIGHT);
 | 
			
		||||
            Rect bestsexRect = new Rect(rect.x + 2f, rect.y + FONTHEIGHT * 3, rect.width - 4f, FONTHEIGHT - 2f);
 | 
			
		||||
 | 
			
		||||
            if (history != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (history.Incest) str += " - " + Keyed.Incest;
 | 
			
		||||
                Pawn partner = history.Partner;
 | 
			
		||||
                DrawPawn(portraitRect, history);
 | 
			
		||||
                Widgets.DrawHighlightIfMouseover(portraitRect);
 | 
			
		||||
                if (Widgets.ButtonInvisible(portraitRect))
 | 
			
		||||
                {
 | 
			
		||||
                    SexPartnerHistory pawnhistory = partner?.GetPartnerHistory();
 | 
			
		||||
                    if (pawnhistory != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        ChangePawn(partner, pawnhistory);
 | 
			
		||||
                        SoundDefOf.Click.PlayOneShotOnCamera();
 | 
			
		||||
                    }
 | 
			
		||||
                    else SoundDefOf.ClickReject.PlayOneShotOnCamera();
 | 
			
		||||
                }
 | 
			
		||||
                GUI.Label(nameRect, partner?.Name?.ToStringFull ?? history.Label.CapitalizeFirst(), fontstyleleft);
 | 
			
		||||
                GUI.Label(sexinfoRect, Keyed.RS_Sex_Count + history.TotalSexCount + " " + history.RapeInfo, fontstyleleft);
 | 
			
		||||
                GUI.Label(sexinfoRect2, Keyed.RS_Orgasms + history.OrgasmCount, fontstyleleft);
 | 
			
		||||
                GUI.Label(sexinfoRect2, pawn.GetRelationsString(partner) + " ", fontstyleright);
 | 
			
		||||
                float p = history.BestSatisfaction / BASESAT;
 | 
			
		||||
                FillableBarLabeled(bestsexRect,String.Format(Keyed.RS_Best_Sextype+": {0}", Keyed.Sextype[(int)history.BestSextype]), p / 2, HistoryUtility.SextypeColor[(int)history.BestSextype], Texture2D.blackTexture, null, String.Format("{0:P2}", p));
 | 
			
		||||
 | 
			
		||||
                if (history.IamFirst) str += "\n" + Keyed.RS_LostVirgin(history.Label, pawn.LabelShort);
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
                TooltipHandler.TipRegion(rect, str);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                Widgets.DrawTextureFitted(portraitRect, HistoryUtility.UnknownPawn, 1.0f);
 | 
			
		||||
                Widgets.Label(nameRect, Keyed.Unknown);
 | 
			
		||||
                Widgets.Label(sexinfoRect, Keyed.RS_Sex_Count + "?");
 | 
			
		||||
                Widgets.Label(sexinfoRect2, Keyed.RS_Orgasms+"?");
 | 
			
		||||
                FillableBarLabeled(bestsexRect,String.Format(Keyed .RS_Best_Sextype + ": {0}", Keyed.Sextype[(int)xxx.rjwSextype.None]), 0, Texture2D.linearGrayTexture, Texture2D.blackTexture);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void DrawSexInfoCard(Rect rect, SexHistory history, string label, string tooltip)
 | 
			
		||||
        {
 | 
			
		||||
            Rect labelRect = new Rect(rect.x, rect.y, rect.width, FONTHEIGHT);
 | 
			
		||||
            Rect infoRect = new Rect(rect.x, rect.y + FONTHEIGHT, rect.width, rect.height - FONTHEIGHT);
 | 
			
		||||
            GUI.Label(labelRect, label, fontstyleleft);
 | 
			
		||||
            DrawInfoWithPortrait(infoRect,history, tooltip);
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Right section
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected void DrawBaseSexInfoRight(Rect rect)
 | 
			
		||||
        {
 | 
			
		||||
            Listing_Standard listmain = new Listing_Standard();
 | 
			
		||||
            listmain.Begin(rect.ContractedBy(4f));
 | 
			
		||||
            DrawSexInfoCard(listmain.GetRect(CARDHEIGHT), history.GetRecentPartnersHistory, Keyed.RS_Recent_Sex_Partner, Keyed.RS_Recent_Sex_Partner_ToolTip);
 | 
			
		||||
            DrawSexInfoCard(listmain.GetRect(CARDHEIGHT), history.GetFirstPartnerHistory, Keyed.RS_First_Sex_Partner, Keyed.RS_First_Sex_Partner_ToolTip);
 | 
			
		||||
            DrawSexInfoCard(listmain.GetRect(CARDHEIGHT), history.GetMostPartnerHistory, Keyed.RS_Most_Sex_Partner, Keyed.RS_Most_Sex_Partner_ToolTip);
 | 
			
		||||
            DrawSexInfoCard(listmain.GetRect(CARDHEIGHT), history.GetBestSexPartnerHistory, Keyed.RS_Best_Sex_Partner, Keyed.RS_Best_Sex_Partner_ToolTip);
 | 
			
		||||
            GUI.Label(listmain.GetRect(FONTHEIGHT), Keyed.RS_PreferRace, fontstyleleft);
 | 
			
		||||
            DrawPreferRace(listmain.GetRect(66f+15f));
 | 
			
		||||
            listmain.GetRect(15f);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            listmain.End();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void DrawPreferRace(Rect rect)
 | 
			
		||||
        {
 | 
			
		||||
            Widgets.DrawMenuSection(rect);
 | 
			
		||||
            Rect portraitRect = new Rect(rect.x, rect.y, rect.height-15f, rect.height-15f);
 | 
			
		||||
            Rect infoRect1 = new Rect(rect.x + portraitRect.width, rect.y, rect.width - portraitRect.width, FONTHEIGHT);
 | 
			
		||||
            Rect infoRect2 = new Rect(rect.x + portraitRect.width, rect.y + FONTHEIGHT, rect.width - portraitRect.width, FONTHEIGHT);
 | 
			
		||||
            Rect infoRect3 = new Rect(rect.x + portraitRect.width, rect.y + FONTHEIGHT*2, rect.width - portraitRect.width - 2f, FONTHEIGHT);
 | 
			
		||||
 | 
			
		||||
            if (history.PreferRace != null)
 | 
			
		||||
            {
 | 
			
		||||
                Widgets.DrawTextureFitted(portraitRect, history.GetPreferRaceIcon(portraitRect.size), 1.0f);
 | 
			
		||||
                GUI.Label(infoRect1, history.PreferRace?.label.CapitalizeFirst() ?? Keyed.None, fontstyleleft);
 | 
			
		||||
                GUI.Label(infoRect2, Keyed.RS_Sex_Count + history.PreferRaceSexCount, fontstyleleft);
 | 
			
		||||
                if (history.PreferRace != pawn.def)
 | 
			
		||||
                {
 | 
			
		||||
                    if (history.PreferRace.race.Animal ^ pawn.def.race.Animal) 
 | 
			
		||||
                    {
 | 
			
		||||
                        GUI.Label(infoRect1, Keyed.RS_Bestiality + " ", fontstyleright);
 | 
			
		||||
                        FillableBarLabeled(infoRect3, Keyed.RS_Sex_Info(Keyed.RS_Bestiality, history.BestialityCount.ToString()), history.BestialityCount/100f, Texture2D.linearGrayTexture, Texture2D.blackTexture);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        GUI.Label(infoRect1, Keyed.RS_Interspecies + " ", fontstyleright);
 | 
			
		||||
                        FillableBarLabeled(infoRect3, Keyed.RS_Sex_Info(Keyed.RS_Interspecies, history.InterspeciesCount.ToString()), history.InterspeciesCount / 100f, Texture2D.linearGrayTexture, Texture2D.blackTexture);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    GUI.Label(infoRect1, Keyed.RS_Normal + " ", fontstyleright);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                Widgets.DrawTextureFitted(portraitRect, HistoryUtility.UnknownPawn, 1.0f);
 | 
			
		||||
                GUI.Label(infoRect1, Keyed.None, fontstyleleft);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Center section
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected void DrawBaseSexInfoCenter(Rect rect, Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            Rect portraitRect = new Rect(rect.x + rect.width / 4, rect.y, rect.width / 2, rect.width / 1.5f);
 | 
			
		||||
            Rect nameRect = new Rect(portraitRect.x, portraitRect.yMax - FONTHEIGHT * 2, portraitRect.width, FONTHEIGHT * 2);
 | 
			
		||||
            Rect infoRect = new Rect(rect.x, rect.y + portraitRect.height, rect.width, rect.height - portraitRect.height);
 | 
			
		||||
            Rect lockRect = new Rect(portraitRect.xMax - ICONSIZE, portraitRect.y, ICONSIZE, ICONSIZE);
 | 
			
		||||
            Rect tmp;
 | 
			
		||||
 | 
			
		||||
            if (Mouse.IsOver(portraitRect))
 | 
			
		||||
            {
 | 
			
		||||
                Texture lockicon = Configurations.SelectionLocked ? HistoryUtility.Locked : HistoryUtility.Unlocked;
 | 
			
		||||
                Widgets.DrawTextureFitted(lockRect, lockicon, 1.0f);
 | 
			
		||||
                if (Widgets.ButtonInvisible(lockRect))
 | 
			
		||||
                {
 | 
			
		||||
                    SoundDefOf.Click.PlayOneShotOnCamera();
 | 
			
		||||
                    Configurations.SelectionLocked = !Configurations.SelectionLocked;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            GUI.Box(portraitRect, "", boxstyle);
 | 
			
		||||
            Widgets.DrawTextureFitted(portraitRect, PortraitsCache.Get(pawn, portraitRect.size, Rot4.South, default, 1, true, true, false, false), 1.0f);
 | 
			
		||||
            Widgets.DrawHighlightIfMouseover(portraitRect);
 | 
			
		||||
            if (Widgets.ButtonInvisible(portraitRect))
 | 
			
		||||
            {
 | 
			
		||||
                SoundDefOf.Click.PlayOneShotOnCamera();
 | 
			
		||||
                selectedPawn = null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            GUI.Box(nameRect, "", boxstyle);
 | 
			
		||||
            GUI.Label(nameRect.TopHalf(), pawn.Name?.ToStringFull ?? pawn.Label, fontstylecenter);
 | 
			
		||||
            if (pawn.story != null) GUI.Label(nameRect.BottomHalf(), pawn.ageTracker.AgeBiologicalYears + ", " + pawn.story.Title, fontstylecenter);
 | 
			
		||||
            else GUI.Label(nameRect.BottomHalf(), pawn.ageTracker.AgeBiologicalYears + ", " + pawn.def.label, fontstylecenter);
 | 
			
		||||
 | 
			
		||||
            Listing_Standard listmain = new Listing_Standard();
 | 
			
		||||
            listmain.Begin(infoRect);
 | 
			
		||||
            listmain.Gap(20f);
 | 
			
		||||
            float p;
 | 
			
		||||
 | 
			
		||||
            if (pawn.IsVirgin())
 | 
			
		||||
            {
 | 
			
		||||
                tmp = listmain.GetRect(FONTHEIGHT);
 | 
			
		||||
                GUI.color = Color.red;
 | 
			
		||||
                GUI.Box(tmp, "", boxstyle);
 | 
			
		||||
                GUI.color = Color.white;
 | 
			
		||||
                GUI.Label(tmp, "Virgin", fontstylecenter);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                p = history.TotalSexHad;
 | 
			
		||||
                FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.RS_TotalSexHad + ": {0:0} ({1:0})", p, pawn.records.GetValue(xxx.CountOfSex)), p / 100, HistoryUtility.TotalSex, Texture2D.blackTexture, null, Keyed.RS_SAT_AVG(String.Format("{0:P2}", history.AVGSat)));
 | 
			
		||||
            }
 | 
			
		||||
            listmain.Gap(1f);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            tmp = listmain.GetRect(FONTHEIGHT);
 | 
			
		||||
            p = pawn.records.GetValue(VariousDefOf.Lust);
 | 
			
		||||
            FillableBarLabeled(tmp, String.Format(Keyed.Lust +": {0:0.00}", p), Mathf.Clamp01(p.Normalization(-Configurations.LustLimit*3, Configurations.LustLimit*3)), HistoryUtility.Slaanesh, Texture2D.blackTexture, null, String.Format(xxx.sex_drive_stat.LabelCap.CapitalizeFirst() + ": {0:P2}", pawn.GetStatValue(xxx.sex_drive_stat)));
 | 
			
		||||
            listmain.Gap(1f);
 | 
			
		||||
            if (Mouse.IsOver(tmp))
 | 
			
		||||
            {
 | 
			
		||||
                TooltipHandler.TipRegion(tmp, RJWUIUtility.GetStatExplanation(pawn, xxx.sex_drive_stat, pawn.GetStatValue(xxx.sex_drive_stat)));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            p = history.GetBestSextype(out xxx.rjwSextype sextype) / BASESAT;
 | 
			
		||||
            FillableBarLabeled(listmain.GetRect(FONTHEIGHT),String.Format(Keyed.RS_Best_Sextype+": {0}", Keyed.Sextype[(int)sextype]), p / 2, HistoryUtility.SextypeColor[(int)sextype], Texture2D.blackTexture, null, Keyed.RS_SAT_AVG(String.Format("{0:P2}", p)));
 | 
			
		||||
            listmain.Gap(1f);
 | 
			
		||||
 | 
			
		||||
            p = history.GetRecentSextype(out sextype) / BASESAT;
 | 
			
		||||
            FillableBarLabeled(listmain.GetRect(FONTHEIGHT),String.Format(Keyed.RS_Recent_Sextype+": {0}", Keyed.Sextype[(int)sextype]), p / 2, HistoryUtility.SextypeColor[(int)sextype], Texture2D.blackTexture, null, String.Format("{0:P2}", p));
 | 
			
		||||
            listmain.Gap(1f);
 | 
			
		||||
 | 
			
		||||
            if (history.IncestuousCount < history.CorpseFuckCount)
 | 
			
		||||
            {
 | 
			
		||||
                p = history.CorpseFuckCount;
 | 
			
		||||
                FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.RS_Necrophile + ": {0}", p), p / 50, HistoryUtility.Nurgle, Texture2D.blackTexture);
 | 
			
		||||
                listmain.Gap(1f);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                p = history.IncestuousCount;
 | 
			
		||||
                FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.Incest + ": {0}", p), p / 50, HistoryUtility.Nurgle, Texture2D.blackTexture);
 | 
			
		||||
                listmain.Gap(1f);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            p = pawn.records.GetValue(VariousDefOf.AmountofEatenCum);
 | 
			
		||||
            FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.RS_Cum_Swallowed + ": {0:0.00} mL, {1} " + Keyed.RS_NumofTimes, p, pawn.records.GetValue(VariousDefOf.NumofEatenCum)), p / 1000, Texture2D.linearGrayTexture, Texture2D.blackTexture);
 | 
			
		||||
            listmain.Gap(1f);
 | 
			
		||||
 | 
			
		||||
            Hediff addiction = pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.CumAddiction);
 | 
			
		||||
            if (addiction != null)
 | 
			
		||||
            {
 | 
			
		||||
                p = addiction.Severity;
 | 
			
		||||
                FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.RS_CumAddiction + ": {0:P2}", p), p, Texture2D.linearGrayTexture, Texture2D.blackTexture, Keyed.RS_CumAddiction_Tooltip);
 | 
			
		||||
                listmain.Gap(1f);
 | 
			
		||||
            }
 | 
			
		||||
            else if ((addiction = pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.CumTolerance)) != null)
 | 
			
		||||
            {
 | 
			
		||||
                p = addiction.Severity;
 | 
			
		||||
                FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.RS_CumAddictiveness + ": {0:P}", p), p, Texture2D.linearGrayTexture, Texture2D.blackTexture, Keyed.RS_CumAddictiveness_Tooltip);
 | 
			
		||||
                listmain.Gap(1f);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                listmain.GetRect(FONTHEIGHT);
 | 
			
		||||
                listmain.Gap(1f);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            //listmain.GetRect(FONTHEIGHT);
 | 
			
		||||
            //listmain.Gap(1f);
 | 
			
		||||
 | 
			
		||||
            p = history.RapedCount;
 | 
			
		||||
            tmp = listmain.GetRect(FONTHEIGHT);
 | 
			
		||||
            if (p < history.BeenRapedCount)
 | 
			
		||||
            {
 | 
			
		||||
                p = history.BeenRapedCount;
 | 
			
		||||
                FillableBarLabeled(tmp, String.Format(Keyed.RS_BeenRaped + ": {0}", p), p / 50, Texture2D.grayTexture, Texture2D.blackTexture, null, String.Format(xxx.vulnerability_stat.LabelCap.CapitalizeFirst() + ": {0:P2}", pawn.GetStatValue(xxx.vulnerability_stat)));
 | 
			
		||||
                listmain.Gap(1f);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                FillableBarLabeled(tmp, String.Format(Keyed.RS_RapedSomeone + ": {0}", p), p / 50, HistoryUtility.Khorne, Texture2D.blackTexture, null, String.Format(xxx.vulnerability_stat.LabelCap.CapitalizeFirst() + ": {0:P2}", pawn.GetStatValue(xxx.vulnerability_stat)));
 | 
			
		||||
                listmain.Gap(1f);
 | 
			
		||||
            }
 | 
			
		||||
            if (Mouse.IsOver(tmp))
 | 
			
		||||
            {
 | 
			
		||||
                TooltipHandler.TipRegion(tmp, RJWUIUtility.GetStatExplanation(pawn, xxx.vulnerability_stat, pawn.GetStatValue(xxx.vulnerability_stat)));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            p = pawn.GetStatValue(xxx.sex_satisfaction);
 | 
			
		||||
            tmp = listmain.GetRect(FONTHEIGHT);
 | 
			
		||||
            FillableBarLabeled(tmp, String.Format(xxx.sex_satisfaction.LabelCap.CapitalizeFirst() + ": {0:P2}", p), p/2, HistoryUtility.Satisfaction, Texture2D.blackTexture);
 | 
			
		||||
            listmain.Gap(1f);
 | 
			
		||||
            if (Mouse.IsOver(tmp))
 | 
			
		||||
            {
 | 
			
		||||
                TooltipHandler.TipRegion(tmp, RJWUIUtility.GetStatExplanation(pawn, xxx.sex_satisfaction, pawn.GetStatValue(xxx.sex_satisfaction)));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //p = pawn.GetStatValue(xxx.vulnerability_stat);
 | 
			
		||||
            //FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(xxx.vulnerability_stat.LabelCap.CapitalizeFirst() + ": {0:P2}", p), p / 2, HistoryUtility.Khorne, Texture2D.blackTexture, xxx.vulnerability_stat.description);
 | 
			
		||||
            //listmain.Gap(1f);
 | 
			
		||||
 | 
			
		||||
            SkillRecord skill = pawn.skills?.GetSkill(VariousDefOf.SexSkill);
 | 
			
		||||
            p = skill?.Level ?? 0;
 | 
			
		||||
            tmp = listmain.GetRect(FONTHEIGHT);
 | 
			
		||||
            FillableBarLabeled(tmp, String.Format(Keyed.RS_SexSkill + ": {0}, {1:P2}", p, skill?.xpSinceLastLevel/ skill?.XpRequiredForLevelUp), p / 20, HistoryUtility.Tzeentch, Texture2D.blackTexture, null, String.Format(xxx.sex_stat.LabelCap.CapitalizeFirst() + ": {0:P2}", pawn.GetStatValue(xxx.sex_stat)), HistoryUtility.PassionBG[(int)(skill?.passion ?? 0)]);
 | 
			
		||||
            if (Mouse.IsOver(tmp))
 | 
			
		||||
            {
 | 
			
		||||
                TooltipHandler.TipRegion(tmp, RJWUIUtility.GetStatExplanation(pawn, xxx.sex_stat, pawn.GetStatValue(xxx.sex_stat)));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            listmain.Gap(1f);
 | 
			
		||||
 | 
			
		||||
            if (selectedPawn != null) DrawSexInfoCard(listmain.GetRect(CARDHEIGHT), selectedPawn, Keyed.RS_Selected_Partner, Keyed.RS_Selected_Partner);
 | 
			
		||||
            else DrawExtraInfo(listmain.GetRect(CARDHEIGHT));
 | 
			
		||||
            
 | 
			
		||||
            listmain.End();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void DrawExtraInfo(Rect rect)
 | 
			
		||||
        {
 | 
			
		||||
            Widgets.DrawMenuSection(rect);
 | 
			
		||||
            Rect inRect = rect.ContractedBy(4f);
 | 
			
		||||
            Listing_Standard listmain = new Listing_Standard();
 | 
			
		||||
            listmain.Begin(inRect);
 | 
			
		||||
            listmain.Gap(4f);
 | 
			
		||||
            listmain.GetRect(FONTHEIGHT).DrawSexuality(rjwcomp);
 | 
			
		||||
            listmain.Gap(1f);
 | 
			
		||||
            listmain.GetRect(FONTHEIGHT).DrawQuirk(pawn);
 | 
			
		||||
            listmain.Gap(1f);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            listmain.End();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Left section
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected void DrawBaseSexInfoLeft(Rect rect)
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            Listing_Standard listmain = new Listing_Standard();
 | 
			
		||||
            listmain.Begin(rect);
 | 
			
		||||
            float p;
 | 
			
		||||
 | 
			
		||||
            //Sex statistics
 | 
			
		||||
            GUI.Label(listmain.GetRect(FONTHEIGHT), " " + Keyed.RS_Statistics, fontstyleleft);
 | 
			
		||||
            listmain.Gap(1f);
 | 
			
		||||
            for (int i = 0; i < Sextype.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                int sexindex = Sextype[i];
 | 
			
		||||
                p = history.GetAVGSat(sexindex) / BASESAT;
 | 
			
		||||
                string label = Keyed.RS_Sex_Info(Keyed.Sextype[sexindex], history.GetSexCount(sexindex).ToString());
 | 
			
		||||
                FillableBarLabeled(listmain.GetRect(FONTHEIGHT),label, p / 2, HistoryUtility.SextypeColor[sexindex], Texture2D.blackTexture, null, Keyed.RS_SAT_AVG(String.Format("{0:P2}", p)));
 | 
			
		||||
                listmain.Gap(1f);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            p = history.PartnerCount;
 | 
			
		||||
            FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.RS_Sex_Partners + ": {0} ({1})", p, pawn.records.GetValue(VariousDefOf.SexPartnerCount)), p / 50, HistoryUtility.Partners, Texture2D.blackTexture);
 | 
			
		||||
            listmain.Gap(1f);
 | 
			
		||||
 | 
			
		||||
            p = history.VirginsTaken;
 | 
			
		||||
            FillableBarLabeled(listmain.GetRect(FONTHEIGHT), String.Format(Keyed.RS_VirginsTaken + ": {0:0}", p), p / 100, HistoryUtility.Partners, Texture2D.blackTexture);
 | 
			
		||||
            listmain.Gap(1f);
 | 
			
		||||
            
 | 
			
		||||
            //Partner list
 | 
			
		||||
            GUI.Label(listmain.GetRect(FONTHEIGHT)," "+Keyed.RS_PartnerList, fontstyleleft);
 | 
			
		||||
            listmain.Gap(1f);
 | 
			
		||||
 | 
			
		||||
            Rect scrollRect = listmain.GetRect(CARDHEIGHT+1f);
 | 
			
		||||
            GUI.Box(scrollRect,"", buttonstyle);
 | 
			
		||||
            List<SexHistory> partnerList = history.PartnerList;
 | 
			
		||||
            Rect listRect = new Rect(scrollRect.x, scrollRect.y, LISTPAWNSIZE * partnerList.Count, scrollRect.height - 30f);
 | 
			
		||||
            Widgets.BeginScrollView(scrollRect, ref scroll, listRect);
 | 
			
		||||
            Widgets.ScrollHorizontal(scrollRect, ref scroll, listRect);
 | 
			
		||||
            DrawPartnerList(listRect, partnerList);
 | 
			
		||||
            Widgets.EndScrollView();
 | 
			
		||||
 | 
			
		||||
            listmain.End();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void DrawPartnerList(Rect rect, List<SexHistory> partnerList)
 | 
			
		||||
        {
 | 
			
		||||
            Rect pawnRect = new Rect(rect.x, rect.y, LISTPAWNSIZE, LISTPAWNSIZE);
 | 
			
		||||
            for (int i = 0; i < partnerList.Count; i++)
 | 
			
		||||
            {
 | 
			
		||||
                Rect labelRect = new Rect(pawnRect.x,pawnRect.yMax - FONTHEIGHT,pawnRect.width,FONTHEIGHT);
 | 
			
		||||
 | 
			
		||||
                DrawPawn(pawnRect, partnerList[i]);
 | 
			
		||||
                Widgets.DrawHighlightIfMouseover(pawnRect);
 | 
			
		||||
                GUI.Label(labelRect, partnerList[i].Label, fontstylecenter);
 | 
			
		||||
                if (Widgets.ButtonInvisible(pawnRect))
 | 
			
		||||
                {
 | 
			
		||||
                    selectedPawn = partnerList[i];
 | 
			
		||||
                    SoundDefOf.Click.PlayOneShotOnCamera();
 | 
			
		||||
                }
 | 
			
		||||
                if (partnerList[i] == selectedPawn)
 | 
			
		||||
                {
 | 
			
		||||
                    Widgets.DrawHighlightSelected(pawnRect);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                pawnRect.x += LISTPAWNSIZE;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected void DrawPawn(Rect rect, SexHistory history)
 | 
			
		||||
        {
 | 
			
		||||
            if (history != null)
 | 
			
		||||
            {
 | 
			
		||||
                bool drawheart = false;
 | 
			
		||||
                Rect iconRect = new Rect(rect.x + rect.width * 3 / 4, rect.y, rect.width / 4, rect.height / 4);
 | 
			
		||||
                Texture img = HistoryUtility.UnknownPawn;
 | 
			
		||||
                if (history.Partner != null)
 | 
			
		||||
                {
 | 
			
		||||
                    img = PortraitsCache.Get(history.Partner, rect.size, Rot4.South, default, 1, true, true, false, false);
 | 
			
		||||
                    if (history.IamFirst)
 | 
			
		||||
                    {
 | 
			
		||||
                        GUI.color = HistoryUtility.HistoryColor;
 | 
			
		||||
                        Widgets.DrawTextureFitted(rect, HistoryUtility.FirstOverlay, 1.0f);
 | 
			
		||||
                        GUI.color = Color.white;
 | 
			
		||||
                    }
 | 
			
		||||
                    
 | 
			
		||||
                    drawheart = LovePartnerRelationUtility.LovePartnerRelationExists(pawn, history.Partner);
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (history.Incest)
 | 
			
		||||
                {
 | 
			
		||||
                    Widgets.DrawTextureFitted(iconRect, HistoryUtility.Incest, 1.0f);
 | 
			
		||||
                    iconRect.x -= iconRect.width;
 | 
			
		||||
                }
 | 
			
		||||
                Widgets.DrawTextureFitted(rect, img, 1.0f);
 | 
			
		||||
                if (drawheart)
 | 
			
		||||
                {
 | 
			
		||||
                    Widgets.DrawTextureFitted(iconRect, HistoryUtility.Heart,1.0f);
 | 
			
		||||
                    iconRect.x -= iconRect.width;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
       
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public static void FillableBarLabeled(Rect rect, string label, float fillPercent, Texture2D filltexture, Texture2D bgtexture, string tooltip = null, string rightlabel = "", Texture2D border = null)
 | 
			
		||||
        {
 | 
			
		||||
            Widgets.FillableBar(rect, Math.Min(fillPercent, 1.0f), filltexture, bgtexture, true);
 | 
			
		||||
            GUI.Label(rect, "  " + label.CapitalizeFirst(), fontstyleleft);
 | 
			
		||||
            GUI.Label(rect, rightlabel.CapitalizeFirst() + "  ", fontstyleright);
 | 
			
		||||
            Widgets.DrawHighlightIfMouseover(rect);
 | 
			
		||||
            if (tooltip != null) TooltipHandler.TipRegion(rect, tooltip);
 | 
			
		||||
            if (border != null)
 | 
			
		||||
            {
 | 
			
		||||
                rect.DrawBorder(border,2f);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -10,26 +10,23 @@ using UnityEngine;
 | 
			
		|||
 | 
			
		||||
namespace RJWSexperience
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    public static class Utility
 | 
			
		||||
    {
 | 
			
		||||
        public static System.Random random = new System.Random(Environment.TickCount);
 | 
			
		||||
 | 
			
		||||
        //public static readonly Dictionary<xxx.rjwSextype, RecordDef> sextypeRecords = new Dictionary<xxx.rjwSextype, RecordDef> {
 | 
			
		||||
        //    { xxx.rjwSextype.Vaginal, xxx.CountOfSex },
 | 
			
		||||
        //    { xxx.rjwSextype.Vaginal, xxx.CountOfSex },
 | 
			
		||||
        //    { xxx.rjwSextype.Vaginal, xxx.CountOfSex },
 | 
			
		||||
        //    { xxx.rjwSextype.Vaginal, xxx.CountOfSex },
 | 
			
		||||
        //    { xxx.rjwSextype.Vaginal, xxx.CountOfSex },
 | 
			
		||||
        //    { xxx.rjwSextype.Vaginal, xxx.CountOfSex },
 | 
			
		||||
        //    { xxx.rjwSextype.Vaginal, xxx.CountOfSex },
 | 
			
		||||
        //    { xxx.rjwSextype.Vaginal, xxx.CountOfSex },
 | 
			
		||||
        //    { xxx.rjwSextype.Vaginal, xxx.CountOfSex },
 | 
			
		||||
        //    { xxx.rjwSextype.Vaginal, xxx.CountOfSex },
 | 
			
		||||
        //    { xxx.rjwSextype.Vaginal, xxx.CountOfSex },
 | 
			
		||||
        //    { xxx.rjwSextype.Vaginal, xxx.CountOfSex }
 | 
			
		||||
        //
 | 
			
		||||
        //
 | 
			
		||||
        //};
 | 
			
		||||
        public static bool IsIncest(this Pawn pawn, Pawn otherpawn)
 | 
			
		||||
        {
 | 
			
		||||
            if (otherpawn != null)
 | 
			
		||||
            {
 | 
			
		||||
                IEnumerable<PawnRelationDef> relations = pawn.GetRelations(otherpawn);
 | 
			
		||||
                if (!relations.EnumerableNullOrEmpty()) foreach (PawnRelationDef relation in relations)
 | 
			
		||||
                    {
 | 
			
		||||
                        if (relation.incestOpinionOffset < 0) return true;
 | 
			
		||||
                    }
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static float RandGaussianLike(float min, float max, int iterations = 3)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -59,6 +56,15 @@ namespace RJWSexperience
 | 
			
		|||
            return value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static int RecordRandomizer(this Pawn pawn, RecordDef record, int avg, int dist, int min = 0, int max = int.MaxValue)
 | 
			
		||||
        {
 | 
			
		||||
            int value = (int)Mathf.Clamp(RandGaussianLike(avg - dist, avg + dist), min, max);
 | 
			
		||||
            int recordvalue = pawn.records.GetAsInt(record);
 | 
			
		||||
            pawn.records.AddTo(record, value - recordvalue);
 | 
			
		||||
 | 
			
		||||
            return value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool ContainAll(this string str, string[] tags)
 | 
			
		||||
        {
 | 
			
		||||
            string lstr = str.ToLower();
 | 
			
		||||
| 
						 | 
				
			
			@ -86,17 +92,17 @@ namespace RJWSexperience
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public static Building GetAdjacentBuilding<T>(this Pawn pawn) where T : Building 
 | 
			
		||||
        public static T GetAdjacentBuilding<T>(this Pawn pawn) where T : Building 
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            if (pawn.Spawned)
 | 
			
		||||
            {
 | 
			
		||||
                EdificeGrid edifice = pawn.Map.edificeGrid;
 | 
			
		||||
                if (edifice[pawn.Position] is T) return edifice[pawn.Position];
 | 
			
		||||
                if (edifice[pawn.Position] is T) return (T)edifice[pawn.Position];
 | 
			
		||||
                IEnumerable<IntVec3> adjcells = GenAdjFast.AdjacentCells8Way(pawn.Position);
 | 
			
		||||
                foreach(IntVec3 pos in adjcells)
 | 
			
		||||
                {
 | 
			
		||||
                    if (edifice[pos] is T) return edifice[pos];
 | 
			
		||||
                    if (edifice[pos] is T) return (T)edifice[pos];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return null;
 | 
			
		||||
| 
						 | 
				
			
			@ -139,18 +145,6 @@ namespace RJWSexperience
 | 
			
		|||
            return res;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void CumDrugEffect(this Pawn pawn)
 | 
			
		||||
        {
 | 
			
		||||
            Need need = pawn.needs?.TryGetNeed(VariousDefOf.Chemical_Cum);
 | 
			
		||||
            if (need != null) need.CurLevel += VariousDefOf.CumneedLevelOffset;
 | 
			
		||||
            Hediff addictive = HediffMaker.MakeHediff(VariousDefOf.CumTolerance, pawn);
 | 
			
		||||
            addictive.Severity = 0.032f;
 | 
			
		||||
            pawn.health.AddHediff(addictive);
 | 
			
		||||
            Hediff addiction = pawn.health.hediffSet.GetFirstHediffOfDef(VariousDefOf.CumAddiction);
 | 
			
		||||
            if (addiction != null) addiction.Severity += VariousDefOf.CumexistingAddictionSeverityOffset;
 | 
			
		||||
 | 
			
		||||
            pawn.needs?.mood?.thoughts?.memories?.TryGainMemoryFast(VariousDefOf.AteCum);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static float Normalization(this float num, float min, float max)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -163,5 +157,134 @@ namespace RJWSexperience
 | 
			
		|||
            return num * (max - min) + min;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void ResetRecord(this Pawn pawn, bool allzero)
 | 
			
		||||
        {
 | 
			
		||||
            if (!allzero)
 | 
			
		||||
            {
 | 
			
		||||
                if (Configurations.EnableRecordRandomizer && pawn != null && xxx.is_human(pawn))
 | 
			
		||||
                {
 | 
			
		||||
                    int avgsex = -500;
 | 
			
		||||
                    bool isvirgin = Rand.Chance(Configurations.VirginRatio);
 | 
			
		||||
                    int totalsex = 0;
 | 
			
		||||
                    int totalbirth = 0;
 | 
			
		||||
                    int deviation = (int)Configurations.MaxSexCountDeviation;
 | 
			
		||||
                    if (pawn.story != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        float lust;
 | 
			
		||||
                        if (xxx.is_nympho(pawn)) lust = pawn.RecordRandomizer(VariousDefOf.Lust, Configurations.AvgLust, Configurations.MaxLustDeviation, 0);
 | 
			
		||||
                        else lust = pawn.RecordRandomizer(VariousDefOf.Lust, Configurations.AvgLust, Configurations.MaxLustDeviation, float.MinValue);
 | 
			
		||||
 | 
			
		||||
                        int sexableage = 0;
 | 
			
		||||
                        int minsexage = (int)(pawn.RaceProps.lifeExpectancy * Configurations.MinSexablePercent);
 | 
			
		||||
                        if (pawn.ageTracker.AgeBiologicalYears > minsexage)
 | 
			
		||||
                        {
 | 
			
		||||
                            sexableage = pawn.ageTracker.AgeBiologicalYears - minsexage;
 | 
			
		||||
                            avgsex = (int)(sexableage * Configurations.SexPerYear * pawn.LustFactor());
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                        if (pawn.relations != null && pawn.gender == Gender.Female)
 | 
			
		||||
                        {
 | 
			
		||||
                            totalbirth += pawn.relations.ChildrenCount;
 | 
			
		||||
                            totalsex += totalbirth;
 | 
			
		||||
                            pawn.records?.AddTo(xxx.CountOfSexWithHumanlikes, totalbirth);
 | 
			
		||||
                            pawn.records?.SetTo(xxx.CountOfBirthHuman, totalbirth);
 | 
			
		||||
                            if (totalbirth > 0) isvirgin = false;
 | 
			
		||||
                        }
 | 
			
		||||
                        if (!isvirgin)
 | 
			
		||||
                        {
 | 
			
		||||
                            if (xxx.is_rapist(pawn))
 | 
			
		||||
                            {
 | 
			
		||||
                                if (xxx.is_zoophile(pawn))
 | 
			
		||||
                                {
 | 
			
		||||
                                    if (pawn.Has(Quirk.ChitinLover)) totalsex += pawn.RecordRandomizer(xxx.CountOfRapedInsects, avgsex, deviation);
 | 
			
		||||
                                    else totalsex += pawn.RecordRandomizer(xxx.CountOfRapedAnimals, avgsex, deviation);
 | 
			
		||||
                                }
 | 
			
		||||
                                else totalsex += pawn.RecordRandomizer(xxx.CountOfRapedHumanlikes, avgsex, deviation);
 | 
			
		||||
                                avgsex /= 8;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            if (xxx.is_zoophile(pawn))
 | 
			
		||||
                            {
 | 
			
		||||
                                if (pawn.Has(Quirk.ChitinLover)) totalsex += pawn.RecordRandomizer(xxx.CountOfRapedInsects, avgsex, deviation);
 | 
			
		||||
                                else totalsex += pawn.RecordRandomizer(xxx.CountOfSexWithAnimals, avgsex, deviation);
 | 
			
		||||
                                avgsex /= 10;
 | 
			
		||||
                            }
 | 
			
		||||
                            else if (xxx.is_necrophiliac(pawn))
 | 
			
		||||
                            {
 | 
			
		||||
                                totalsex += pawn.RecordRandomizer(xxx.CountOfSexWithCorpse, avgsex, deviation);
 | 
			
		||||
                                avgsex /= 4;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            if (pawn.IsSlave)
 | 
			
		||||
                            {
 | 
			
		||||
                                totalsex += pawn.RecordRandomizer(xxx.CountOfBeenRapedByAnimals, Rand.Range(-50, 10), Rand.Range(0, 10) * sexableage);
 | 
			
		||||
                                totalsex += pawn.RecordRandomizer(xxx.CountOfBeenRapedByHumanlikes, 0, Rand.Range(0, 100) * sexableage);
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                            totalsex += pawn.RecordRandomizer(xxx.CountOfSexWithHumanlikes, avgsex, deviation);
 | 
			
		||||
 | 
			
		||||
                            if (totalsex > 0) pawn.records.AddTo(VariousDefOf.SexPartnerCount, Math.Max(1, Rand.Range(0, totalsex / 7)));
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    pawn.records?.SetTo(xxx.CountOfSex, totalsex);
 | 
			
		||||
                    RJWUtility.GenerateSextypeRecords(pawn, totalsex);
 | 
			
		||||
                }
 | 
			
		||||
                if (pawn.story?.traits != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (pawn.IsVirgin())
 | 
			
		||||
                    {
 | 
			
		||||
                        int degree = 0;
 | 
			
		||||
                        if (pawn.gender == Gender.Female) degree = 2;
 | 
			
		||||
                        Trait virgin = new Trait(VariousDefOf.Virgin, degree, true);
 | 
			
		||||
                        pawn.story.traits.GainTrait(virgin);
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (pawn.gender == Gender.Female && Rand.Chance(0.05f))
 | 
			
		||||
                    {
 | 
			
		||||
                        Trait virgin = new Trait(VariousDefOf.Virgin, 1, true);
 | 
			
		||||
                        pawn.story.traits.GainTrait(virgin);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.Lust, 0);
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.NumofEatenCum, 0);
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.AmountofEatenCum, 0);
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.VaginalSexCount, 0);
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.AnalSexCount, 0);
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.OralSexCount, 0);
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.BlowjobCount, 0);
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.CunnilingusCount, 0);
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.GenitalCaressCount, 0);
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.HandjobCount, 0);
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.FingeringCount, 0);
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.FootjobCount, 0);
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.MiscSexualBehaviorCount, 0);
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.SexPartnerCount, 0);
 | 
			
		||||
                pawn.records.SetTo(VariousDefOf.OrgasmCount, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfBeenRapedByAnimals, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfBeenRapedByHumanlikes, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfBeenRapedByInsects, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfBeenRapedByOthers, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfBirthAnimal, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfBirthEgg, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfBirthHuman, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfFappin, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfRapedAnimals, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfRapedHumanlikes, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfRapedInsects, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfRapedOthers, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfSex, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfSexWithAnimals, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfSexWithCorpse, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfSexWithHumanlikes, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfSexWithInsects, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfSexWithOthers, 0);
 | 
			
		||||
                pawn.records.SetTo(xxx.CountOfWhore, 0);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ namespace RJWSexperience
 | 
			
		|||
    public static class VariousDefOf
 | 
			
		||||
    {
 | 
			
		||||
        public static readonly RecordDef NumofEatenCum = DefDatabase<RecordDef>.GetNamed("NumofEatenCum");
 | 
			
		||||
        public static readonly RecordDef AmountofEatenCum = DefDatabase<RecordDef>.GetNamed("AmountofEatenCum");
 | 
			
		||||
        public static readonly RecordDef Lust = DefDatabase<RecordDef>.GetNamed("Lust");
 | 
			
		||||
        public static readonly RecordDef VaginalSexCount = DefDatabase<RecordDef>.GetNamed("VaginalSexCount");
 | 
			
		||||
        public static readonly RecordDef AnalSexCount = DefDatabase<RecordDef>.GetNamed("AnalSexCount");
 | 
			
		||||
| 
						 | 
				
			
			@ -18,20 +19,27 @@ namespace RJWSexperience
 | 
			
		|||
        public static readonly RecordDef BlowjobCount = DefDatabase<RecordDef>.GetNamed("BlowjobCount");
 | 
			
		||||
        public static readonly RecordDef CunnilingusCount = DefDatabase<RecordDef>.GetNamed("CunnilingusCount");
 | 
			
		||||
        public static readonly RecordDef GenitalCaressCount = DefDatabase<RecordDef>.GetNamed("GenitalCaressCount");
 | 
			
		||||
        public static readonly RecordDef HadnjobCount = DefDatabase<RecordDef>.GetNamed("HadnjobCount");
 | 
			
		||||
        public static readonly RecordDef HandjobCount = DefDatabase<RecordDef>.GetNamed("HandjobCount");
 | 
			
		||||
        public static readonly RecordDef FingeringCount = DefDatabase<RecordDef>.GetNamed("FingeringCount");
 | 
			
		||||
        public static readonly RecordDef FootjobCount = DefDatabase<RecordDef>.GetNamed("FootjobCount");
 | 
			
		||||
        public static readonly RecordDef MiscSexualBehaviorCount = DefDatabase<RecordDef>.GetNamed("MiscSexualBehaviorCount");
 | 
			
		||||
        public static readonly RecordDef SexPartnerCount = DefDatabase<RecordDef>.GetNamed("SexPartnerCount");
 | 
			
		||||
        public static readonly RecordDef OrgasmCount = DefDatabase<RecordDef>.GetNamed("OrgasmCount");
 | 
			
		||||
        public static readonly SkillDef SexSkill = DefDatabase<SkillDef>.GetNamed("Sex");
 | 
			
		||||
        public static readonly ThoughtDef_Recordbased AteCum = DefDatabase<ThoughtDef_Recordbased>.GetNamed("AteCum");
 | 
			
		||||
        public static readonly PawnRelationDef Bastard = DefDatabase<PawnRelationDef>.GetNamed("Bastard");
 | 
			
		||||
        public static readonly ThingDef GatheredCum = DefDatabase<ThingDef>.GetNamed("GatheredCum");
 | 
			
		||||
        public static readonly ThingDef FilthCum = ThingDef.Named("FilthCum");
 | 
			
		||||
        public static readonly ThingDef FilthGirlcum = ThingDef.Named("FilthGirlCum");
 | 
			
		||||
        public static readonly HediffDef CumAddiction = DefDatabase<HediffDef>.GetNamed("CumAddiction");
 | 
			
		||||
        public static readonly HediffDef CumTolerance = DefDatabase<HediffDef>.GetNamed("CumTolerance");
 | 
			
		||||
        public static readonly ChemicalDef Cum = DefDatabase<ChemicalDef>.GetNamed("Cum");
 | 
			
		||||
        public static readonly NeedDef Chemical_Cum = DefDatabase<NeedDef>.GetNamed("Chemical_Cum");
 | 
			
		||||
        public static readonly TraitDef Virgin = DefDatabase<TraitDef>.GetNamed("Virgin");
 | 
			
		||||
        public static readonly JobDef CleanSelfwithBucket = DefDatabase<JobDef>.GetNamed("CleanSelfwithBucket");
 | 
			
		||||
        public static readonly PawnRelationDef relation_birthgiver = DefDatabase<PawnRelationDef>.GetNamed("RJW_Sire");
 | 
			
		||||
        public static readonly PawnRelationDef relation_spawn = DefDatabase<PawnRelationDef>.GetNamed("RJW_Pup");
 | 
			
		||||
        public static readonly KeyBindingDef OpenSexStatistics = DefDatabase<KeyBindingDef>.GetNamed("OpenSexStatistics");
 | 
			
		||||
 | 
			
		||||
        public static float CumneedLevelOffset
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
<Defs>
 | 
			
		||||
 | 
			
		||||
  <DutyDef>
 | 
			
		||||
    <defName>Gangbang</defName>
 | 
			
		||||
    <defName>Gangbang_Rape</defName>
 | 
			
		||||
    <hook>HighPriority</hook>
 | 
			
		||||
    <socialModeMax>Off</socialModeMax>
 | 
			
		||||
    <thinkNode Class="ThinkNode_Priority">
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +26,31 @@
 | 
			
		|||
    </thinkNode>
 | 
			
		||||
  </DutyDef>
 | 
			
		||||
  
 | 
			
		||||
  <DutyDef>
 | 
			
		||||
    <defName>Gangbang_Consensual</defName>
 | 
			
		||||
    <hook>HighPriority</hook>
 | 
			
		||||
    <socialModeMax>Off</socialModeMax>
 | 
			
		||||
    <thinkNode Class="ThinkNode_Priority">
 | 
			
		||||
      <subNodes>
 | 
			
		||||
        <li Class="ThinkNode_ConditionalInGatheringArea">
 | 
			
		||||
          <subNodes>
 | 
			
		||||
            <li Class="ThinkNode_ConditionalRandom">
 | 
			
		||||
              <chance>0.25</chance>
 | 
			
		||||
              <subNodes>
 | 
			
		||||
                 <li Class="RJWSexperience.Ideology.JobGiver_GangbangConsensual"/>
 | 
			
		||||
              </subNodes>
 | 
			
		||||
            </li>
 | 
			
		||||
          </subNodes>
 | 
			
		||||
        </li>
 | 
			
		||||
 | 
			
		||||
        <li Class="JobGiver_WanderInGatheringArea">
 | 
			
		||||
			  	<locomotionUrgency>Jog</locomotionUrgency>
 | 
			
		||||
			  	<ticksBetweenWandersRange>50~250</ticksBetweenWandersRange>
 | 
			
		||||
			  </li>
 | 
			
		||||
      </subNodes>
 | 
			
		||||
    </thinkNode>
 | 
			
		||||
  </DutyDef>
 | 
			
		||||
 | 
			
		||||
  <DutyDef>
 | 
			
		||||
    <defName>FuckVictim</defName>
 | 
			
		||||
    <hook>HighPriority</hook>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,4 +28,20 @@
 | 
			
		|||
		<reportString>masturbatin'.</reportString>
 | 
			
		||||
		<casualInterruptible>false</casualInterruptible>
 | 
			
		||||
	</JobDef>
 | 
			
		||||
 | 
			
		||||
	<JobDef>
 | 
			
		||||
		<defName>Gangbang</defName>
 | 
			
		||||
		<driverClass>RJWSexperience.Ideology.JobDriver_Gangbang</driverClass>
 | 
			
		||||
		<reportString>lovin'.</reportString>
 | 
			
		||||
		<casualInterruptible>false</casualInterruptible>
 | 
			
		||||
	</JobDef>
 | 
			
		||||
 | 
			
		||||
	<JobDef>
 | 
			
		||||
		<defName>GettinGangbang</defName>
 | 
			
		||||
		<driverClass>RJWSexperience.Ideology.JobDriver_GangbangReceiver</driverClass>
 | 
			
		||||
		<reportString>gettin' gangbanged.</reportString>
 | 
			
		||||
		<checkOverrideOnDamage>Never</checkOverrideOnDamage>
 | 
			
		||||
		<casualInterruptible>false</casualInterruptible>
 | 
			
		||||
	</JobDef>
 | 
			
		||||
 | 
			
		||||
</Defs>
 | 
			
		||||
| 
						 | 
				
			
			@ -27,6 +27,28 @@
 | 
			
		|||
  </PreceptDef>
 | 
			
		||||
  
 | 
			
		||||
  <PreceptDef>
 | 
			
		||||
    <defName>GangbangCeremony_Consensual</defName>
 | 
			
		||||
    <label>gangbang</label>
 | 
			
		||||
    <description>A ritualistic gangbang where a organizer being fucked. The audience will fuck the organizer.</description>
 | 
			
		||||
    <issue>Ritual</issue>
 | 
			
		||||
    <impact>Medium</impact>
 | 
			
		||||
    <iconPath>UI/Issues/Gangbang_Consensual</iconPath>
 | 
			
		||||
    <preceptClass>Precept_Ritual</preceptClass>
 | 
			
		||||
    <ritualPatternBase>Gangbang_Consensual</ritualPatternBase>
 | 
			
		||||
    <allowDuplicates>true</allowDuplicates>
 | 
			
		||||
    <countsTowardsPreceptLimit>false</countsTowardsPreceptLimit>
 | 
			
		||||
    <selectionWeight>1.0</selectionWeight>
 | 
			
		||||
    <displayOrderInImpact>100</displayOrderInImpact>
 | 
			
		||||
    <ignoreLimitsInEditMode>false</ignoreLimitsInEditMode>
 | 
			
		||||
    <receivesExpectationsQualityOffset>true</receivesExpectationsQualityOffset>
 | 
			
		||||
    <canGenerateAsSpecialPrecept>false</canGenerateAsSpecialPrecept>
 | 
			
		||||
    <allowStackingRitualObligationAlerts>true</allowStackingRitualObligationAlerts>
 | 
			
		||||
    <requiredMemes>
 | 
			
		||||
      <li>Lewd</li>
 | 
			
		||||
    </requiredMemes>
 | 
			
		||||
  </PreceptDef>
 | 
			
		||||
 | 
			
		||||
  <RJWSexperience.Ideology.PreceptDef_RequirementExtended>
 | 
			
		||||
    <defName>AnimalGangbangCeremony</defName>
 | 
			
		||||
    <label>animal gangbang</label>
 | 
			
		||||
    <description>A ritualistic gangbang where animals rape a victim.</description>
 | 
			
		||||
| 
						 | 
				
			
			@ -43,12 +65,36 @@
 | 
			
		|||
    <receivesExpectationsQualityOffset>true</receivesExpectationsQualityOffset>
 | 
			
		||||
    <canGenerateAsSpecialPrecept>false</canGenerateAsSpecialPrecept>
 | 
			
		||||
    <allowStackingRitualObligationAlerts>true</allowStackingRitualObligationAlerts>
 | 
			
		||||
    <requiredAllMemes>
 | 
			
		||||
      <li>Rapist</li>
 | 
			
		||||
      <li>Zoophile</li>
 | 
			
		||||
    </requiredAllMemes>
 | 
			
		||||
  </RJWSexperience.Ideology.PreceptDef_RequirementExtended>
 | 
			
		||||
  
 | 
			
		||||
  <PreceptDef>
 | 
			
		||||
    <defName>AnimalGangbangCeremony_Consensual</defName>
 | 
			
		||||
    <label>animal gangbang</label>
 | 
			
		||||
    <description>A ritualistic gangbang where animals fuck the organizer.</description>
 | 
			
		||||
    <issue>Ritual</issue>
 | 
			
		||||
    <impact>Medium</impact>
 | 
			
		||||
    <iconPath>UI/Commands/Breeding_Pawn_on</iconPath>
 | 
			
		||||
    <preceptClass>Precept_Ritual</preceptClass>
 | 
			
		||||
    <ritualPatternBase>GangbangByAnimal_Consensual</ritualPatternBase>
 | 
			
		||||
    <allowDuplicates>true</allowDuplicates>
 | 
			
		||||
    <countsTowardsPreceptLimit>false</countsTowardsPreceptLimit>
 | 
			
		||||
    <selectionWeight>1.0</selectionWeight>
 | 
			
		||||
    <displayOrderInImpact>100</displayOrderInImpact>
 | 
			
		||||
    <ignoreLimitsInEditMode>false</ignoreLimitsInEditMode>
 | 
			
		||||
    <receivesExpectationsQualityOffset>true</receivesExpectationsQualityOffset>
 | 
			
		||||
    <canGenerateAsSpecialPrecept>false</canGenerateAsSpecialPrecept>
 | 
			
		||||
    <allowStackingRitualObligationAlerts>true</allowStackingRitualObligationAlerts>
 | 
			
		||||
    <requiredMemes>
 | 
			
		||||
      <li>Zoophile</li>
 | 
			
		||||
    </requiredMemes>
 | 
			
		||||
  </PreceptDef>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  <PreceptDef>
 | 
			
		||||
    <defName>DrugOrgyCeremony</defName>
 | 
			
		||||
    <label>drug orgy</label>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,8 +58,6 @@
 | 
			
		|||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>AnalSex</eventDef>
 | 
			
		||||
        <thought>Sex_Promiscuous</thought>
 | 
			
		||||
        <recordDef>Lust</recordDef>
 | 
			
		||||
        <recordoffset>2.0</recordoffset>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_KnowsMemoryThoughtTagged">
 | 
			
		||||
        <eventDef>AnalSex</eventDef>
 | 
			
		||||
| 
						 | 
				
			
			@ -68,8 +66,6 @@
 | 
			
		|||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>OralSex</eventDef>
 | 
			
		||||
        <thought>Sex_Promiscuous</thought>
 | 
			
		||||
        <recordDef>Lust</recordDef>
 | 
			
		||||
        <recordoffset>2.0</recordoffset>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_KnowsMemoryThoughtTagged">
 | 
			
		||||
        <eventDef>OralSex</eventDef>
 | 
			
		||||
| 
						 | 
				
			
			@ -78,8 +74,6 @@
 | 
			
		|||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>MiscSex</eventDef>
 | 
			
		||||
        <thought>Sex_Promiscuous</thought>
 | 
			
		||||
        <recordDef>Lust</recordDef>
 | 
			
		||||
        <recordoffset>2.0</recordoffset>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_KnowsMemoryThoughtTagged">
 | 
			
		||||
        <eventDef>MiscSex</eventDef>
 | 
			
		||||
| 
						 | 
				
			
			@ -88,8 +82,6 @@
 | 
			
		|||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>PromiscuousSex</eventDef>
 | 
			
		||||
        <thought>Sex_Promiscuous</thought>
 | 
			
		||||
        <recordDef>Lust</recordDef>
 | 
			
		||||
        <recordoffset>3.0</recordoffset>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_KnowsMemoryThoughtTagged">
 | 
			
		||||
        <eventDef>PromiscuousSex</eventDef>
 | 
			
		||||
| 
						 | 
				
			
			@ -111,8 +103,6 @@
 | 
			
		|||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>VaginalSex</eventDef>
 | 
			
		||||
        <thought>Sex_Promiscuous</thought>
 | 
			
		||||
        <recordDef>Lust</recordDef>
 | 
			
		||||
        <recordoffset>2.0</recordoffset>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_KnowsMemoryThoughtTagged">
 | 
			
		||||
        <eventDef>VaginalSex</eventDef>
 | 
			
		||||
| 
						 | 
				
			
			@ -121,8 +111,6 @@
 | 
			
		|||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>OralSex</eventDef>
 | 
			
		||||
        <thought>Sex_Promiscuous</thought>
 | 
			
		||||
        <recordDef>Lust</recordDef>
 | 
			
		||||
        <recordoffset>2.0</recordoffset>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_KnowsMemoryThoughtTagged">
 | 
			
		||||
        <eventDef>OralSex</eventDef>
 | 
			
		||||
| 
						 | 
				
			
			@ -131,8 +119,6 @@
 | 
			
		|||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>MiscSex</eventDef>
 | 
			
		||||
        <thought>Sex_Promiscuous</thought>
 | 
			
		||||
        <recordDef>Lust</recordDef>
 | 
			
		||||
        <recordoffset>2.0</recordoffset>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_KnowsMemoryThoughtTagged">
 | 
			
		||||
        <eventDef>MiscSex</eventDef>
 | 
			
		||||
| 
						 | 
				
			
			@ -141,8 +127,6 @@
 | 
			
		|||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>PromiscuousSex</eventDef>
 | 
			
		||||
        <thought>Sex_Promiscuous</thought>
 | 
			
		||||
        <recordDef>Lust</recordDef>
 | 
			
		||||
        <recordoffset>3.0</recordoffset>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_KnowsMemoryThoughtTagged">
 | 
			
		||||
        <eventDef>PromiscuousSex</eventDef>
 | 
			
		||||
| 
						 | 
				
			
			@ -164,8 +148,6 @@
 | 
			
		|||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>VaginalSex</eventDef>
 | 
			
		||||
        <thought>Sex_Promiscuous</thought>
 | 
			
		||||
        <recordDef>Lust</recordDef>
 | 
			
		||||
        <recordoffset>2.0</recordoffset>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_KnowsMemoryThoughtTagged">
 | 
			
		||||
        <eventDef>VaginalSex</eventDef>
 | 
			
		||||
| 
						 | 
				
			
			@ -174,8 +156,6 @@
 | 
			
		|||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>AnalSex</eventDef>
 | 
			
		||||
        <thought>Sex_Promiscuous</thought>
 | 
			
		||||
        <recordDef>Lust</recordDef>
 | 
			
		||||
        <recordoffset>2.0</recordoffset>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_KnowsMemoryThoughtTagged">
 | 
			
		||||
        <eventDef>AnalSex</eventDef>
 | 
			
		||||
| 
						 | 
				
			
			@ -184,8 +164,6 @@
 | 
			
		|||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>MiscSex</eventDef>
 | 
			
		||||
        <thought>Sex_Promiscuous</thought>
 | 
			
		||||
        <recordDef>Lust</recordDef>
 | 
			
		||||
        <recordoffset>2.0</recordoffset>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_KnowsMemoryThoughtTagged">
 | 
			
		||||
        <eventDef>MiscSex</eventDef>
 | 
			
		||||
| 
						 | 
				
			
			@ -194,8 +172,6 @@
 | 
			
		|||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>PromiscuousSex</eventDef>
 | 
			
		||||
        <thought>Sex_Promiscuous</thought>
 | 
			
		||||
        <recordDef>Lust</recordDef>
 | 
			
		||||
        <recordoffset>3.0</recordoffset>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_KnowsMemoryThoughtTagged">
 | 
			
		||||
        <eventDef>PromiscuousSex</eventDef>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										342
									
								
								RJWSexperience_Ideology/Defs/PreceptDefs/Precepts_Virginity.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,342 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
<Defs>
 | 
			
		||||
  <!-- Issues -->
 | 
			
		||||
  <IssueDef>
 | 
			
		||||
    <defName>Virginity_Female</defName>
 | 
			
		||||
    <label>virginity of female</label>
 | 
			
		||||
    <iconPath>UI/Issues/Female</iconPath>
 | 
			
		||||
  </IssueDef>
 | 
			
		||||
 | 
			
		||||
  <IssueDef>
 | 
			
		||||
    <defName>Virginity_Male</defName>
 | 
			
		||||
    <label>virginity of male</label>
 | 
			
		||||
    <iconPath>UI/Issues/Male</iconPath>
 | 
			
		||||
  </IssueDef>
 | 
			
		||||
 | 
			
		||||
  <HistoryEventDef>
 | 
			
		||||
    <defName>Virgin_TakenF</defName>
 | 
			
		||||
    <label>virgin taken</label>
 | 
			
		||||
  </HistoryEventDef>
 | 
			
		||||
 | 
			
		||||
  <HistoryEventDef>
 | 
			
		||||
    <defName>Virgin_TakenM</defName>
 | 
			
		||||
    <label>virgin taken</label>
 | 
			
		||||
  </HistoryEventDef>
 | 
			
		||||
 | 
			
		||||
  <HistoryEventDef>
 | 
			
		||||
    <defName>Virgin_TookF</defName>
 | 
			
		||||
    <label>virgin took</label>
 | 
			
		||||
  </HistoryEventDef>
 | 
			
		||||
 | 
			
		||||
  <HistoryEventDef>
 | 
			
		||||
    <defName>Virgin_TookM</defName>
 | 
			
		||||
    <label>virgin took</label>
 | 
			
		||||
  </HistoryEventDef>
 | 
			
		||||
 | 
			
		||||
  <!-- Precepts -->
 | 
			
		||||
 | 
			
		||||
  <PreceptDef>
 | 
			
		||||
    <defName>Virgin_UselessF</defName>
 | 
			
		||||
    <issue>Virginity_Female</issue>
 | 
			
		||||
    <label>useless</label>
 | 
			
		||||
    <description>Female's virginity is useless.</description>
 | 
			
		||||
    <impact>Medium</impact>
 | 
			
		||||
    <displayOrderInIssue>50</displayOrderInIssue>
 | 
			
		||||
    <displayOrderInImpact>1000</displayOrderInImpact>
 | 
			
		||||
    <defaultSelectionWeight>10</defaultSelectionWeight>
 | 
			
		||||
  </PreceptDef>
 | 
			
		||||
 | 
			
		||||
  <PreceptDef>
 | 
			
		||||
    <defName>Virgin_UselessM</defName>
 | 
			
		||||
    <issue>Virginity_Male</issue>
 | 
			
		||||
    <label>useless</label>
 | 
			
		||||
    <description>Male's virginity is useless.</description>
 | 
			
		||||
    <impact>Low</impact>
 | 
			
		||||
    <displayOrderInIssue>50</displayOrderInIssue>
 | 
			
		||||
    <displayOrderInImpact>1000</displayOrderInImpact>
 | 
			
		||||
    <defaultSelectionWeight>80</defaultSelectionWeight>
 | 
			
		||||
  </PreceptDef>
 | 
			
		||||
 | 
			
		||||
  <PreceptDef>
 | 
			
		||||
    <defName>Virgin_PreciousF</defName>
 | 
			
		||||
    <issue>Virginity_Female</issue>
 | 
			
		||||
    <label>precious</label>
 | 
			
		||||
    <description>Female's virginity is precious.</description>
 | 
			
		||||
    <impact>Medium</impact>
 | 
			
		||||
    <displayOrderInIssue>40</displayOrderInIssue>
 | 
			
		||||
    <displayOrderInImpact>1000</displayOrderInImpact>
 | 
			
		||||
    <defaultSelectionWeight>80</defaultSelectionWeight>
 | 
			
		||||
    <comps>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>Virgin_TakenF</eventDef>
 | 
			
		||||
        <thought>Virgin_Precious_Taken_Forcefully</thought>
 | 
			
		||||
        <tag>BeenRaped</tag>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>Virgin_TakenF</eventDef>
 | 
			
		||||
        <thought>Virgin_Precious_Taken</thought>
 | 
			
		||||
        <tag>BeenRaped</tag>
 | 
			
		||||
        <exclusive>true</exclusive>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>Virgin_TookF</eventDef>
 | 
			
		||||
        <thought>TookVirginity</thought>
 | 
			
		||||
      </li>
 | 
			
		||||
    </comps>
 | 
			
		||||
  </PreceptDef>
 | 
			
		||||
 | 
			
		||||
  <PreceptDef>
 | 
			
		||||
    <defName>Virgin_PreciousM</defName>
 | 
			
		||||
    <issue>Virginity_Male</issue>
 | 
			
		||||
    <label>precious</label>
 | 
			
		||||
    <description>Male's virginity is precious.</description>
 | 
			
		||||
    <impact>Medium</impact>
 | 
			
		||||
    <displayOrderInIssue>40</displayOrderInIssue>
 | 
			
		||||
    <displayOrderInImpact>1000</displayOrderInImpact>
 | 
			
		||||
    <defaultSelectionWeight>1</defaultSelectionWeight>
 | 
			
		||||
    <comps>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>Virgin_TakenM</eventDef>
 | 
			
		||||
        <thought>Virgin_Precious_Taken_Forcefully</thought>
 | 
			
		||||
        <tag>BeenRaped</tag>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>Virgin_TakenM</eventDef>
 | 
			
		||||
        <thought>Virgin_Precious_Taken</thought>
 | 
			
		||||
        <tag>BeenRaped</tag>
 | 
			
		||||
        <exclusive>true</exclusive>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>Virgin_TookM</eventDef>
 | 
			
		||||
        <thought>TookVirginity</thought>
 | 
			
		||||
      </li>
 | 
			
		||||
    </comps>
 | 
			
		||||
  </PreceptDef>
 | 
			
		||||
 | 
			
		||||
  <PreceptDef>
 | 
			
		||||
    <defName>Virgin_OnlyForSpouseF</defName>
 | 
			
		||||
    <issue>Virginity_Female</issue>
 | 
			
		||||
    <label>precious(strict)</label>
 | 
			
		||||
    <description>Losing virginity before marriage is evil.</description>
 | 
			
		||||
    <impact>Medium</impact>
 | 
			
		||||
    <displayOrderInIssue>40</displayOrderInIssue>
 | 
			
		||||
    <displayOrderInImpact>1000</displayOrderInImpact>
 | 
			
		||||
    <defaultSelectionWeight>80</defaultSelectionWeight>
 | 
			
		||||
    <requiredMemes>
 | 
			
		||||
      <li>MaleSupremacy</li>
 | 
			
		||||
    </requiredMemes>
 | 
			
		||||
    <conflictingMemes>
 | 
			
		||||
      <li>FemaleSupremacy</li>
 | 
			
		||||
    </conflictingMemes>
 | 
			
		||||
    <associatedMemes>
 | 
			
		||||
      <li>MaleSupremacy</li>
 | 
			
		||||
    </associatedMemes>
 | 
			
		||||
    <comps>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>Virgin_TakenF</eventDef>
 | 
			
		||||
        <thought>Virgin_Precious_Taken_Forcefully</thought>
 | 
			
		||||
        <tag>BeenRaped</tag>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>Virgin_TakenF</eventDef>
 | 
			
		||||
        <thought>Virgin_Precious_Taken</thought>
 | 
			
		||||
        <tag>BeenRaped</tag>
 | 
			
		||||
        <exclusive>true</exclusive>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_KnowsMemoryThoughtTagged">
 | 
			
		||||
        <eventDef>Virgin_TakenF</eventDef>
 | 
			
		||||
        <thought>Virgin_OnlyForSpouse_Know_Taken</thought>
 | 
			
		||||
        <tag>Female, NotSpouse</tag>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="PreceptComp_SelfTookMemoryThought">
 | 
			
		||||
        <eventDef>Virgin_TookF</eventDef>
 | 
			
		||||
        <thought>TookVirginity</thought>
 | 
			
		||||
      </li>
 | 
			
		||||
    </comps>
 | 
			
		||||
  </PreceptDef>
 | 
			
		||||
 | 
			
		||||
  <PreceptDef>
 | 
			
		||||
    <defName>Virgin_OnlyForSpouseM</defName>
 | 
			
		||||
    <issue>Virginity_Male</issue>
 | 
			
		||||
    <label>precious(strict)</label>
 | 
			
		||||
    <description>Losing virginity before marriage is evil.</description>
 | 
			
		||||
    <impact>Medium</impact>
 | 
			
		||||
    <displayOrderInIssue>40</displayOrderInIssue>
 | 
			
		||||
    <displayOrderInImpact>1000</displayOrderInImpact>
 | 
			
		||||
    <defaultSelectionWeight>20</defaultSelectionWeight>
 | 
			
		||||
    <requiredMemes>
 | 
			
		||||
      <li>FemaleSupremacy</li>
 | 
			
		||||
    </requiredMemes>
 | 
			
		||||
    <conflictingMemes>
 | 
			
		||||
      <li>MaleSupremacy</li>
 | 
			
		||||
    </conflictingMemes>
 | 
			
		||||
    <associatedMemes>
 | 
			
		||||
      <li>FemaleSupremacy</li>
 | 
			
		||||
    </associatedMemes>
 | 
			
		||||
    <comps>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>Virgin_TakenM</eventDef>
 | 
			
		||||
        <thought>Virgin_Precious_Taken_Forcefully</thought>
 | 
			
		||||
        <tag>BeenRaped</tag>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>Virgin_TakenM</eventDef>
 | 
			
		||||
        <thought>Virgin_Precious_Taken</thought>
 | 
			
		||||
        <tag>BeenRaped</tag>
 | 
			
		||||
        <exclusive>true</exclusive>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_KnowsMemoryThoughtTagged">
 | 
			
		||||
        <eventDef>Virgin_TakenM</eventDef>
 | 
			
		||||
        <thought>Virgin_OnlyForSpouse_Know_Taken</thought>
 | 
			
		||||
        <tag>Male, NotSpouse</tag>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="PreceptComp_SelfTookMemoryThought">
 | 
			
		||||
        <eventDef>Virgin_TookM</eventDef>
 | 
			
		||||
        <thought>TookVirginity</thought>
 | 
			
		||||
      </li>
 | 
			
		||||
    </comps>
 | 
			
		||||
  </PreceptDef>
 | 
			
		||||
 | 
			
		||||
  <PreceptDef>
 | 
			
		||||
    <defName>Virgin_ShamefulF</defName>
 | 
			
		||||
    <issue>Virginity_Female</issue>
 | 
			
		||||
    <label>shameful</label>
 | 
			
		||||
    <description>Remaining as virgin is shameful thing and being laughed at.</description>
 | 
			
		||||
    <impact>Medium</impact>
 | 
			
		||||
    <displayOrderInIssue>30</displayOrderInIssue>
 | 
			
		||||
    <displayOrderInImpact>1000</displayOrderInImpact>
 | 
			
		||||
    <defaultSelectionWeight>1</defaultSelectionWeight>
 | 
			
		||||
    <associatedMemes>
 | 
			
		||||
      <li>FemaleSupremacy</li>
 | 
			
		||||
    </associatedMemes>
 | 
			
		||||
    <comps>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>Virgin_TakenF</eventDef>
 | 
			
		||||
        <thought>Virgin_Shameful_Taken</thought>
 | 
			
		||||
        <tag>BeenRaped</tag>
 | 
			
		||||
        <exclusive>true</exclusive>
 | 
			
		||||
      </li>
 | 
			
		||||
    </comps>
 | 
			
		||||
  </PreceptDef>
 | 
			
		||||
 | 
			
		||||
  <PreceptDef>
 | 
			
		||||
    <defName>Virgin_ShamefulM</defName>
 | 
			
		||||
    <issue>Virginity_Male</issue>
 | 
			
		||||
    <label>shameful</label>
 | 
			
		||||
    <description>Remaining as virgin is shameful thing and being laughed at.</description>
 | 
			
		||||
    <impact>Medium</impact>
 | 
			
		||||
    <displayOrderInIssue>30</displayOrderInIssue>
 | 
			
		||||
    <displayOrderInImpact>1000</displayOrderInImpact>
 | 
			
		||||
    <defaultSelectionWeight>40</defaultSelectionWeight>
 | 
			
		||||
    <associatedMemes>
 | 
			
		||||
      <li>MaleSupremacy</li>
 | 
			
		||||
    </associatedMemes>
 | 
			
		||||
    <comps>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.PreceptComp_SelfTookThoughtTagged">
 | 
			
		||||
        <eventDef>Virgin_TakenM</eventDef>
 | 
			
		||||
        <thought>Virgin_Shameful_Taken</thought>
 | 
			
		||||
        <tag>BeenRaped</tag>
 | 
			
		||||
        <exclusive>true</exclusive>
 | 
			
		||||
      </li>
 | 
			
		||||
    </comps>
 | 
			
		||||
  </PreceptDef>
 | 
			
		||||
 | 
			
		||||
  <!-- Thoughts -->
 | 
			
		||||
 | 
			
		||||
  <ThoughtDef>
 | 
			
		||||
    <defName>Virgin_Precious_Taken_Forcefully</defName>
 | 
			
		||||
    <thoughtClass>Thought_MemorySocial</thoughtClass>
 | 
			
		||||
    <durationDays>30</durationDays>
 | 
			
		||||
    <stackLimit>1</stackLimit>
 | 
			
		||||
    <stages>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Lost virginity</label>
 | 
			
		||||
        <description>I lost my virginity forcefully.</description>
 | 
			
		||||
        <baseMoodEffect>-10</baseMoodEffect>
 | 
			
		||||
        <baseOpinionOffset>-200</baseOpinionOffset>
 | 
			
		||||
      </li>
 | 
			
		||||
    </stages>
 | 
			
		||||
  </ThoughtDef>
 | 
			
		||||
 | 
			
		||||
  <RJWSexperience.ThoughtDef_Opinionbased>
 | 
			
		||||
    <defName>Virgin_Precious_Taken</defName>
 | 
			
		||||
    <thoughtClass>RJWSexperience.Thought_Opinionbased</thoughtClass>
 | 
			
		||||
    <durationDays>7</durationDays>
 | 
			
		||||
    <stackLimit>1</stackLimit>
 | 
			
		||||
    <minimumValueforStage>
 | 
			
		||||
      <li>-100</li>
 | 
			
		||||
      <li>-50</li>
 | 
			
		||||
      <li>0</li>
 | 
			
		||||
      <li>75</li>
 | 
			
		||||
    </minimumValueforStage>
 | 
			
		||||
    <stages>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Lost virginity by {0}</label>
 | 
			
		||||
        <description>I am no longer virgin.</description>
 | 
			
		||||
        <baseMoodEffect>-5</baseMoodEffect>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Lost virginity by {0}</label>
 | 
			
		||||
        <description>I am no longer virgin.</description>
 | 
			
		||||
        <baseMoodEffect>-3</baseMoodEffect>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Lost virginity by {0}</label>
 | 
			
		||||
        <description>I am no longer virgin.</description>
 | 
			
		||||
        <baseMoodEffect>-1</baseMoodEffect>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Gave virginity to {0}</label>
 | 
			
		||||
        <description>I Gave my virginity to my love.</description>
 | 
			
		||||
        <baseMoodEffect>5</baseMoodEffect>
 | 
			
		||||
      </li>
 | 
			
		||||
    </stages>
 | 
			
		||||
  </RJWSexperience.ThoughtDef_Opinionbased>
 | 
			
		||||
 | 
			
		||||
  <RJWSexperience.ThoughtDef_Opinionbased>
 | 
			
		||||
    <defName>Virgin_Shameful_Taken</defName>
 | 
			
		||||
    <thoughtClass>RJWSexperience.Thought_Opinionbased</thoughtClass>
 | 
			
		||||
    <durationDays>7</durationDays>
 | 
			
		||||
    <stackLimit>1</stackLimit>
 | 
			
		||||
    <minimumValueforStage>
 | 
			
		||||
      <li>-100</li>
 | 
			
		||||
      <li>0</li>
 | 
			
		||||
      <li>75</li>
 | 
			
		||||
    </minimumValueforStage>
 | 
			
		||||
    <stages>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Lost virginity by {0}</label>
 | 
			
		||||
        <description>Finally!</description>
 | 
			
		||||
        <baseMoodEffect>5</baseMoodEffect>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Lost virginity by {0}</label>
 | 
			
		||||
        <description>Finally!</description>
 | 
			
		||||
        <baseMoodEffect>10</baseMoodEffect>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Lost virginity by {0}</label>
 | 
			
		||||
        <description>Finally!</description>
 | 
			
		||||
        <baseMoodEffect>20</baseMoodEffect>
 | 
			
		||||
      </li>
 | 
			
		||||
    </stages>
 | 
			
		||||
  </RJWSexperience.ThoughtDef_Opinionbased>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  <ThoughtDef>
 | 
			
		||||
    <defName>Virgin_OnlyForSpouse_Know_Taken</defName>
 | 
			
		||||
    <thoughtClass>Thought_MemorySocial</thoughtClass>
 | 
			
		||||
    <durationDays>30</durationDays>
 | 
			
		||||
    <stackLimit>100</stackLimit>
 | 
			
		||||
    <stackLimitForSameOtherPawn>3</stackLimitForSameOtherPawn>
 | 
			
		||||
    <nullifyingTraits>
 | 
			
		||||
      <li>Nymphomaniac</li>
 | 
			
		||||
    </nullifyingTraits>
 | 
			
		||||
    <stages>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>slut</label>
 | 
			
		||||
        <baseOpinionOffset>-30</baseOpinionOffset>
 | 
			
		||||
      </li>
 | 
			
		||||
    </stages>
 | 
			
		||||
  </ThoughtDef>
 | 
			
		||||
</Defs>
 | 
			
		||||
| 
						 | 
				
			
			@ -21,6 +21,17 @@
 | 
			
		|||
    <patternGroupTag/>
 | 
			
		||||
  </RitualPatternDef>
 | 
			
		||||
 | 
			
		||||
  <RitualPatternDef ParentName="GangbangBase">
 | 
			
		||||
    <defName>Gangbang_Consensual</defName>
 | 
			
		||||
    <ritualBehavior>Gangbang_Consensual</ritualBehavior>
 | 
			
		||||
    <shortDescOverride>gangbang</shortDescOverride>
 | 
			
		||||
    <descOverride>A ritualistic gangbang. The organizer will give a speech to excite the crowd, then fucked by the crowd.</descOverride>
 | 
			
		||||
    <iconPathOverride>UI/Issues/Gangbang_Consensual</iconPathOverride>
 | 
			
		||||
    <ritualOnlyForIdeoMembers>false</ritualOnlyForIdeoMembers>
 | 
			
		||||
    <ritualOutcomeEffect>Gangbang_Consensual</ritualOutcomeEffect>
 | 
			
		||||
    <patternGroupTag/>
 | 
			
		||||
  </RitualPatternDef>
 | 
			
		||||
 | 
			
		||||
  <RitualPatternDef ParentName="GangbangBase">
 | 
			
		||||
    <defName>GangbangByAnimal</defName>
 | 
			
		||||
    <ritualBehavior>GangbangByAnimal</ritualBehavior>
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +43,17 @@
 | 
			
		|||
    <patternGroupTag/>
 | 
			
		||||
  </RitualPatternDef>
 | 
			
		||||
  
 | 
			
		||||
  <RitualPatternDef ParentName="GangbangBase">
 | 
			
		||||
    <defName>GangbangByAnimal_Consensual</defName>
 | 
			
		||||
    <ritualBehavior>GangbangByAnimal_Consensual</ritualBehavior>
 | 
			
		||||
    <shortDescOverride>gangbang by animal</shortDescOverride>
 | 
			
		||||
    <descOverride>A ritualistic animal gangbang. The organizer will give a speech to excite the crowd, then animals begin fuck the organizer.</descOverride>
 | 
			
		||||
    <iconPathOverride>UI/Commands/Breeding_Pawn_on</iconPathOverride>
 | 
			
		||||
    <ritualOnlyForIdeoMembers>false</ritualOnlyForIdeoMembers>
 | 
			
		||||
    <ritualOutcomeEffect>BestialGangbang_Consensual</ritualOutcomeEffect>
 | 
			
		||||
    <patternGroupTag/>
 | 
			
		||||
  </RitualPatternDef>
 | 
			
		||||
  
 | 
			
		||||
  <RitualPatternDef ParentName="CelebrationConsumable">
 | 
			
		||||
    <defName>DrugOrgy</defName>
 | 
			
		||||
    <shortDescOverride>drug orgy</shortDescOverride>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,9 @@
 | 
			
		|||
<Defs>
 | 
			
		||||
 | 
			
		||||
  <RitualBehaviorDef Name="GangbangBehaviorBase" Abstract="True" ParentName="DateRitualBehavior">
 | 
			
		||||
    <preceptRequirements><li Class="PreceptRequirement_Altar"/></preceptRequirements>
 | 
			
		||||
    <preceptRequirements>
 | 
			
		||||
      <li Class="PreceptRequirement_Altar"/>
 | 
			
		||||
    </preceptRequirements>
 | 
			
		||||
    <durationTicks>7500</durationTicks>
 | 
			
		||||
    <roles Inherit="False">
 | 
			
		||||
      <li Class="RitualRoleTag">
 | 
			
		||||
| 
						 | 
				
			
			@ -84,7 +86,7 @@
 | 
			
		|||
        </roleBehaviors>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualStage_InteractWithVictim">
 | 
			
		||||
        <defaultDuty>Gangbang</defaultDuty>
 | 
			
		||||
        <defaultDuty>Gangbang_Rape</defaultDuty>
 | 
			
		||||
        <essential>True</essential>
 | 
			
		||||
        <endTriggers>
 | 
			
		||||
          <li Class="StageEndTrigger_DurationPercentage">
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +104,7 @@
 | 
			
		|||
        </roleBehaviors>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualStage_InteractWithVictim">
 | 
			
		||||
        <defaultDuty>Gangbang</defaultDuty>
 | 
			
		||||
        <defaultDuty>Gangbang_Rape</defaultDuty>
 | 
			
		||||
        <endTriggers>
 | 
			
		||||
          <li Class="StageEndTrigger_DurationPercentage">
 | 
			
		||||
            <percentage>0.1</percentage>
 | 
			
		||||
| 
						 | 
				
			
			@ -122,6 +124,85 @@
 | 
			
		|||
    </stages>
 | 
			
		||||
  </RitualBehaviorDef>
 | 
			
		||||
 | 
			
		||||
  <RitualBehaviorDef ParentName="GangbangBehaviorBase">
 | 
			
		||||
    <defName>Gangbang_Consensual</defName>
 | 
			
		||||
    <workerClass>RJWSexperience.Ideology.RitualBehaviorWorker_Gangbang_Consensual</workerClass>
 | 
			
		||||
    <stages Inherit="False">
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualStage_InteractWithInitiator">
 | 
			
		||||
        <defaultDuty>Spectate</defaultDuty>
 | 
			
		||||
        <endTriggers>
 | 
			
		||||
          <li Class="StageEndTrigger_RolesArrived">
 | 
			
		||||
            <roleIds>
 | 
			
		||||
              <li>initiator</li>
 | 
			
		||||
            </roleIds>
 | 
			
		||||
          </li>
 | 
			
		||||
        </endTriggers>
 | 
			
		||||
        <roleBehaviors>
 | 
			
		||||
          <li>
 | 
			
		||||
            <roleId>initiator</roleId>
 | 
			
		||||
            <dutyDef>ArriveToCell</dutyDef>
 | 
			
		||||
          </li>
 | 
			
		||||
        </roleBehaviors>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <defaultDuty>Spectate</defaultDuty>
 | 
			
		||||
        <endTriggers>
 | 
			
		||||
          <li Class="StageEndTrigger_DurationPercentage">
 | 
			
		||||
            <percentage>0.1</percentage>
 | 
			
		||||
          </li>
 | 
			
		||||
        </endTriggers>
 | 
			
		||||
        <roleBehaviors>
 | 
			
		||||
          <li>
 | 
			
		||||
            <roleId>initiator</roleId>
 | 
			
		||||
            <dutyDef>SpeakOnCellFacingSpectators</dutyDef>
 | 
			
		||||
            <speakerInteraction>Speech_Gangbang</speakerInteraction>
 | 
			
		||||
            <customPositions>
 | 
			
		||||
              <li Class="RitualPosition_Lectern">
 | 
			
		||||
                <maxDistanceToFocus>5</maxDistanceToFocus>
 | 
			
		||||
              </li>
 | 
			
		||||
              <li Class="RitualPosition_OnInteractionCell" />
 | 
			
		||||
            </customPositions>
 | 
			
		||||
          </li>
 | 
			
		||||
        </roleBehaviors>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualStage_InteractWithInitiator">
 | 
			
		||||
        <defaultDuty>Gangbang_Consensual</defaultDuty>
 | 
			
		||||
        <essential>True</essential>
 | 
			
		||||
        <endTriggers>
 | 
			
		||||
          <li Class="StageEndTrigger_DurationPercentage">
 | 
			
		||||
            <percentage>1.0</percentage>
 | 
			
		||||
          </li>
 | 
			
		||||
        </endTriggers>
 | 
			
		||||
        <roleBehaviors>
 | 
			
		||||
          <li>
 | 
			
		||||
            <roleId>initiator</roleId>
 | 
			
		||||
            <dutyDef>LayDownAwake</dutyDef>
 | 
			
		||||
            <customPositions>
 | 
			
		||||
              <li Class="RitualPosition_OnInteractionCell" />
 | 
			
		||||
            </customPositions>
 | 
			
		||||
          </li>
 | 
			
		||||
        </roleBehaviors>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualStage_InteractWithInitiator">
 | 
			
		||||
        <defaultDuty>Spectate</defaultDuty>
 | 
			
		||||
        <endTriggers>
 | 
			
		||||
          <li Class="StageEndTrigger_DurationPercentage">
 | 
			
		||||
            <percentage>0.1</percentage>
 | 
			
		||||
          </li>
 | 
			
		||||
        </endTriggers>
 | 
			
		||||
        <roleBehaviors>
 | 
			
		||||
          <li>
 | 
			
		||||
            <roleId>initiator</roleId>
 | 
			
		||||
            <dutyDef>SpeakOnCellFacingSpectators</dutyDef>
 | 
			
		||||
            <speakerInteraction>Speech_Gangbang</speakerInteraction>
 | 
			
		||||
            <customPositions>
 | 
			
		||||
              <li Class="RitualPosition_OnInteractionCell" />
 | 
			
		||||
            </customPositions>
 | 
			
		||||
          </li>
 | 
			
		||||
        </roleBehaviors>
 | 
			
		||||
      </li>
 | 
			
		||||
    </stages>
 | 
			
		||||
  </RitualBehaviorDef>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  <RitualBehaviorDef ParentName="GangbangBehaviorBase">
 | 
			
		||||
| 
						 | 
				
			
			@ -228,7 +309,7 @@
 | 
			
		|||
        <roleBehaviors>
 | 
			
		||||
          <li>
 | 
			
		||||
            <roleId>animal</roleId>
 | 
			
		||||
            <dutyDef>Gangbang</dutyDef>
 | 
			
		||||
            <dutyDef>Gangbang_Rape</dutyDef>
 | 
			
		||||
            <customPositions>
 | 
			
		||||
              <li Class="RitualPosition_OnInteractionCell" />
 | 
			
		||||
            </customPositions>
 | 
			
		||||
| 
						 | 
				
			
			@ -264,6 +345,105 @@
 | 
			
		|||
    </stages>
 | 
			
		||||
  </RitualBehaviorDef>
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  <RitualBehaviorDef ParentName="GangbangBehaviorBase">
 | 
			
		||||
    <defName>GangbangByAnimal_Consensual</defName>
 | 
			
		||||
    <workerClass>RJWSexperience.Ideology.RitualBehaviorWorker_Gangbang_Consensual</workerClass>
 | 
			
		||||
    <roles>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualRole_AnimalBreeder">
 | 
			
		||||
        <label>breeder</label>
 | 
			
		||||
        <id>animal</id>
 | 
			
		||||
        <maxCount>30</maxCount>
 | 
			
		||||
        <required>false</required>
 | 
			
		||||
        <missingDesc>a breedable animal</missingDesc>
 | 
			
		||||
        <countsAsParticipant>false</countsAsParticipant>
 | 
			
		||||
      </li>
 | 
			
		||||
    </roles>
 | 
			
		||||
    <stages Inherit="False">
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualStage_InteractWithInitiator">
 | 
			
		||||
        <defaultDuty>Spectate</defaultDuty>
 | 
			
		||||
        <endTriggers>
 | 
			
		||||
          <li Class="StageEndTrigger_RolesArrived">
 | 
			
		||||
            <roleIds>
 | 
			
		||||
              <li>initiator</li>
 | 
			
		||||
            </roleIds>
 | 
			
		||||
          </li>
 | 
			
		||||
        </endTriggers>
 | 
			
		||||
        <roleBehaviors>
 | 
			
		||||
          <li>
 | 
			
		||||
            <roleId>initiator</roleId>
 | 
			
		||||
            <dutyDef>ArriveToCell</dutyDef>
 | 
			
		||||
          </li>
 | 
			
		||||
        </roleBehaviors>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <defaultDuty>Spectate</defaultDuty>
 | 
			
		||||
        <endTriggers>
 | 
			
		||||
          <li Class="StageEndTrigger_DurationPercentage">
 | 
			
		||||
            <percentage>0.1</percentage>
 | 
			
		||||
          </li>
 | 
			
		||||
        </endTriggers>
 | 
			
		||||
        <roleBehaviors>
 | 
			
		||||
          <li>
 | 
			
		||||
            <roleId>initiator</roleId>
 | 
			
		||||
            <dutyDef>SpeakOnCellFacingSpectators</dutyDef>
 | 
			
		||||
            <speakerInteraction>Speech_Zoophile</speakerInteraction>
 | 
			
		||||
            <customPositions>
 | 
			
		||||
              <li Class="RitualPosition_Lectern">
 | 
			
		||||
                <maxDistanceToFocus>5</maxDistanceToFocus>
 | 
			
		||||
              </li>
 | 
			
		||||
              <li Class="RitualPosition_OnInteractionCell" />
 | 
			
		||||
            </customPositions>
 | 
			
		||||
          </li>
 | 
			
		||||
          <li>
 | 
			
		||||
            <roleId>animal</roleId>
 | 
			
		||||
            <dutyDef>Spectate</dutyDef>
 | 
			
		||||
          </li>
 | 
			
		||||
        </roleBehaviors>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualStage_InteractWithInitiator">
 | 
			
		||||
        <defaultDuty>Spectate</defaultDuty>
 | 
			
		||||
        <essential>True</essential>
 | 
			
		||||
        <endTriggers>
 | 
			
		||||
          <li Class="StageEndTrigger_DurationPercentage">
 | 
			
		||||
            <percentage>0.9</percentage>
 | 
			
		||||
          </li>
 | 
			
		||||
        </endTriggers>
 | 
			
		||||
        <roleBehaviors>
 | 
			
		||||
          <li>
 | 
			
		||||
            <roleId>animal</roleId>
 | 
			
		||||
            <dutyDef>Gangbang_Consensual</dutyDef>
 | 
			
		||||
            <customPositions>
 | 
			
		||||
              <li Class="RitualPosition_OnInteractionCell" />
 | 
			
		||||
            </customPositions>
 | 
			
		||||
          </li>
 | 
			
		||||
          <li>
 | 
			
		||||
            <roleId>initiator</roleId>
 | 
			
		||||
            <dutyDef>LayDownAwake</dutyDef>
 | 
			
		||||
          </li>
 | 
			
		||||
        </roleBehaviors>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <defaultDuty>Spectate</defaultDuty>
 | 
			
		||||
        <endTriggers>
 | 
			
		||||
          <li Class="StageEndTrigger_DurationPercentage">
 | 
			
		||||
            <percentage>0.1</percentage>
 | 
			
		||||
          </li>
 | 
			
		||||
        </endTriggers>
 | 
			
		||||
        <roleBehaviors>
 | 
			
		||||
          <li>
 | 
			
		||||
            <roleId>initiator</roleId>
 | 
			
		||||
            <dutyDef>SpeakOnCellFacingSpectators</dutyDef>
 | 
			
		||||
            <speakerInteraction>Speech_Zoophile</speakerInteraction>
 | 
			
		||||
            <customPositions>
 | 
			
		||||
              <li Class="RitualPosition_OnInteractionCell" />
 | 
			
		||||
            </customPositions>
 | 
			
		||||
          </li>
 | 
			
		||||
        </roleBehaviors>
 | 
			
		||||
      </li>
 | 
			
		||||
    </stages>
 | 
			
		||||
  </RitualBehaviorDef>
 | 
			
		||||
 | 
			
		||||
  <RitualBehaviorDef ParentName="DateRitualBehavior">
 | 
			
		||||
    <defName>DrugOrgy</defName>
 | 
			
		||||
    <durationTicks>7500</durationTicks>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,31 +32,37 @@
 | 
			
		|||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualOutcomeComp_HediffBased">
 | 
			
		||||
        <label>victim broken</label>
 | 
			
		||||
        <qualityOffset>0.2</qualityOffset>
 | 
			
		||||
        <qualityOffset>0.15</qualityOffset>
 | 
			
		||||
        <hediffDef>FeelingBroken</hediffDef>
 | 
			
		||||
        <minSeverity>0.3</minSeverity>
 | 
			
		||||
        <roleId>victim</roleId>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualOutcomeComp_HediffBased">
 | 
			
		||||
        <label>victim extremly broken</label>
 | 
			
		||||
        <qualityOffset>0.2</qualityOffset>
 | 
			
		||||
        <qualityOffset>0.15</qualityOffset>
 | 
			
		||||
        <hediffDef>FeelingBroken</hediffDef>
 | 
			
		||||
        <minSeverity>0.5</minSeverity>
 | 
			
		||||
        <roleId>victim</roleId>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualOutcomeComp_HediffBased">
 | 
			
		||||
        <label>victim completely broken</label>
 | 
			
		||||
        <qualityOffset>0.4</qualityOffset>
 | 
			
		||||
        <qualityOffset>0.3</qualityOffset>
 | 
			
		||||
        <hediffDef>FeelingBroken</hediffDef>
 | 
			
		||||
        <minSeverity>0.9</minSeverity>
 | 
			
		||||
        <roleId>victim</roleId>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualOutcomeComp_NeedBased">
 | 
			
		||||
        <label>statisfied participants</label>
 | 
			
		||||
        <qualityOffset>0.2</qualityOffset>
 | 
			
		||||
        <qualityOffset>0.4</qualityOffset>
 | 
			
		||||
        <needDef>Sex</needDef>
 | 
			
		||||
        <minAvgNeed>0.7</minAvgNeed>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualOutcomeComp_NeedBased">
 | 
			
		||||
        <label>completly statisfied participants</label>
 | 
			
		||||
        <qualityOffset>0.4</qualityOffset>
 | 
			
		||||
        <needDef>Sex</needDef>
 | 
			
		||||
        <minAvgNeed>0.9</minAvgNeed>
 | 
			
		||||
      </li>
 | 
			
		||||
    </comps>
 | 
			
		||||
    <outcomeChances>
 | 
			
		||||
      <li>
 | 
			
		||||
| 
						 | 
				
			
			@ -92,6 +98,82 @@
 | 
			
		|||
    </outcomeChances>
 | 
			
		||||
  </RitualOutcomeEffectDef>
 | 
			
		||||
  
 | 
			
		||||
  <RitualOutcomeEffectDef>
 | 
			
		||||
    <defName>Gangbang_Consensual</defName>
 | 
			
		||||
    <description>Depending on ritual quality, participants will get between {MINMOOD} and {MAXMOOD} mood for {MOODDAYS} days.</description>
 | 
			
		||||
    <workerClass>RitualOutcomeEffectWorker_Consumable</workerClass>
 | 
			
		||||
    <extraPredictedOutcomeDescriptions>
 | 
			
		||||
      <li>If the {0} is satisfying, one of the participants might gain an inspiration.</li>
 | 
			
		||||
    </extraPredictedOutcomeDescriptions>
 | 
			
		||||
    <comps>
 | 
			
		||||
      <li Class="RitualOutcomeComp_RolePresentNotSubstituted">
 | 
			
		||||
        <roleId>initiator</roleId>
 | 
			
		||||
        <label>moral guide present</label>
 | 
			
		||||
        <qualityOffset>0.10</qualityOffset>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RitualOutcomeComp_ParticipantCount">
 | 
			
		||||
        <label>participant count</label>
 | 
			
		||||
        <curve>
 | 
			
		||||
          <points>
 | 
			
		||||
            <li>(1,  -0.20)</li>
 | 
			
		||||
            <li>(3,  -0.05)</li>
 | 
			
		||||
            <li>(5, 0.05)</li>
 | 
			
		||||
            <li>(10, 0.10)</li>
 | 
			
		||||
          </points>
 | 
			
		||||
        </curve>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RitualOutcomeComp_RitualTargetDefs">
 | 
			
		||||
        <allowAltars>true</allowAltars>
 | 
			
		||||
        <label>started at altar</label>
 | 
			
		||||
        <qualityOffset>0.2</qualityOffset>
 | 
			
		||||
        <expectedThingLabelTip>an altar</expectedThingLabelTip>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualOutcomeComp_NeedBased">
 | 
			
		||||
        <label>statisfied participants</label>
 | 
			
		||||
        <qualityOffset>0.4</qualityOffset>
 | 
			
		||||
        <needDef>Sex</needDef>
 | 
			
		||||
        <minAvgNeed>0.7</minAvgNeed>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualOutcomeComp_NeedBased">
 | 
			
		||||
        <label>completly statisfied participants</label>
 | 
			
		||||
        <qualityOffset>1.0</qualityOffset>
 | 
			
		||||
        <needDef>Sex</needDef>
 | 
			
		||||
        <minAvgNeed>0.8</minAvgNeed>
 | 
			
		||||
      </li>
 | 
			
		||||
    </comps>
 | 
			
		||||
    <outcomeChances>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Terrible</label>
 | 
			
		||||
        <chance>0.05</chance>
 | 
			
		||||
        <memory>TerribleGangbang</memory>
 | 
			
		||||
        <description>The {0} was terrible! The speech was stuttering and incoherent, and the victim was botched - everyone was waiting for it to end.</description>
 | 
			
		||||
        <positivityIndex>-2</positivityIndex>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Boring</label>
 | 
			
		||||
        <chance>0.10</chance>
 | 
			
		||||
        <memory>BoringGangbang</memory>
 | 
			
		||||
        <description>The {0} was boring. The speech was repetitive and the victim was noticeably flawed. It just didn't feel dignified.</description>
 | 
			
		||||
        <positivityIndex>-1</positivityIndex>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Satisfying</label>
 | 
			
		||||
        <chance>0.6</chance>
 | 
			
		||||
        <memory>FunGangbang</memory>
 | 
			
		||||
        <description>The {0} was satisfying. The speech felt meaningful, and the victim was precise and dignified.</description>
 | 
			
		||||
        <potentialExtraOutcomeDesc>There's a 5% chance that a random participant gets an inspiration.</potentialExtraOutcomeDesc>
 | 
			
		||||
        <positivityIndex>1</positivityIndex>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Spectacular</label>
 | 
			
		||||
        <chance>0.25</chance>
 | 
			
		||||
        <memory>UnforgettableGangbang</memory>
 | 
			
		||||
        <description>The {0} was spectacular! The speech brought everyone to the edge of a frenzy and the victim was like succubus.</description>
 | 
			
		||||
        <potentialExtraOutcomeDesc>There's a 10% chance that a random participant gets an inspiration.</potentialExtraOutcomeDesc>
 | 
			
		||||
        <positivityIndex>2</positivityIndex>
 | 
			
		||||
      </li>
 | 
			
		||||
    </outcomeChances>
 | 
			
		||||
  </RitualOutcomeEffectDef>
 | 
			
		||||
 | 
			
		||||
  <RitualOutcomeEffectDef>
 | 
			
		||||
    <defName>BestialGangbang</defName>
 | 
			
		||||
| 
						 | 
				
			
			@ -125,21 +207,21 @@
 | 
			
		|||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualOutcomeComp_HediffBased">
 | 
			
		||||
        <label>breedee broken</label>
 | 
			
		||||
        <qualityOffset>0.3</qualityOffset>
 | 
			
		||||
        <qualityOffset>0.45</qualityOffset>
 | 
			
		||||
        <hediffDef>FeelingBroken</hediffDef>
 | 
			
		||||
        <minSeverity>0.3</minSeverity>
 | 
			
		||||
        <roleId>victim</roleId>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualOutcomeComp_HediffBased">
 | 
			
		||||
        <label>breedee extremly broken</label>
 | 
			
		||||
        <qualityOffset>0.3</qualityOffset>
 | 
			
		||||
        <qualityOffset>0.45</qualityOffset>
 | 
			
		||||
        <hediffDef>FeelingBroken</hediffDef>
 | 
			
		||||
        <minSeverity>0.5</minSeverity>
 | 
			
		||||
        <roleId>victim</roleId>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RJWSexperience.Ideology.RitualOutcomeComp_HediffBased">
 | 
			
		||||
        <label>breedee completely broken</label>
 | 
			
		||||
        <qualityOffset>0.6</qualityOffset>
 | 
			
		||||
        <qualityOffset>0.8</qualityOffset>
 | 
			
		||||
        <hediffDef>FeelingBroken</hediffDef>
 | 
			
		||||
        <minSeverity>0.9</minSeverity>
 | 
			
		||||
        <roleId>victim</roleId>
 | 
			
		||||
| 
						 | 
				
			
			@ -179,6 +261,70 @@
 | 
			
		|||
    </outcomeChances>
 | 
			
		||||
  </RitualOutcomeEffectDef>
 | 
			
		||||
 | 
			
		||||
  <RitualOutcomeEffectDef>
 | 
			
		||||
    <defName>BestialGangbang_Consensual</defName>
 | 
			
		||||
    <description>Depending on ritual quality, participants will get between {MINMOOD} and {MAXMOOD} mood for {MOODDAYS} days.</description>
 | 
			
		||||
    <workerClass>RitualOutcomeEffectWorker_Consumable</workerClass>
 | 
			
		||||
    <extraPredictedOutcomeDescriptions>
 | 
			
		||||
      <li>If the {0} is satisfying, one of the participants might gain an inspiration.</li>
 | 
			
		||||
    </extraPredictedOutcomeDescriptions>
 | 
			
		||||
    <comps>
 | 
			
		||||
      <li Class="RitualOutcomeComp_RolePresentNotSubstituted">
 | 
			
		||||
        <roleId>initiator</roleId>
 | 
			
		||||
        <label>moral guide present</label>
 | 
			
		||||
        <qualityOffset>0.10</qualityOffset>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RitualOutcomeComp_ParticipantCount">
 | 
			
		||||
        <label>participant count</label>
 | 
			
		||||
        <curve>
 | 
			
		||||
          <points>
 | 
			
		||||
            <li>(1,  0.20)</li>
 | 
			
		||||
            <li>(3,  0.40)</li>
 | 
			
		||||
            <li>(5,  0.65)</li>
 | 
			
		||||
            <li>(10, 1.20)</li>
 | 
			
		||||
          </points>
 | 
			
		||||
        </curve>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li Class="RitualOutcomeComp_RitualTargetDefs">
 | 
			
		||||
        <allowAltars>true</allowAltars>
 | 
			
		||||
        <label>started at altar</label>
 | 
			
		||||
        <qualityOffset>0.2</qualityOffset>
 | 
			
		||||
        <expectedThingLabelTip>an altar</expectedThingLabelTip>
 | 
			
		||||
      </li>
 | 
			
		||||
    </comps>
 | 
			
		||||
    <outcomeChances>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Terrible</label>
 | 
			
		||||
        <chance>0.05</chance>
 | 
			
		||||
        <memory>TerribleGangbang</memory>
 | 
			
		||||
        <description>The {0} was terrible! The speech was stuttering and incoherent, and the victim was botched - everyone was waiting for it to end.</description>
 | 
			
		||||
        <positivityIndex>-2</positivityIndex>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Boring</label>
 | 
			
		||||
        <chance>0.10</chance>
 | 
			
		||||
        <memory>BoringGangbang</memory>
 | 
			
		||||
        <description>The {0} was boring. The speech was repetitive and the victim was noticeably flawed. It just didn't feel dignified.</description>
 | 
			
		||||
        <positivityIndex>-1</positivityIndex>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Satisfying</label>
 | 
			
		||||
        <chance>0.65</chance>
 | 
			
		||||
        <memory>FunGangbang</memory>
 | 
			
		||||
        <description>The {0} was satisfying. The speech felt meaningful, and the victim was precise and dignified.</description>
 | 
			
		||||
        <potentialExtraOutcomeDesc>There's a 5% chance that a random participant gets an inspiration.</potentialExtraOutcomeDesc>
 | 
			
		||||
        <positivityIndex>1</positivityIndex>
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
        <label>Spectacular</label>
 | 
			
		||||
        <chance>0.2</chance>
 | 
			
		||||
        <memory>UnforgettableGangbang</memory>
 | 
			
		||||
        <description>The {0} was spectacular! The speech brought everyone to the edge of a frenzy and the victim was like succubus.</description>
 | 
			
		||||
        <potentialExtraOutcomeDesc>There's a 10% chance that a random participant gets an inspiration.</potentialExtraOutcomeDesc>
 | 
			
		||||
        <positivityIndex>2</positivityIndex>
 | 
			
		||||
      </li>
 | 
			
		||||
    </outcomeChances>
 | 
			
		||||
  </RitualOutcomeEffectDef>
 | 
			
		||||
 | 
			
		||||
  <RitualOutcomeEffectDef>
 | 
			
		||||
    <defName>DrugOrgy</defName>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										
											BIN
										
									
								
								RJWSexperience_Ideology/Textures/UI/Issues/Female.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 5.5 KiB  | 
| 
		 After Width: | Height: | Size: 13 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								RJWSexperience_Ideology/Textures/UI/Issues/Gender.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 6.1 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								RJWSexperience_Ideology/Textures/UI/Issues/Male.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.5 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Textures/UI/Icon/FirstBG.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 5.2 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Textures/UI/Icon/Incest.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.4 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Textures/UI/Icon/RSLocked.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.9 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Textures/UI/Icon/RSUnlocked.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.9 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Textures/UI/Icon/UnknownPawn.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.8 KiB  | 
| 
						 | 
				
			
			@ -1,7 +1,22 @@
 | 
			
		|||
Version Beta 1.0.2.0
 | 
			
		||||
This update will mess your pawn's record. Use debug tools.
 | 
			
		||||
 - requires RimWorld 1.3.3117 or later
 | 
			
		||||
 - requires RJW 4.8.1 or later
 | 
			
		||||
 - submissive gender can be designated as comfort
 | 
			
		||||
 - added virgin
 | 
			
		||||
 - added sex history
 | 
			
		||||
 - 
 | 
			
		||||
 - added virgin precept
 | 
			
		||||
 - added hymenoplasty(hymen restoration surgery)
 | 
			
		||||
 - added sex history(not applied retroactively)
 | 
			
		||||
   - you can change hotkey in keyboard configuration(default: none)
 | 
			
		||||
 - can collect cum on body
 | 
			
		||||
 - cum can spill out from cum buckets if over the stack count
 | 
			
		||||
 - fixed disabling sex record generation was not worked
 | 
			
		||||
 - removed lust adjustment from precepts that causing massive lust increment
 | 
			
		||||
 - changed gangbang condition
 | 
			
		||||
 - now pawns will go to the nearest cum bucket when cleaning self or masturbating
 | 
			
		||||
 - added consensual ganbang rituals(requires lewd meme)
 | 
			
		||||
 - non-consensual animal gangbang requires both rapist and zoophile memes
 | 
			
		||||
 - adjusted gangbang outcome values
 | 
			
		||||
 | 
			
		||||
Version Beta 1.0.1.11b
 | 
			
		||||
 - fixed erros on masturbations
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||