1.5 support
no cum rendering
							
								
								
									
										
											BIN
										
									
								
								1.5/Assemblies/0Harmony.dll
									
										
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										3693
									
								
								1.5/Assemblies/0Harmony.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								1.5/Assemblies/RimJobWorldCum.dll
									
										
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										49
									
								
								1.5/Defs/HediffsDef/Hediff_CumController.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
<Defs>
 | 
			
		||||
	<!--master hediff adding up the smaller Cum splatches-->
 | 
			
		||||
	<HediffDef>
 | 
			
		||||
		<defName>Hediff_CumController</defName>
 | 
			
		||||
		<hediffClass>rjwcum.Hediff_CumController</hediffClass>
 | 
			
		||||
		<label>Cum</label>
 | 
			
		||||
		<description>Covered in cum.</description>
 | 
			
		||||
		<makesSickThought>false</makesSickThought>
 | 
			
		||||
		<initialSeverity>0.01</initialSeverity>
 | 
			
		||||
		<maxSeverity>1</maxSeverity>
 | 
			
		||||
		<!--<injuryProps>-->
 | 
			
		||||
				<!--<canMerge>true</canMerge>--><!-- this might not even be required-->
 | 
			
		||||
		<!--</injuryProps>-->
 | 
			
		||||
		<!--<scenarioCanAdd>true</scenarioCanAdd>-->
 | 
			
		||||
		<isBad>false</isBad>
 | 
			
		||||
		<tendable>false</tendable>
 | 
			
		||||
		<stages>
 | 
			
		||||
			<li>
 | 
			
		||||
				<label>minor</label>
 | 
			
		||||
				<becomeVisible>false</becomeVisible>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li>
 | 
			
		||||
				<minSeverity>0.3</minSeverity>
 | 
			
		||||
				<label>little</label>
 | 
			
		||||
				<statOffsets>
 | 
			
		||||
					<Vulnerability>0.2</Vulnerability>
 | 
			
		||||
					<SocialImpact>-0.1</SocialImpact>
 | 
			
		||||
				</statOffsets>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li>
 | 
			
		||||
				<minSeverity>0.6</minSeverity>
 | 
			
		||||
				<label>extensive</label>
 | 
			
		||||
				<statOffsets>
 | 
			
		||||
					<Vulnerability>0.3</Vulnerability>			
 | 
			
		||||
					<SocialImpact>-0.3</SocialImpact>
 | 
			
		||||
				</statOffsets>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li>
 | 
			
		||||
				<minSeverity>0.8</minSeverity>
 | 
			
		||||
				<label>full</label>
 | 
			
		||||
				<statOffsets>
 | 
			
		||||
					<Vulnerability>-0.1</Vulnerability><!--pawns prefer victims not being completely drenched-->
 | 
			
		||||
					<SocialImpact>-0.5</SocialImpact>
 | 
			
		||||
				</statOffsets>
 | 
			
		||||
			</li>
 | 
			
		||||
		</stages>
 | 
			
		||||
	</HediffDef>
 | 
			
		||||
</Defs>
 | 
			
		||||
							
								
								
									
										72
									
								
								1.5/Defs/HediffsDef/Hediffs_Cum.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
<Defs>
 | 
			
		||||
	<HediffDef Name="Hediff_Cum_Base" Abstract="True">
 | 
			
		||||
		<hediffClass>rjwcum.Hediff_Cum</hediffClass>	
 | 
			
		||||
		<defName>Hediff_Cum</defName>
 | 
			
		||||
		<label>Cum</label>
 | 
			
		||||
		<labelNoun>cum</labelNoun>
 | 
			
		||||
		<description>cum.</description>
 | 
			
		||||
		<labelNounPretty>cum on {1}</labelNounPretty>
 | 
			
		||||
		<defaultLabelColor>(0.95,0.95,0.95)</defaultLabelColor>	
 | 
			
		||||
		<isBad>false</isBad>
 | 
			
		||||
		<tendable>false</tendable>
 | 
			
		||||
		<makesSickThought>false</makesSickThought>
 | 
			
		||||
		<makesAlert>false</makesAlert>	
 | 
			
		||||
		<maxSeverity>1</maxSeverity>
 | 
			
		||||
		<initialSeverity>0.001</initialSeverity>
 | 
			
		||||
		<injuryProps>
 | 
			
		||||
			<canMerge>true</canMerge>
 | 
			
		||||
		</injuryProps>	
 | 
			
		||||
		<stages>
 | 
			
		||||
			<li>
 | 
			
		||||
				<label>little</label>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li>
 | 
			
		||||
				<minSeverity>0.25</minSeverity>
 | 
			
		||||
				<label>some</label>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li>
 | 
			
		||||
				<minSeverity>0.5</minSeverity>
 | 
			
		||||
				<label>dripping</label>
 | 
			
		||||
			</li>
 | 
			
		||||
			<li>
 | 
			
		||||
				<minSeverity>0.8</minSeverity>
 | 
			
		||||
				<label>drenched</label>
 | 
			
		||||
			</li>
 | 
			
		||||
		</stages>	
 | 
			
		||||
		<comps>
 | 
			
		||||
			<li Class="HediffCompProperties_SelfHeal">
 | 
			
		||||
				<!--0.01*100*1800/60.0000-->
 | 
			
		||||
				<healIntervalTicksStanding>1800</healIntervalTicksStanding><!-- 1 day = 60.000 ticks -->
 | 
			
		||||
				<healAmount>0.01</healAmount><!--dries by itself, completely drying from 1.0 to 0.0 takes ~72h-->
 | 
			
		||||
			</li>
 | 
			
		||||
		</comps>	
 | 
			
		||||
	</HediffDef>
 | 
			
		||||
	
 | 
			
		||||
	<HediffDef ParentName="Hediff_Cum_Base">
 | 
			
		||||
		<defName>Hediff_Cum</defName>
 | 
			
		||||
		<label>Cum</label>
 | 
			
		||||
		<labelNoun>cum</labelNoun>
 | 
			
		||||
		<description>cum</description>
 | 
			
		||||
		<labelNounPretty>cum on {1}</labelNounPretty>
 | 
			
		||||
		<defaultLabelColor>(0.95,0.95,0.95)</defaultLabelColor>	
 | 
			
		||||
	</HediffDef>
 | 
			
		||||
	
 | 
			
		||||
	<HediffDef ParentName="Hediff_Cum_Base">	
 | 
			
		||||
		<defName>Hediff_InsectSpunk</defName>
 | 
			
		||||
		<description>Insect spunk.</description>
 | 
			
		||||
		<label>insect spunk</label>
 | 
			
		||||
		<labelNoun>insect spunk</labelNoun>
 | 
			
		||||
		<labelNounPretty>insect spunk on {1}</labelNounPretty>
 | 
			
		||||
		<defaultLabelColor>(0.6,0.83,0.35)</defaultLabelColor>	
 | 
			
		||||
	</HediffDef>
 | 
			
		||||
	
 | 
			
		||||
	<HediffDef ParentName="Hediff_Cum_Base">	
 | 
			
		||||
		<defName>Hediff_MechaFluids</defName>
 | 
			
		||||
		<description>Mechanoid fluids.</description>
 | 
			
		||||
		<label>mechanoid fluids</label>
 | 
			
		||||
		<labelNoun>mechanoid fluids</labelNoun>
 | 
			
		||||
		<labelNounPretty>mecha fluids on {1}</labelNounPretty>
 | 
			
		||||
		<defaultLabelColor>(0.37,0.71,0.82)</defaultLabelColor>	
 | 
			
		||||
	</HediffDef>	
 | 
			
		||||
</Defs>
 | 
			
		||||
							
								
								
									
										10
									
								
								1.5/Defs/JobDefs/Jobs_CleanSelf.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
 | 
			
		||||
<Defs>
 | 
			
		||||
	<JobDef>
 | 
			
		||||
		<defName>CleanSelf</defName>
 | 
			
		||||
		<driverClass>rjwcum.JobDriver_CleanSelf</driverClass>
 | 
			
		||||
		<reportString>cleaning self</reportString>
 | 
			
		||||
		<casualInterruptible>true</casualInterruptible>
 | 
			
		||||
	</JobDef>
 | 
			
		||||
</Defs>
 | 
			
		||||
							
								
								
									
										16
									
								
								1.5/Defs/WorkGiverDefs/WorkGivers_CleanSelf.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8" ?>
 | 
			
		||||
<Defs>
 | 
			
		||||
	<WorkGiverDef>
 | 
			
		||||
		<defName>CleanSelf</defName>
 | 
			
		||||
		<label>clean self</label>
 | 
			
		||||
		<giverClass>rjwcum.WorkGiver_CleanSelf</giverClass>
 | 
			
		||||
		<workType>Cleaning</workType>
 | 
			
		||||
		<verb>clean self</verb>
 | 
			
		||||
		<gerund>cleaning self</gerund>
 | 
			
		||||
		<scanCells>false</scanCells>
 | 
			
		||||
		<priorityInType>11</priorityInType><!-- slightly higher than normal cleaning (relatively unimportant)-->
 | 
			
		||||
		<requiredCapacities>
 | 
			
		||||
			<li>Manipulation</li>
 | 
			
		||||
		</requiredCapacities>
 | 
			
		||||
	</WorkGiverDef>
 | 
			
		||||
</Defs>
 | 
			
		||||
							
								
								
									
										15
									
								
								1.5/Languages/English/Keyed/Cum.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<LanguageData>
 | 
			
		||||
		<debug>Debug</debug>
 | 
			
		||||
		<debug_desc></debug_desc>
 | 
			
		||||
		<cum_on_body>Enable cum on body (Hediffs)</cum_on_body>
 | 
			
		||||
		<cum_on_body_desc>Enables cum hediffs in health tab.</cum_on_body_desc>
 | 
			
		||||
		<cum_on_body_amount>Adjust cum amount on body</cum_on_body_amount>
 | 
			
		||||
		<cum_on_body_amount_desc>All cum applied to pawn bodies will be multiplied by this amount. </cum_on_body_amount_desc>
 | 
			
		||||
		<cum_overlays>Enable cum overlays (Visuals)</cum_overlays>
 | 
			
		||||
		<cum_overlays_desc>Enables cum overlay for pawn drawer(may have conflicts with mods that change pawn appearance and other issues).\nRequires Cum on body option enabled.</cum_overlays_desc>
 | 
			
		||||
		<manual_hero_CleanSelf>Hero manual CleanSelf</manual_hero_CleanSelf>
 | 
			
		||||
		<manual_hero_CleanSelf_desc>Hero pawn will only clean cum from body if manually told so.</manual_hero_CleanSelf_desc>
 | 
			
		||||
		<dubsDBH_block_CleanSelf>DubsBadHygiene block CleanSelf</dubsDBH_block_CleanSelf>
 | 
			
		||||
		<dubsDBH_block_CleanSelf_desc>If DubsBadHygiene installed, pawns will only clean cum from body in buckets, showers, baths, hottubs etc.</dubsDBH_block_CleanSelf_desc>
 | 
			
		||||
</LanguageData>
 | 
			
		||||
							
								
								
									
										20
									
								
								1.5/Patches/FacialAnimation_compatibility.xml
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<Patch>
 | 
			
		||||
  <Operation Class="PatchOperationFindMod">
 | 
			
		||||
    <mods>
 | 
			
		||||
      <li>[NL] Facial Animation - WIP</li>
 | 
			
		||||
    </mods>
 | 
			
		||||
    <match Class="PatchOperationSequence">
 | 
			
		||||
      <success>Always</success>
 | 
			
		||||
      <operations>
 | 
			
		||||
        <li Class="PatchOperationAdd">
 | 
			
		||||
          <xpath>/Defs/FacialAnimation.FaceAnimationDef[defName="Wear" or defName="Wear2" or defName="Wear3"]/targetJobs</xpath>
 | 
			
		||||
          <success>Always</success>
 | 
			
		||||
          <value>
 | 
			
		||||
            <li>CleanSelf</li>
 | 
			
		||||
          </value>
 | 
			
		||||
        </li>
 | 
			
		||||
      </operations>
 | 
			
		||||
    </match>
 | 
			
		||||
  </Operation>
 | 
			
		||||
</Patch>
 | 
			
		||||
							
								
								
									
										53
									
								
								1.5/Source/Mod/CumBase.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
using System;
 | 
			
		||||
using HugsLib;
 | 
			
		||||
using HugsLib.Settings;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwcum
 | 
			
		||||
{
 | 
			
		||||
	public class CumBase : ModBase
 | 
			
		||||
	{
 | 
			
		||||
		public override string ModIdentifier
 | 
			
		||||
		{
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return "RJW_Cum";
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static SettingHandle<bool> debug;
 | 
			
		||||
		public static SettingHandle<bool> cum_on_body;
 | 
			
		||||
		public static SettingHandle<bool> cum_overlays;
 | 
			
		||||
		public static SettingHandle<float> cum_on_body_amount;
 | 
			
		||||
		public static SettingHandle<bool> manual_hero_CleanSelf;
 | 
			
		||||
		public static SettingHandle<bool> dubsDBH_block_CleanSelf;
 | 
			
		||||
 | 
			
		||||
		public override void DefsLoaded()
 | 
			
		||||
		{
 | 
			
		||||
			debug = Settings.GetHandle("debug",
 | 
			
		||||
									Translator.Translate("debug"),
 | 
			
		||||
									Translator.Translate("debug_desc"),
 | 
			
		||||
									false);
 | 
			
		||||
			cum_on_body = Settings.GetHandle("cum_on_body",
 | 
			
		||||
									Translator.Translate("cum_on_body"),
 | 
			
		||||
									Translator.Translate("cum_on_body_desc"),
 | 
			
		||||
									true);
 | 
			
		||||
			cum_overlays = Settings.GetHandle("cum_overlays",
 | 
			
		||||
									 Translator.Translate("cum_overlays"),
 | 
			
		||||
									 Translator.Translate("cum_overlays_desc"),
 | 
			
		||||
									 true);
 | 
			
		||||
			cum_on_body_amount = Settings.GetHandle("cum_on_body_amount",
 | 
			
		||||
										   Translator.Translate("cum_on_body_amount"),
 | 
			
		||||
										   Translator.Translate("cum_on_body_amount_desc"),
 | 
			
		||||
										   1.0f);
 | 
			
		||||
			manual_hero_CleanSelf = Settings.GetHandle("manual_hero_CleanSelf",
 | 
			
		||||
									 Translator.Translate("manual_hero_CleanSelf"),
 | 
			
		||||
									 Translator.Translate("manual_hero_CleanSelf_desc"),
 | 
			
		||||
									 true);
 | 
			
		||||
			dubsDBH_block_CleanSelf = Settings.GetHandle("dubsDBH_block_CleanSelf",
 | 
			
		||||
									 Translator.Translate("dubsDBH_block_CleanSelf"),
 | 
			
		||||
									 Translator.Translate("dubsDBH_block_CleanSelf_desc"),
 | 
			
		||||
									 true);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										622
									
								
								1.5/Source/Mod/CumHelper.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,622 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
using HarmonyLib;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
//using Multiplayer.API;
 | 
			
		||||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace rjwcum
 | 
			
		||||
{
 | 
			
		||||
	[StaticConstructorOnStartup]
 | 
			
		||||
	public static class CumHelper
 | 
			
		||||
	{
 | 
			
		||||
		/*
 | 
			
		||||
		contains many important functions of use to the other classes
 | 
			
		||||
		*/
 | 
			
		||||
 | 
			
		||||
		//amount of cum per sex act:
 | 
			
		||||
 | 
			
		||||
		public static readonly Dictionary<key, values> splatchAdjust;//saves x (horizontal) and z (vertical) adjustments of texture positiion for each unique combination of bodyType and bodyPart
 | 
			
		||||
		public static readonly Dictionary<key_layer, values_layer> layerAdjust;//saves y adjustments (drawing plane) for left/right appendages + bodyPart combinations to hide spunk if pawn looks in the wrong direction
 | 
			
		||||
 | 
			
		||||
		//structs are used to pack related variables together - used as keys for the dictionaries
 | 
			
		||||
		public struct key//allows to save all unique combinations of bodyType and bodyPart
 | 
			
		||||
		{
 | 
			
		||||
			public readonly BodyTypeDef bodyType;
 | 
			
		||||
			public readonly BodyPartDef bodyPart;
 | 
			
		||||
			public key(BodyTypeDef bodyType, BodyPartDef bodyPart)
 | 
			
		||||
			{
 | 
			
		||||
				this.bodyType = bodyType;
 | 
			
		||||
				this.bodyPart = bodyPart;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//for the 4 directions, use arrays to store the different adjust for north, east, south, west (in that order)
 | 
			
		||||
		public struct values
 | 
			
		||||
		{
 | 
			
		||||
			public readonly float[] x;
 | 
			
		||||
			public readonly float[] z;
 | 
			
		||||
			//public readonly bool over_clothing;//on gentials: hide when clothes are worn - in case of the other body parts it can't be said (for now) if it was added on the clothing or not
 | 
			
		||||
			public values(float[] xAdjust, float[] zAdjust)
 | 
			
		||||
			{
 | 
			
		||||
				x = xAdjust;
 | 
			
		||||
				z = zAdjust;
 | 
			
		||||
				//this.over_clothing = over_clothing;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		public struct key_layer//used to save left/right appendage + bodyPart combinations
 | 
			
		||||
		{
 | 
			
		||||
			public readonly bool left_side;
 | 
			
		||||
			public readonly BodyPartDef bodyPart;
 | 
			
		||||
 | 
			
		||||
			public key_layer(bool left_side, BodyPartDef bodyPart)
 | 
			
		||||
			{
 | 
			
		||||
				this.left_side = left_side;
 | 
			
		||||
				this.bodyPart = bodyPart;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public struct values_layer//saves the y-adjustments for different body parts and sides -> e.g. allows hiding spunk on the right arm if pawn is looking to the left (aka west)
 | 
			
		||||
		{
 | 
			
		||||
			public readonly float[] y;
 | 
			
		||||
 | 
			
		||||
			public values_layer(float[] yAdjust)
 | 
			
		||||
			{
 | 
			
		||||
				y = yAdjust;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//get defs of the rjw parts
 | 
			
		||||
		public static BodyPartDef genitalsDef = BodyDefOf.Human.AllParts.Find(bpr => string.Equals(bpr.def.defName, "Genitals")).def;
 | 
			
		||||
		public static BodyPartDef anusDef = BodyDefOf.Human.AllParts.Find(bpr => string.Equals(bpr.def.defName, "Anus")).def;
 | 
			
		||||
		public static BodyPartDef chestDef = BodyDefOf.Human.AllParts.Find(bpr => string.Equals(bpr.def.defName, "Chest")).def;
 | 
			
		||||
		public static BodyPartDef JawDef = BodyDefOf.Human.AllParts.Find(bpr => string.Equals(bpr.def.defName, "Jaw")).def;
 | 
			
		||||
		public static BodyPartDef NeckDef = BodyDefOf.Human.AllParts.Find(bpr => string.Equals(bpr.def.defName, "Neck")).def;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		static CumHelper()
 | 
			
		||||
		{
 | 
			
		||||
			splatchAdjust = new Dictionary<key, values>();
 | 
			
		||||
			//maybe there is a more elegant way to save and load this data, but I don't know about it
 | 
			
		||||
 | 
			
		||||
			//structure explained: 
 | 
			
		||||
			//1) key: struct consisting of bodyType + bodyPart (= unique key for every combination of bodyType + part)
 | 
			
		||||
			//2) values: struct containing positioning information (xAdjust: horizontal positioning, yAdjust: vertical positioning, zAdjust: whether to draw above or below pawn
 | 
			
		||||
			//note: arms, hands, and legs (which are only visible from one direction) values need not be inverted between west and east
 | 
			
		||||
 | 
			
		||||
			//BodyType Thin
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Thin, BodyPartDefOf.Arm), new values(new float[] { -0.13f, 0.05f, 0.13f, 0.05f }, new float[] { 0f, 0f, 0f, 0f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Thin, BodyPartDefOf.Hand), new values(new float[] { -0.12f, 0.15f, 0.12f, 0.15f }, new float[] { -0.25f, -0.25f, -0.25f, -0.25f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Thin, BodyPartDefOf.Head), new values(new float[] { 0f, -0.23f, 0f, 0.23f }, new float[] { 0.37f, 0.35f, 0.33f, 0.35f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Thin, JawDef), new values(new float[] { 0f, -0.19f, 0f, 0.19f }, new float[] { 0.15f, 0.15f, 0.15f, 0.15f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Thin, BodyPartDefOf.Leg), new values(new float[] { -0.1f, 0.1f, 0.1f, 0.1f }, new float[] { -0.4f, -0.4f, -0.4f, -0.4f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Thin, NeckDef), new values(new float[] { 0f, -0.07f, 0f, 0.07f }, new float[] { 0.06f, 0.06f, 0.06f, 0.06f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Thin, BodyPartDefOf.Torso), new values(new float[] { 0f, 0f, 0f, 0f }, new float[] { -0.18f, -0.20f, -0.25f, -0.25f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Thin, genitalsDef), new values(new float[] { 0f, 0.01f, 0f, -0.01f }, new float[] { 0, -0.35f, -0.35f, -0.35f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Thin, anusDef), new values(new float[] { 0, 0.18f, 0, -0.18f }, new float[] { -0.42f, -0.35f, 0, -0.35f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Thin, chestDef), new values(new float[] { 0f, -0.1f, 0f, 0.1f }, new float[] { -0.06f, -0.05f, -0.06f, -0.05f }));
 | 
			
		||||
 | 
			
		||||
			//BodyType Female
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Female, BodyPartDefOf.Arm), new values(new float[] { -0.17f, 0f, 0.17f, 0f }, new float[] { 0f, 0f, 0f, 0f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Female, BodyPartDefOf.Hand), new values(new float[] { -0.17f, 0.1f, 0.17f, 0.1f }, new float[] { -0.25f, -0.25f, -0.25f, -0.25f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Female, BodyPartDefOf.Head), new values(new float[] { 0f, -0.23f, 0f, 0.23f }, new float[] { 0.37f, 0.35f, 0.33f, 0.35f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Female, JawDef), new values(new float[] { 0f, -0.19f, 0f, 0.19f }, new float[] { 0.15f, 0.15f, 0.15f, 0.15f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Female, BodyPartDefOf.Leg), new values(new float[] { -0.2f, 0.1f, 0.2f, 0.1f }, new float[] { -0.4f, -0.4f, -0.4f, -0.4f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Female, NeckDef), new values(new float[] { 0f, -0.07f, 0f, 0.07f }, new float[] { 0.06f, 0.06f, 0.06f, 0.06f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Female, BodyPartDefOf.Torso), new values(new float[] { 0f, -0.05f, 0f, 0.05f }, new float[] { -0.20f, -0.25f, -0.25f, -0.25f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Female, genitalsDef), new values(new float[] { 0f, -0.10f, 0f, 0.10f }, new float[] { 0, -0.42f, -0.45f, -0.42f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Female, anusDef), new values(new float[] { 0, 0.26f, 0, -0.26f }, new float[] { -0.42f, -0.35f, 0, -0.35f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Female, chestDef), new values(new float[] { 0f, -0.12f, 0f, 0.12f }, new float[] { -0.06f, -0.05f, -0.06f, -0.05f }));
 | 
			
		||||
 | 
			
		||||
			//BodyType Male
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Male, BodyPartDefOf.Arm), new values(new float[] { -0.21f, 0.05f, 0.21f, 0.05f }, new float[] { 0f, -0.02f, 0f, -0.02f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Male, BodyPartDefOf.Hand), new values(new float[] { -0.17f, 0.07f, 0.17f, 0.07f }, new float[] { -0.25f, -0.25f, -0.25f, -0.25f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Male, BodyPartDefOf.Head), new values(new float[] { 0f, -0.23f, 0f, 0.23f }, new float[] { 0.37f, 0.35f, 0.33f, 0.35f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Male, JawDef), new values(new float[] { 0f, -0.19f, 0f, 0.19f }, new float[] { 0.15f, 0.15f, 0.15f, 0.15f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Male, BodyPartDefOf.Leg), new values(new float[] { -0.17f, 0.07f, 0.17f, 0.07f }, new float[] { -0.4f, -0.4f, -0.4f, -0.4f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Male, NeckDef), new values(new float[] { 0f, -0.07f, 0f, 0.07f }, new float[] { 0.06f, 0.06f, 0.06f, 0.06f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Male, BodyPartDefOf.Torso), new values(new float[] { 0f, -0.05f, 0f, 0.05f }, new float[] { -0.20f, -0.25f, -0.25f, -0.25f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Male, genitalsDef), new values(new float[] { 0f, -0.07f, 0f, 0.07f }, new float[] { 0, -0.35f, -0.42f, -0.35f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Male, anusDef), new values(new float[] { 0, 0.17f, 0, -0.17f }, new float[] { -0.42f, -0.35f, 0, -0.35f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Male, chestDef), new values(new float[] { 0f, -0.16f, 0f, 0.16f }, new float[] { -0.06f, -0.05f, -0.06f, -0.05f }));
 | 
			
		||||
 | 
			
		||||
			//BodyType Hulk
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Hulk, BodyPartDefOf.Arm), new values(new float[] { -0.3f, 0.05f, 0.3f, 0.05f }, new float[] { 0f, -0.02f, 0f, -0.02f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Hulk, BodyPartDefOf.Hand), new values(new float[] { -0.22f, 0.07f, 0.22f, 0.07f }, new float[] { -0.28f, -0.28f, -0.28f, -0.28f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Hulk, BodyPartDefOf.Head), new values(new float[] { 0f, -0.23f, 0f, 0.23f }, new float[] { 0.37f, 0.35f, 0.33f, 0.35f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Hulk, JawDef), new values(new float[] { 0f, -0.19f, 0f, 0.19f }, new float[] { 0.15f, 0.15f, 0.15f, 0.15f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Hulk, BodyPartDefOf.Leg), new values(new float[] { -0.17f, 0.07f, 0.17f, 0.07f }, new float[] { -0.5f, -0.5f, -0.5f, -0.5f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Hulk, NeckDef), new values(new float[] { 0f, -0.07f, 0f, 0.07f }, new float[] { 0.06f, 0.06f, 0.06f, 0.06f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Hulk, BodyPartDefOf.Torso), new values(new float[] { 0f, -0.05f, 0f, 0.05f }, new float[] { -0.20f, -0.3f, -0.3f, -0.3f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Hulk, genitalsDef), new values(new float[] { 0f, -0.02f, 0f, 0.02f }, new float[] { 0, -0.55f, -0.55f, -0.55f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Hulk, anusDef), new values(new float[] { 0, 0.35f, 0, -0.35f }, new float[] { -0.5f, -0.5f, 0, -0.5f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Hulk, chestDef), new values(new float[] { 0f, -0.22f, 0f, 0.22f }, new float[] { -0.06f, -0.05f, -0.06f, -0.05f }));
 | 
			
		||||
 | 
			
		||||
			//BodyType Fat
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Fat, BodyPartDefOf.Arm), new values(new float[] { -0.3f, 0.05f, 0.3f, 0.05f }, new float[] { 0f, -0.02f, 0f, -0.02f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Fat, BodyPartDefOf.Hand), new values(new float[] { -0.32f, 0.07f, 0.32f, 0.07f }, new float[] { -0.28f, -0.28f, -0.28f, -0.28f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Fat, BodyPartDefOf.Head), new values(new float[] { 0f, -0.23f, 0f, 0.23f }, new float[] { 0.37f, 0.35f, 0.33f, 0.35f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Fat, JawDef), new values(new float[] { 0f, -0.19f, 0f, 0.19f }, new float[] { 0.15f, 0.15f, 0.15f, 0.15f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Fat, BodyPartDefOf.Leg), new values(new float[] { -0.17f, 0.07f, 0.17f, 0.07f }, new float[] { -0.45f, -0.45f, -0.45f, -0.45f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Fat, NeckDef), new values(new float[] { 0f, -0.07f, 0f, 0.07f }, new float[] { 0.06f, 0.06f, 0.06f, 0.06f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Fat, BodyPartDefOf.Torso), new values(new float[] { 0f, -0.15f, 0f, 0.15f }, new float[] { -0.20f, -0.3f, -0.3f, -0.3f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Fat, genitalsDef), new values(new float[] { 0f, -0.25f, 0f, 0.25f }, new float[] { 0, -0.45f, -0.50f, -0.45f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Fat, anusDef), new values(new float[] { 0, 0.35f, 0, -0.35f }, new float[] { -0.5f, -0.4f, 0, -0.4f }));
 | 
			
		||||
			splatchAdjust.Add(new key(BodyTypeDefOf.Fat, chestDef), new values(new float[] { 0f, -0.27f, 0f, 0.27f }, new float[] { -0.07f, -0.05f, -0.07f, -0.05f }));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			//now for the layer/plane adjustments:
 | 
			
		||||
			layerAdjust = new Dictionary<key_layer, values_layer>();
 | 
			
		||||
 | 
			
		||||
			//left body parts: 
 | 
			
		||||
			//in theory, all body parts not coming in pairs should have the bool as false -> be listed as right, so I wouldn't need to add them here, but it doesn't hurt to be safe
 | 
			
		||||
			layerAdjust.Add(new key_layer(true, BodyPartDefOf.Arm), new values_layer(new float[] { 0f, -99f, 0f, 0f }));//0.00 = drawn over body (=visible) if the pawn looks in any direction except west, in which case it's hidden (-99)
 | 
			
		||||
			layerAdjust.Add(new key_layer(true, BodyPartDefOf.Hand), new values_layer(new float[] { 0f, -99f, 0f, 0f }));
 | 
			
		||||
			layerAdjust.Add(new key_layer(true, BodyPartDefOf.Leg), new values_layer(new float[] { 0f, -99f, 0f, 0f }));
 | 
			
		||||
 | 
			
		||||
			layerAdjust.Add(new key_layer(true, BodyPartDefOf.Head), new values_layer(new float[] { 0.02f, 0.02f, 0.02f, 0.02f }));//drawn from all directions, 0.02 = over hair
 | 
			
		||||
			layerAdjust.Add(new key_layer(true, JawDef), new values_layer(new float[] { -9f, 0.01f, 0.01f, 0.01f }));//0.01 = drawn over head but under hair, only hidden if facing north
 | 
			
		||||
			layerAdjust.Add(new key_layer(true, NeckDef), new values_layer(new float[] { 0f, 0f, 0f, 0f }));
 | 
			
		||||
			layerAdjust.Add(new key_layer(true, BodyPartDefOf.Torso), new values_layer(new float[] { 0f, 0f, 0f, 0f }));
 | 
			
		||||
			layerAdjust.Add(new key_layer(true, genitalsDef), new values_layer(new float[] { -99f, 0f, 0f, 0f }));//only hidden if facing north
 | 
			
		||||
			layerAdjust.Add(new key_layer(true, anusDef), new values_layer(new float[] { 0f, 0f, -99f, 0f }));
 | 
			
		||||
			layerAdjust.Add(new key_layer(true, chestDef), new values_layer(new float[] { -99f, 0f, 0f, 0f }));
 | 
			
		||||
 | 
			
		||||
			//right body parts:
 | 
			
		||||
			layerAdjust.Add(new key_layer(false, BodyPartDefOf.Arm), new values_layer(new float[] { 0f, 0f, 0f, -99f }));
 | 
			
		||||
			layerAdjust.Add(new key_layer(false, BodyPartDefOf.Hand), new values_layer(new float[] { 0f, 0f, 0f, -99f }));
 | 
			
		||||
			layerAdjust.Add(new key_layer(false, BodyPartDefOf.Leg), new values_layer(new float[] { 0f, 0f, 0f, -99f }));
 | 
			
		||||
 | 
			
		||||
			layerAdjust.Add(new key_layer(false, BodyPartDefOf.Head), new values_layer(new float[] { 0.02f, 0.02f, 0.02f, 0.02f }));
 | 
			
		||||
			layerAdjust.Add(new key_layer(false, JawDef), new values_layer(new float[] { -99f, 0.01f, 0.01f, 0.01f }));
 | 
			
		||||
			layerAdjust.Add(new key_layer(false, NeckDef), new values_layer(new float[] { 0f, 0f, 0f, 0f }));
 | 
			
		||||
			layerAdjust.Add(new key_layer(false, BodyPartDefOf.Torso), new values_layer(new float[] { 0f, 0f, 0f, 0f }));
 | 
			
		||||
			layerAdjust.Add(new key_layer(false, genitalsDef), new values_layer(new float[] { -99f, 0f, 0f, 0f }));
 | 
			
		||||
			layerAdjust.Add(new key_layer(false, anusDef), new values_layer(new float[] { 0f, 0f, -99f, 0f }));
 | 
			
		||||
			layerAdjust.Add(new key_layer(false, chestDef), new values_layer(new float[] { -99f, 0f, 0f, 0f }));
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//all body parts that cum can theoretically be applied to:
 | 
			
		||||
		public static List<BodyPartDef> getAllowedBodyParts()
 | 
			
		||||
		{
 | 
			
		||||
			List<BodyPartDef> allowedParts = new List<BodyPartDef>();
 | 
			
		||||
 | 
			
		||||
			allowedParts.Add(BodyPartDefOf.Arm);
 | 
			
		||||
			allowedParts.Add(BodyPartDefOf.Hand);
 | 
			
		||||
			allowedParts.Add(BodyPartDefOf.Leg);
 | 
			
		||||
			allowedParts.Add(BodyPartDefOf.Head);
 | 
			
		||||
			allowedParts.Add(JawDef);
 | 
			
		||||
			allowedParts.Add(NeckDef);
 | 
			
		||||
			allowedParts.Add(BodyPartDefOf.Torso);
 | 
			
		||||
			allowedParts.Add(genitalsDef);
 | 
			
		||||
			allowedParts.Add(anusDef);
 | 
			
		||||
			allowedParts.Add(chestDef);
 | 
			
		||||
 | 
			
		||||
			return allowedParts;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//get valid body parts for a specific pawn
 | 
			
		||||
		public static IEnumerable<BodyPartRecord> getAvailableBodyParts(Pawn pawn)
 | 
			
		||||
		{
 | 
			
		||||
			//get all non-missing body parts:
 | 
			
		||||
			IEnumerable<BodyPartRecord> bodyParts = pawn.health.hediffSet.GetNotMissingParts(BodyPartHeight.Undefined, BodyPartDepth.Outside, null, null);
 | 
			
		||||
			BodyPartRecord anus = pawn.def.race.body.AllParts.Find(bpr => string.Equals(bpr.def.defName, "Anus"));//not found by above function since depth is "inside"
 | 
			
		||||
 | 
			
		||||
			if (anus != null)
 | 
			
		||||
			{
 | 
			
		||||
				bodyParts = bodyParts.AddItem(anus);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			//filter for allowed body parts (e.g. no single fingers/toes):
 | 
			
		||||
			List<BodyPartDef> filterParts = CumHelper.getAllowedBodyParts();
 | 
			
		||||
 | 
			
		||||
			IEnumerable<BodyPartRecord> filteredParts = bodyParts.Where(item1 => filterParts.Any(item2 => item2.Equals(item1.def)));
 | 
			
		||||
			return filteredParts;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		public const int CUM_NORMAL = 0;
 | 
			
		||||
		public const int CUM_INSECT = 1;
 | 
			
		||||
		public const int CUM_MECHA = 2;
 | 
			
		||||
 | 
			
		||||
		public static readonly Color color_normal = new Color(0.95f, 0.95f, 0.95f);
 | 
			
		||||
		public static readonly Color color_insect = new Color(0.6f, 0.83f, 0.35f);//green-yellowish
 | 
			
		||||
		public static readonly Color color_mecha = new Color(0.37f, 0.71f, 0.82f);//cyan-ish
 | 
			
		||||
 | 
			
		||||
		//name should be self-explanatory:
 | 
			
		||||
		public static void cumOn(Pawn receiver, BodyPartRecord bodyPart, float amount = 0.2f, Pawn giver = null, int cumType = CUM_NORMAL)
 | 
			
		||||
		{
 | 
			
		||||
			Hediff_Cum hediff;
 | 
			
		||||
			if (cumType == CUM_NORMAL)
 | 
			
		||||
			{
 | 
			
		||||
				hediff = (Hediff_Cum)HediffMaker.MakeHediff(HediffDefOf.Hediff_Cum, receiver, null);
 | 
			
		||||
			}
 | 
			
		||||
			else if (cumType == CUM_INSECT)
 | 
			
		||||
			{
 | 
			
		||||
				hediff = (Hediff_Cum)HediffMaker.MakeHediff(HediffDefOf.Hediff_InsectSpunk, receiver, null);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				hediff = (Hediff_Cum)HediffMaker.MakeHediff(HediffDefOf.Hediff_MechaFluids, receiver, null);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			hediff.Severity = amount;//if this body part is already maximally full -> spill over to other parts
 | 
			
		||||
 | 
			
		||||
			//idea: here, a log entry that can act as source could be linked to the hediff - maybe reuse the playlog entry of rjw:
 | 
			
		||||
			hediff.cumType = cumType;
 | 
			
		||||
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				//error when adding to missing part
 | 
			
		||||
				receiver.health.AddHediff(hediff, bodyPart, null, null);
 | 
			
		||||
			}
 | 
			
		||||
			catch
 | 
			
		||||
			{
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			//Log.Message(xxx.get_pawnname(receiver) + " cum amount" + amount);
 | 
			
		||||
			//causes significant memory leak, fixx someday
 | 
			
		||||
			//if (amount > 1f)//spillover in case of very large amounts: just apply hediff a second time
 | 
			
		||||
			//{
 | 
			
		||||
			//	Hediff_cum hediff2 = (Hediff_cum)HediffMaker.MakeHediff(hediff.def, receiver, null);
 | 
			
		||||
			//	hediff2.cumType = cumType;
 | 
			
		||||
			//	hediff2.Severity = amount - 1f;
 | 
			
		||||
			//	receiver.health.AddHediff(hediff2, bodyPart, null, null);
 | 
			
		||||
			//}
 | 
			
		||||
 | 
			
		||||
			//always also add cumcontroller hediff as manager
 | 
			
		||||
			receiver.health.AddHediff(HediffDefOf.Hediff_CumController);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//if spunk on one body part reaches a certain level, it can spill over to others, this function returns from where to where
 | 
			
		||||
		//[SyncMethod]
 | 
			
		||||
		public static BodyPartDef spillover(BodyPartDef sourcePart)
 | 
			
		||||
		{
 | 
			
		||||
			//caution: danger of infinite loop if circular spillover between 2 full parts -> don't define possible circles
 | 
			
		||||
			BodyPartDef newPart = null;
 | 
			
		||||
			int sel;
 | 
			
		||||
			//Rand.PopState();
 | 
			
		||||
			//Rand.PushState(RJW_Multiplayer.PredictableSeed());
 | 
			
		||||
			if (sourcePart == BodyPartDefOf.Torso)
 | 
			
		||||
			{
 | 
			
		||||
				sel = Rand.Range(0, 4);
 | 
			
		||||
				if (sel == 0)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = BodyPartDefOf.Arm;
 | 
			
		||||
				}
 | 
			
		||||
				else if (sel == 1)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = BodyPartDefOf.Leg;
 | 
			
		||||
				}
 | 
			
		||||
				else if (sel == 2)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = NeckDef;
 | 
			
		||||
				}
 | 
			
		||||
				else if (sel == 3)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = chestDef;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else if (sourcePart == JawDef)
 | 
			
		||||
			{
 | 
			
		||||
				sel = Rand.Range(0, 4);
 | 
			
		||||
				if (sel == 0)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = BodyPartDefOf.Head;
 | 
			
		||||
				}
 | 
			
		||||
				else if (sel == 1)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = BodyPartDefOf.Torso;
 | 
			
		||||
				}
 | 
			
		||||
				else if (sel == 2)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = NeckDef;
 | 
			
		||||
				}
 | 
			
		||||
				else if (sel == 3)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = chestDef;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else if (sourcePart == genitalsDef)
 | 
			
		||||
			{
 | 
			
		||||
				sel = Rand.Range(0, 2);
 | 
			
		||||
				if (sel == 0)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = BodyPartDefOf.Leg;
 | 
			
		||||
				}
 | 
			
		||||
				else if (sel == 1)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = BodyPartDefOf.Torso;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else if (sourcePart == anusDef)
 | 
			
		||||
			{
 | 
			
		||||
				sel = Rand.Range(0, 2);
 | 
			
		||||
				if (sel == 0)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = BodyPartDefOf.Leg;
 | 
			
		||||
				}
 | 
			
		||||
				else if (sel == 1)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = BodyPartDefOf.Torso;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else if (sourcePart == chestDef)
 | 
			
		||||
			{
 | 
			
		||||
				sel = Rand.Range(0, 3);
 | 
			
		||||
				if (sel == 0)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = BodyPartDefOf.Arm;
 | 
			
		||||
				}
 | 
			
		||||
				else if (sel == 1)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = BodyPartDefOf.Torso;
 | 
			
		||||
				}
 | 
			
		||||
				else if (sel == 2)
 | 
			
		||||
				{
 | 
			
		||||
					newPart = NeckDef;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return newPart;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//determines who is the active male (or equivalent) in the exchange and the amount of cum dispensed and where to
 | 
			
		||||
		//[SyncMethod]
 | 
			
		||||
		public static void calculateAndApplyCum(SexProps props)
 | 
			
		||||
		{
 | 
			
		||||
			if (!CumBase.cum_on_body) return;
 | 
			
		||||
			Pawn pawn = props.pawn;
 | 
			
		||||
			Pawn partner = props.partner;
 | 
			
		||||
 | 
			
		||||
			Pawn giver, receiver;
 | 
			
		||||
			//Rand.PopState();
 | 
			
		||||
			//Rand.PushState(RJW_Multiplayer.PredictableSeed());
 | 
			
		||||
 | 
			
		||||
			List<Hediff> giverparts;
 | 
			
		||||
			List<Hediff> pawnparts = pawn.GetGenitalsList();
 | 
			
		||||
			List<Hediff> partnerparts = partner != pawn ? partner.GetGenitalsList(): null; // masturbation
 | 
			
		||||
 | 
			
		||||
			//dispenser of the seed
 | 
			
		||||
			if (xxx.is_mechanoid(pawn) || Genital_Helper.has_penis_fertile(pawn, pawnparts) || Genital_Helper.has_ovipositorF(pawn, pawnparts))
 | 
			
		||||
			{
 | 
			
		||||
				giver = pawn;
 | 
			
		||||
				giverparts = pawnparts;
 | 
			
		||||
				receiver = partner;
 | 
			
		||||
			}
 | 
			
		||||
			else if (partner != null && props.isCoreLovin && (xxx.is_mechanoid(partner) || Genital_Helper.has_penis_fertile(partner, partnerparts) || Genital_Helper.has_ovipositorF(partner, partnerparts)))
 | 
			
		||||
			{
 | 
			
		||||
				giver = partner;
 | 
			
		||||
				giverparts = partnerparts;
 | 
			
		||||
				receiver = pawn;
 | 
			
		||||
			}
 | 
			
		||||
			else//female on female or genderless - no cum dispensed; maybe add futa support?
 | 
			
		||||
			{
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			//slimes do not waste fluids?
 | 
			
		||||
			//if (xxx.is_slime(giver)) return;
 | 
			
		||||
 | 
			
		||||
			//determine entity:
 | 
			
		||||
			int entityType = CumHelper.CUM_NORMAL;
 | 
			
		||||
			if (xxx.is_mechanoid(giver))
 | 
			
		||||
			{
 | 
			
		||||
				entityType = CumHelper.CUM_MECHA;
 | 
			
		||||
			}
 | 
			
		||||
			else if (xxx.is_insect(giver))
 | 
			
		||||
			{
 | 
			
		||||
				entityType = CumHelper.CUM_INSECT;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			//ModLog.Message("giver " + xxx.get_pawnname(giver));
 | 
			
		||||
			//ModLog.Message("receiver " + xxx.get_pawnname(receiver));
 | 
			
		||||
			//ModLog.Message("Cumtype " + entityType);
 | 
			
		||||
 | 
			
		||||
			//get pawn genitalia:
 | 
			
		||||
			BodyPartRecord genitals;
 | 
			
		||||
			if (xxx.is_mechanoid(giver))
 | 
			
		||||
			{
 | 
			
		||||
				genitals = giver.RaceProps.body.AllParts.Find(x => string.Equals(x.def.defName, "MechGenitals"));
 | 
			
		||||
			}
 | 
			
		||||
			else//insects, animals, humans
 | 
			
		||||
			{
 | 
			
		||||
				genitals = giver.RaceProps.body.AllParts.Find(x => x.def == CumHelper.genitalsDef);
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
			//no cum without genitals
 | 
			
		||||
			if (genitals == null)
 | 
			
		||||
			{
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			float cumAmount = giver.BodySize; //fallback for mechanoinds and w/e without hediffs
 | 
			
		||||
			float horniness = 1f;
 | 
			
		||||
			float ageScale = Math.Min(80 / SexUtility.ScaleToHumanAge(giver), 1.0f);//calculation lifted from rjw
 | 
			
		||||
 | 
			
		||||
			if (xxx.is_mechanoid(giver) && giverparts.NullOrEmpty())
 | 
			
		||||
			{
 | 
			
		||||
				//use default above
 | 
			
		||||
			}
 | 
			
		||||
			else if (giverparts.NullOrEmpty())
 | 
			
		||||
				return;
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				var penisHediff = giverparts.FindAll((Hediff hed) => hed.def.defName.ToLower().Contains("penis")).InRandomOrder().FirstOrDefault();
 | 
			
		||||
 | 
			
		||||
				if (penisHediff == null)
 | 
			
		||||
					penisHediff = giverparts.FindAll((Hediff hed) => hed.def.defName.ToLower().Contains("ovipositorf")).InRandomOrder().FirstOrDefault();
 | 
			
		||||
				if (penisHediff == null)
 | 
			
		||||
					penisHediff = giverparts.FindAll((Hediff hed) => hed.def.defName.ToLower().Contains("ovipositorm")).InRandomOrder().FirstOrDefault();
 | 
			
		||||
				if (penisHediff == null)
 | 
			
		||||
					penisHediff = giverparts.FindAll((Hediff hed) => hed.def.defName.ToLower().Contains("tentacle")).InRandomOrder().FirstOrDefault();
 | 
			
		||||
 | 
			
		||||
				if (penisHediff != null)
 | 
			
		||||
				{
 | 
			
		||||
					cumAmount = penisHediff.Severity * giver.BodySize;
 | 
			
		||||
 | 
			
		||||
					CompHediffBodyPart chdf = penisHediff.TryGetComp<rjw.CompHediffBodyPart>();
 | 
			
		||||
					if (chdf != null)
 | 
			
		||||
					{
 | 
			
		||||
						if (chdf.FluidAmmount != 0)
 | 
			
		||||
							cumAmount = chdf.FluidAmmount * chdf.FluidModifier;
 | 
			
		||||
					}
 | 
			
		||||
					//ModLog.Message("cumAmount base " + cumAmount);
 | 
			
		||||
 | 
			
		||||
					Need sexNeed = giver?.needs?.AllNeeds.Find(x => string.Equals(x.def.defName, "Sex"));
 | 
			
		||||
					if (sexNeed != null)//non-humans don't have it - therefore just use the default value
 | 
			
		||||
					{
 | 
			
		||||
						horniness = 1f - sexNeed.CurLevel;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				else 
 | 
			
		||||
				{ 
 | 
			
		||||
					//something is wrong... vagina?
 | 
			
		||||
					return; 
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			cumAmount *= CumBase.cum_on_body_amount;
 | 
			
		||||
			//ModLog.Message("cumAmount after cum_on_body_amount_adjust after " + cumAmount);
 | 
			
		||||
			cumAmount *= horniness;
 | 
			
		||||
			//ModLog.Message("cumAmount after horniness mod " + cumAmount);
 | 
			
		||||
			cumAmount *= ageScale;
 | 
			
		||||
			//ModLog.Message("cumAmount after ageScale mod " + cumAmount);
 | 
			
		||||
			cumAmount /= 10;
 | 
			
		||||
			//ModLog.Message("cumAmount final " + cumAmount);
 | 
			
		||||
 | 
			
		||||
			//TODO: cumHelper Autofellatio
 | 
			
		||||
			//if no partner -> masturbation, apply some cum on self:
 | 
			
		||||
			//if (partner == null && sextype == xxx.rjwSextype.Autofellatio)
 | 
			
		||||
			//{
 | 
			
		||||
			//	if (!xxx.is_slime(giver))
 | 
			
		||||
			//		cumHelper.cumOn(giver, BodyPartDefOf.Jaw, cumAmount, giver);
 | 
			
		||||
			//	return;
 | 
			
		||||
			//}
 | 
			
		||||
			if (props.sexType == xxx.rjwSextype.Masturbation)
 | 
			
		||||
			{
 | 
			
		||||
				if (!xxx.is_slime(giver))
 | 
			
		||||
					CumHelper.cumOn(giver, genitals, cumAmount * 0.3f, giver);//pawns are usually not super-messy -> only apply 30%
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			else if (receiver != null)
 | 
			
		||||
			{
 | 
			
		||||
				List<BodyPartRecord> targetParts = new List<BodyPartRecord>();//which to apply cum on
 | 
			
		||||
				IEnumerable<BodyPartRecord> availableParts = CumHelper.getAvailableBodyParts(receiver);
 | 
			
		||||
				BodyPartRecord randomPart;//not always needed
 | 
			
		||||
 | 
			
		||||
				switch (props.sexType)
 | 
			
		||||
				{
 | 
			
		||||
					case rjw.xxx.rjwSextype.Anal:
 | 
			
		||||
						targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == CumHelper.anusDef));
 | 
			
		||||
						break;
 | 
			
		||||
					case rjw.xxx.rjwSextype.Boobjob:
 | 
			
		||||
						targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == CumHelper.chestDef));
 | 
			
		||||
						break;
 | 
			
		||||
					case rjw.xxx.rjwSextype.DoublePenetration:
 | 
			
		||||
						targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == CumHelper.anusDef));
 | 
			
		||||
						targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == CumHelper.genitalsDef));
 | 
			
		||||
						break;
 | 
			
		||||
					case rjw.xxx.rjwSextype.Fingering:
 | 
			
		||||
						cumAmount = 0;
 | 
			
		||||
						break;
 | 
			
		||||
					case rjw.xxx.rjwSextype.Fisting:
 | 
			
		||||
						cumAmount = 0;
 | 
			
		||||
						break;
 | 
			
		||||
					case rjw.xxx.rjwSextype.Footjob:
 | 
			
		||||
						//random part:
 | 
			
		||||
						availableParts.TryRandomElement<BodyPartRecord>(out randomPart);
 | 
			
		||||
						targetParts.Add(randomPart);
 | 
			
		||||
						break;
 | 
			
		||||
					case rjw.xxx.rjwSextype.Handjob:
 | 
			
		||||
						//random part:
 | 
			
		||||
						availableParts.TryRandomElement<BodyPartRecord>(out randomPart);
 | 
			
		||||
						targetParts.Add(randomPart);
 | 
			
		||||
						break;
 | 
			
		||||
					case rjw.xxx.rjwSextype.Masturbation:
 | 
			
		||||
						cumAmount *= 2f;
 | 
			
		||||
						break;
 | 
			
		||||
					case rjw.xxx.rjwSextype.MechImplant:
 | 
			
		||||
						//one of the openings:
 | 
			
		||||
						int random = Rand.Range(0, 3);
 | 
			
		||||
						if (random == 0)
 | 
			
		||||
						{
 | 
			
		||||
							targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == CumHelper.genitalsDef));
 | 
			
		||||
						}
 | 
			
		||||
						else if (random == 1)
 | 
			
		||||
						{
 | 
			
		||||
							targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == CumHelper.anusDef));
 | 
			
		||||
						}
 | 
			
		||||
						else if (random == 2)
 | 
			
		||||
						{
 | 
			
		||||
							targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == JawDef));
 | 
			
		||||
						}
 | 
			
		||||
						break;
 | 
			
		||||
					case rjw.xxx.rjwSextype.MutualMasturbation:
 | 
			
		||||
						//random
 | 
			
		||||
						availableParts.TryRandomElement<BodyPartRecord>(out randomPart);
 | 
			
		||||
						targetParts.Add(randomPart);
 | 
			
		||||
						break;
 | 
			
		||||
					case rjw.xxx.rjwSextype.None:
 | 
			
		||||
						cumAmount = 0;
 | 
			
		||||
						break;
 | 
			
		||||
					case rjw.xxx.rjwSextype.Oral:
 | 
			
		||||
						targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == JawDef));
 | 
			
		||||
						break;
 | 
			
		||||
					case rjw.xxx.rjwSextype.Scissoring:
 | 
			
		||||
						//I guess if it came to here, a male must be involved?
 | 
			
		||||
						targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == CumHelper.genitalsDef));
 | 
			
		||||
						break;
 | 
			
		||||
					case rjw.xxx.rjwSextype.Vaginal:
 | 
			
		||||
						targetParts.Add(receiver.RaceProps.body.AllParts.Find(x => x.def == CumHelper.genitalsDef));
 | 
			
		||||
						break;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (cumAmount > 0)
 | 
			
		||||
				{
 | 
			
		||||
					if (receiver != null && xxx.is_slime(receiver))
 | 
			
		||||
					{
 | 
			
		||||
						//slime absorb cum
 | 
			
		||||
						//this needs balancing, since cumamount ranges 0-10(?) which is fine for cum/hentai but not very realistic for feeding
 | 
			
		||||
						//using TransferNutrition for now
 | 
			
		||||
						//Log.Message("cumAmount " + cumAmount);
 | 
			
		||||
						//float nutrition_amount = cumAmount/10;
 | 
			
		||||
 | 
			
		||||
						Need_Food need = need = giver.needs.TryGetNeed<Need_Food>();
 | 
			
		||||
						if (need == null)
 | 
			
		||||
						{
 | 
			
		||||
							//Log.Message("xxx::TransferNutrition() " + xxx.get_pawnname(pawn) + " doesn't track nutrition in itself, probably shouldn't feed the others");
 | 
			
		||||
							return;
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						if (receiver?.needs?.TryGetNeed<Need_Food>() != null)
 | 
			
		||||
						{
 | 
			
		||||
							//Log.Message("xxx::TransferNutrition() " +  xxx.get_pawnname(partner) + " can receive");
 | 
			
		||||
							float nutrition_amount = Math.Min(need.MaxLevel / 15f, need.CurLevel); //body size is taken into account implicitly by need.MaxLevel
 | 
			
		||||
							receiver.needs.food.CurLevel += nutrition_amount;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						CumHelper.cumOn(giver, genitals, cumAmount * 0.3f, giver, entityType);//cum on self - smaller amount
 | 
			
		||||
						if (receiver != null)
 | 
			
		||||
							foreach (BodyPartRecord bpr in targetParts)
 | 
			
		||||
							{
 | 
			
		||||
								if (bpr != null)
 | 
			
		||||
								{
 | 
			
		||||
									CumHelper.cumOn(receiver, bpr, cumAmount, giver, entityType);//cum on partner
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								1.5/Source/Mod/DefOf/HediffDefOf.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwcum
 | 
			
		||||
{
 | 
			
		||||
	[DefOf]
 | 
			
		||||
	public static class HediffDefOf
 | 
			
		||||
	{
 | 
			
		||||
		public static HediffDef Hediff_Cum;//for humans & animals
 | 
			
		||||
		public static HediffDef Hediff_InsectSpunk;
 | 
			
		||||
		public static HediffDef Hediff_MechaFluids;
 | 
			
		||||
 | 
			
		||||
		public static HediffDef Hediff_CumController;//cum hediff manager
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								1.5/Source/Mod/DefOf/JobDefOf.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
 | 
			
		||||
namespace rjwcum
 | 
			
		||||
{
 | 
			
		||||
	[DefOf]
 | 
			
		||||
	public static class JobDefOf
 | 
			
		||||
	{
 | 
			
		||||
		public static JobDef CleanSelf;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										155
									
								
								1.5/Source/Mod/Hediffs/Hediff_Cum.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,155 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using Verse;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
//using Multiplayer.API;
 | 
			
		||||
 | 
			
		||||
namespace rjwcum
 | 
			
		||||
{
 | 
			
		||||
	public class Hediff_Cum : HediffWithComps
 | 
			
		||||
	{
 | 
			
		||||
		public int cumType = CumHelper.CUM_NORMAL;//-> different colors
 | 
			
		||||
 | 
			
		||||
		public string giverName = null;//not utilized right now, maybe in the future save origin of the cum
 | 
			
		||||
 | 
			
		||||
		public override string LabelInBrackets
 | 
			
		||||
		{
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				StringBuilder stringBuilder = new StringBuilder();
 | 
			
		||||
				stringBuilder.Append(base.LabelInBrackets);
 | 
			
		||||
				if (this.sourceHediffDef != null)
 | 
			
		||||
				{
 | 
			
		||||
					if (stringBuilder.Length != 0)
 | 
			
		||||
					{
 | 
			
		||||
						stringBuilder.Append(", ");
 | 
			
		||||
					}
 | 
			
		||||
					stringBuilder.Append(this.sourceHediffDef.label);
 | 
			
		||||
				}
 | 
			
		||||
				else if (this.sourceDef != null)
 | 
			
		||||
				{
 | 
			
		||||
					if (stringBuilder.Length != 0)
 | 
			
		||||
					{
 | 
			
		||||
						stringBuilder.Append(", ");
 | 
			
		||||
					}
 | 
			
		||||
					stringBuilder.Append(this.sourceLabel);
 | 
			
		||||
					if (this.sourceBodyPartGroup != null)
 | 
			
		||||
					{
 | 
			
		||||
						stringBuilder.Append(" ");
 | 
			
		||||
						stringBuilder.Append(this.sourceBodyPartGroup.LabelShort);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				return stringBuilder.ToString();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		public override string SeverityLabel
 | 
			
		||||
		{
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				if (this.Severity == 0f)
 | 
			
		||||
				{
 | 
			
		||||
					return null;
 | 
			
		||||
				}
 | 
			
		||||
				return this.Severity.ToString("F1");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//[SyncMethod]
 | 
			
		||||
		public override bool TryMergeWith(Hediff other)
 | 
			
		||||
		{
 | 
			
		||||
			//if a new cum hediff is added to the same body part, they are combined. if severity reaches more than 1, spillover to other body parts occurs
 | 
			
		||||
 | 
			
		||||
			Hediff_Cum hediff_cum = other as Hediff_Cum;
 | 
			
		||||
			if (hediff_cum != null && hediff_cum.def == this.def && hediff_cum.Part == base.Part && this.def.injuryProps.canMerge)
 | 
			
		||||
			{
 | 
			
		||||
				cumType = hediff_cum.cumType;//take over new creature color
 | 
			
		||||
 | 
			
		||||
				float totalAmount = hediff_cum.Severity + this.Severity;
 | 
			
		||||
				if (totalAmount > 1.0f)
 | 
			
		||||
				{
 | 
			
		||||
					BodyPartDef spillOverTo = CumHelper.spillover(this.Part.def);//cumHelper saves valid other body parts for spillover
 | 
			
		||||
					if (spillOverTo != null)
 | 
			
		||||
					{
 | 
			
		||||
						//Rand.PopState();
 | 
			
		||||
						//Rand.PushState(RJW_Multiplayer.PredictableSeed());
 | 
			
		||||
						IEnumerable<BodyPartRecord> availableParts = CumHelper.getAvailableBodyParts(pawn);//gets all non missing, valid body parts
 | 
			
		||||
						IEnumerable<BodyPartRecord> filteredParts = availableParts.Where(x => x.def == spillOverTo);//filters again for valid spill target
 | 
			
		||||
						if (!filteredParts.EnumerableNullOrEmpty())
 | 
			
		||||
						{
 | 
			
		||||
							BodyPartRecord spillPart = null;
 | 
			
		||||
							spillPart = filteredParts.RandomElement<BodyPartRecord>();//then pick one
 | 
			
		||||
							if (spillPart != null)
 | 
			
		||||
							{
 | 
			
		||||
								CumHelper.cumOn(pawn, spillPart, totalAmount - this.Severity, null, cumType);
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				return (base.TryMergeWith(other));
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
			return (false);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void ExposeData()
 | 
			
		||||
		{
 | 
			
		||||
			base.ExposeData();
 | 
			
		||||
			Scribe_Values.Look<int>(ref cumType, "cumType", CumHelper.CUM_NORMAL);
 | 
			
		||||
 | 
			
		||||
			if (Scribe.mode == LoadSaveMode.PostLoadInit && base.Part == null)
 | 
			
		||||
			{
 | 
			
		||||
				//Log.Error("Hediff_cum has null part after loading.", false);
 | 
			
		||||
				this.pawn.health.hediffSet.hediffs.Remove(this);
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//handles the icon in the health tab and its color
 | 
			
		||||
		public override TextureAndColor StateIcon
 | 
			
		||||
		{
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				TextureAndColor tex = TextureAndColor.None;
 | 
			
		||||
				Color color = Color.white;
 | 
			
		||||
				switch (cumType)
 | 
			
		||||
				{
 | 
			
		||||
					case CumHelper.CUM_NORMAL:
 | 
			
		||||
						color = CumHelper.color_normal;
 | 
			
		||||
						break;
 | 
			
		||||
					case CumHelper.CUM_INSECT:
 | 
			
		||||
						color = CumHelper.color_insect;
 | 
			
		||||
						break;
 | 
			
		||||
					case CumHelper.CUM_MECHA:
 | 
			
		||||
						color = CumHelper.color_mecha;
 | 
			
		||||
						break;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				Texture2D tex2d = CumTextures.CumIcon_little;
 | 
			
		||||
				switch (this.CurStageIndex)
 | 
			
		||||
				{
 | 
			
		||||
					case 0:
 | 
			
		||||
						tex2d = CumTextures.CumIcon_little;
 | 
			
		||||
						break;
 | 
			
		||||
					case 1:
 | 
			
		||||
						tex2d = CumTextures.CumIcon_some;
 | 
			
		||||
						break;
 | 
			
		||||
					case 2:
 | 
			
		||||
						tex2d = CumTextures.CumIcon_dripping;
 | 
			
		||||
						break;
 | 
			
		||||
					case 3:
 | 
			
		||||
						tex2d = CumTextures.CumIcon_drenched;
 | 
			
		||||
						break;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				tex = new TextureAndColor(tex2d, color);
 | 
			
		||||
 | 
			
		||||
				return tex;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										272
									
								
								1.5/Source/Mod/Hediffs/Hediff_CumController.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,272 @@
 | 
			
		|||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Verse;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
//using Multiplayer.API;
 | 
			
		||||
 | 
			
		||||
namespace rjwcum
 | 
			
		||||
{
 | 
			
		||||
	class Hediff_CumController : HediffWithComps
 | 
			
		||||
	{
 | 
			
		||||
		/*
 | 
			
		||||
		Whenever cum is applied, this hediff is also added to the pawn.
 | 
			
		||||
		Since there is always only a single hediff of this type on the pawn, it serves as master controller, adding up the individual cum hediffs, applying debuffs and drawing overlays
 | 
			
		||||
		*/
 | 
			
		||||
 | 
			
		||||
		private static readonly float cumWeight = 0.2f;//how much individual cum_hediffs contribute to the overall bukkake severity
 | 
			
		||||
		List<Hediff> hediffs_cum;
 | 
			
		||||
		Dictionary<string, CumSplatch> splatches;
 | 
			
		||||
 | 
			
		||||
		public override void ExposeData()
 | 
			
		||||
		{
 | 
			
		||||
			base.ExposeData();
 | 
			
		||||
			//Scribe_Values.Look<Dictionary<string, CumSplatch>>(ref splatches, "splatches", new Dictionary<string, CumSplatch>()); - causes errors when loading. for now, just make a new dictionary
 | 
			
		||||
			splatches = new Dictionary<string, CumSplatch>();//instead of loading, just recreate anew
 | 
			
		||||
			hediffs_cum = new List<Hediff>();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void PostMake()
 | 
			
		||||
		{
 | 
			
		||||
			base.PostMake();
 | 
			
		||||
			splatches = new Dictionary<string, CumSplatch>();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void PostTick()
 | 
			
		||||
		{
 | 
			
		||||
			if (pawn.RaceProps.Humanlike)//for now, only humans are supported 
 | 
			
		||||
			{
 | 
			
		||||
				hediffs_cum = this.pawn.health.hediffSet.hediffs.FindAll(x => (x.def == HediffDefOf.Hediff_Cum || x.def == HediffDefOf.Hediff_InsectSpunk || x.def == HediffDefOf.Hediff_MechaFluids));
 | 
			
		||||
				float Level = CalculateLevel();//sum of severity of all the cum hediffs x cumWeight
 | 
			
		||||
				this.Severity = Level;
 | 
			
		||||
				bool updatePortrait = false;
 | 
			
		||||
 | 
			
		||||
				//loop through all cum hediffs, add missing ones to dictionary
 | 
			
		||||
				for (int i = 0; i < hediffs_cum.Count(); i++)
 | 
			
		||||
				{
 | 
			
		||||
					Hediff_Cum h = (Hediff_Cum)hediffs_cum[i];
 | 
			
		||||
					string ID = h.GetUniqueLoadID();//unique ID for each hediff
 | 
			
		||||
					if (!splatches.ContainsKey(ID))//if it isn't here yet, make new object
 | 
			
		||||
					{
 | 
			
		||||
						updatePortrait = true;
 | 
			
		||||
						bool leftSide = h.Part.Label.Contains("left") ? true : false;//depending on whether the body part is left or right, drawing-offset on x-aixs may be inverted
 | 
			
		||||
 | 
			
		||||
						splatches[ID] = new CumSplatch(h, pawn.story.bodyType, h.Part.def, leftSide, h.cumType);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
				//remove splatch objects once their respective cum hediff is gone
 | 
			
		||||
				List<string> removeKeys = new List<string>();
 | 
			
		||||
				foreach (string key in splatches.Keys)
 | 
			
		||||
				{
 | 
			
		||||
					CumSplatch s = splatches[key];
 | 
			
		||||
 | 
			
		||||
					if (!hediffs_cum.Contains(s.hediff_cum))
 | 
			
		||||
					{
 | 
			
		||||
						removeKeys.Add(key);
 | 
			
		||||
						updatePortrait = true;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				//loop over and remove elements that should be destroyed:
 | 
			
		||||
				foreach (string key in removeKeys)
 | 
			
		||||
				{
 | 
			
		||||
					CumSplatch s = splatches[key];
 | 
			
		||||
					splatches.Remove(key);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (updatePortrait)//right now, portraits are only updated when a completely new cum hediff is added or an old one removed - maybe that should be done more frequently
 | 
			
		||||
				{
 | 
			
		||||
					PortraitsCache.SetDirty(pawn);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//called from the PawnWoundDrawer (see HarmonyPatches)
 | 
			
		||||
		public void DrawCum(Vector3 drawLoc, Quaternion quat, bool forPortrait, float angle, bool inBed = false)
 | 
			
		||||
		{
 | 
			
		||||
			Rot4 bodyFacing = pawn.Rotation;
 | 
			
		||||
			int facingDir = bodyFacing.AsInt;//0: north, 1:east, 2:south, 3:west
 | 
			
		||||
			foreach (string key in splatches.Keys)
 | 
			
		||||
			{
 | 
			
		||||
				CumSplatch s = splatches[key];
 | 
			
		||||
				s.Draw(drawLoc, quat, forPortrait, facingDir, angle, inBed);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//new Hediff_CumController added to pawn -> just combine the two
 | 
			
		||||
		public override bool TryMergeWith(Hediff other)
 | 
			
		||||
		{
 | 
			
		||||
			if (other == null || other.def != this.def)
 | 
			
		||||
			{
 | 
			
		||||
				return false;
 | 
			
		||||
			}
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private float CalculateLevel()
 | 
			
		||||
		{
 | 
			
		||||
			float num = 0f;
 | 
			
		||||
			for (int i = 0; i < hediffs_cum.Count; i++)
 | 
			
		||||
			{
 | 
			
		||||
				num += hediffs_cum[i].Severity * cumWeight;
 | 
			
		||||
			}
 | 
			
		||||
			return num;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//class for handling drawing of the individual splatches
 | 
			
		||||
		private class CumSplatch
 | 
			
		||||
		{
 | 
			
		||||
			public readonly Hediff_Cum hediff_cum;
 | 
			
		||||
			public readonly Material cumMaterial;
 | 
			
		||||
			public readonly BodyPartDef bodyPart;
 | 
			
		||||
			private bool mirrorMesh;
 | 
			
		||||
 | 
			
		||||
			private const float maxSize = 0.20f;//1.0 = 1 tile
 | 
			
		||||
			private const float minSize = 0.05f;
 | 
			
		||||
 | 
			
		||||
			//data taken from CumHelper.cs:
 | 
			
		||||
			private readonly float[] xAdjust;
 | 
			
		||||
			private readonly float[] zAdjust;
 | 
			
		||||
			private readonly float[] yAdjust;
 | 
			
		||||
 | 
			
		||||
			public CumSplatch(Hediff_Cum hediff, BodyTypeDef bodyType, BodyPartDef bodyPart, bool leftSide = false, int cumType = CumHelper.CUM_NORMAL)
 | 
			
		||||
			{
 | 
			
		||||
				hediff_cum = hediff;
 | 
			
		||||
				cumMaterial = new Material(CumTextures.pickRandomSplatch());//needs to create new material in order to allow for different colors
 | 
			
		||||
				cumMaterial.SetTextureScale("_MainTex", new Vector2(-1, 1));
 | 
			
		||||
				this.bodyPart = bodyPart;
 | 
			
		||||
				//Rand.PopState();
 | 
			
		||||
				//Rand.PushState(RJW_Multiplayer.PredictableSeed());
 | 
			
		||||
 | 
			
		||||
				//set color:
 | 
			
		||||
				switch (cumType)
 | 
			
		||||
				{
 | 
			
		||||
					case CumHelper.CUM_NORMAL:
 | 
			
		||||
						cumMaterial.color = CumHelper.color_normal;
 | 
			
		||||
						break;
 | 
			
		||||
					case CumHelper.CUM_INSECT:
 | 
			
		||||
						cumMaterial.color = CumHelper.color_insect;
 | 
			
		||||
						break;
 | 
			
		||||
					case CumHelper.CUM_MECHA:
 | 
			
		||||
						cumMaterial.color = CumHelper.color_mecha;
 | 
			
		||||
						break;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				//if (!MP.enabled)
 | 
			
		||||
					mirrorMesh = (Rand.Value > 0.5f);//in 50% of the cases, flip mesh horizontally for more variance
 | 
			
		||||
 | 
			
		||||
				//x,y,z adjustments to draw splatches over the approximately correct locations; values stored in Cum helper - accessed by unique combinations of bodyTypes and bodyParts
 | 
			
		||||
				CumHelper.key k = new CumHelper.key(bodyType, bodyPart);
 | 
			
		||||
				if (CumHelper.splatchAdjust.Keys.Contains(k))
 | 
			
		||||
				{
 | 
			
		||||
					CumHelper.values helperValues = CumHelper.splatchAdjust[k];
 | 
			
		||||
 | 
			
		||||
					//invert, x-adjust (horizontal) depending on left/right body side:
 | 
			
		||||
					if (!leftSide)
 | 
			
		||||
					{
 | 
			
		||||
						float[] xAdjTemp = new float[4];
 | 
			
		||||
						for (int i = 0; i < xAdjTemp.Length; i++)
 | 
			
		||||
						{
 | 
			
		||||
							xAdjTemp[i] = helperValues.x[i] * -1f;
 | 
			
		||||
						}
 | 
			
		||||
						xAdjust = xAdjTemp;
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						xAdjust = helperValues.x;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					zAdjust = helperValues.z;//vertical adjustment
 | 
			
		||||
 | 
			
		||||
				}
 | 
			
		||||
				else//fallback in the the key can't be found
 | 
			
		||||
				{
 | 
			
		||||
					//if (RJWSettings.DevMode)
 | 
			
		||||
					//{
 | 
			
		||||
					//	ModLog.Message("created cum splatch for undefined body type or part. BodyType: " + bodyType + " , BodyPart: " + bodyPart);
 | 
			
		||||
					//}
 | 
			
		||||
					xAdjust = new float[] { 0f, 0f, 0f, 0f };
 | 
			
		||||
					zAdjust = new float[] { 0f, 0f, 0f, 0f };
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
				//y adjustments: plane/layer of drawing, > 0 -> above certain objects, < 0 -> below
 | 
			
		||||
				CumHelper.key_layer k2 = new CumHelper.key_layer(leftSide, bodyPart);
 | 
			
		||||
 | 
			
		||||
				if (CumHelper.layerAdjust.Keys.Contains(k2))
 | 
			
		||||
				{
 | 
			
		||||
					CumHelper.values_layer helperValues_layer = CumHelper.layerAdjust[k2];
 | 
			
		||||
					yAdjust = helperValues_layer.y;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					yAdjust = new float[] { 0.02f, 0.02f, 0.02f, 0.02f };//over body in every direction
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			public void Draw(Vector3 drawPos, Quaternion quat, bool forPortrait, int facingDir = 0, float angle = 0,bool inBed=false)
 | 
			
		||||
			{
 | 
			
		||||
				if (inBed)
 | 
			
		||||
				{
 | 
			
		||||
					if (this.bodyPart != CumHelper.JawDef && this.bodyPart != BodyPartDefOf.Head)//when pawn is in bed (=bed with sheets), only draw cum on head
 | 
			
		||||
					{
 | 
			
		||||
						return;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				//these two create new mesh instance and never destroying it, filling ram and crashing
 | 
			
		||||
				//float size = minSize+((maxSize-minSize)*hediff_cum.Severity);
 | 
			
		||||
				//mesh = MeshMakerPlanes.NewPlaneMesh(size);
 | 
			
		||||
 | 
			
		||||
				//use core MeshPool.plane025 instead
 | 
			
		||||
 | 
			
		||||
				//if (mirrorMesh)//horizontal flip
 | 
			
		||||
				//{
 | 
			
		||||
					//mesh = flipMesh(mesh);
 | 
			
		||||
				//}
 | 
			
		||||
 | 
			
		||||
				//rotation:
 | 
			
		||||
				if (angle == 0)//normal situation (pawn standing upright)
 | 
			
		||||
				{
 | 
			
		||||
					drawPos.x += xAdjust[facingDir];
 | 
			
		||||
					drawPos.z += zAdjust[facingDir];
 | 
			
		||||
				}
 | 
			
		||||
				else//if downed etc, more complex calculation becomes necessary
 | 
			
		||||
				{
 | 
			
		||||
					float radian = angle / 180 * (float)Math.PI;
 | 
			
		||||
					radian = -radian;
 | 
			
		||||
					drawPos.x += Mathf.Cos(radian) * xAdjust[hediff_cum.pawn.Rotation.AsInt] - Mathf.Sin(radian) * zAdjust[facingDir];//facingDir doesn't appear to be chosen correctly in all cases
 | 
			
		||||
					drawPos.z += Mathf.Cos(radian) * zAdjust[hediff_cum.pawn.Rotation.AsInt] + Mathf.Sin(radian) * xAdjust[facingDir];
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				//drawPos.y += yAdjust[facingDir];// 0.00: over body; 0.01: over body but under face, 0.02: over face, but under hair, -99 = "never" visible
 | 
			
		||||
				drawPos.y += yAdjust[facingDir];
 | 
			
		||||
 | 
			
		||||
				GenDraw.DrawMeshNowOrLater(MeshPool.plane025, drawPos, quat, cumMaterial, forPortrait);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			//flips mesh UV horizontally, thereby mirroring the texture
 | 
			
		||||
			private Mesh flipMesh(Mesh meshToFlip)
 | 
			
		||||
			{
 | 
			
		||||
				var uvs = meshToFlip.uv;
 | 
			
		||||
				if (uvs.Length != 4)
 | 
			
		||||
				{
 | 
			
		||||
					return (meshToFlip);
 | 
			
		||||
				}
 | 
			
		||||
				for (var i = 0; i < uvs.Length; i++)
 | 
			
		||||
				{
 | 
			
		||||
					if (Mathf.Approximately(uvs[i].x, 1.0f))
 | 
			
		||||
						uvs[i].x = 0.0f;
 | 
			
		||||
					else
 | 
			
		||||
						uvs[i].x = 1.0f;
 | 
			
		||||
				}
 | 
			
		||||
				meshToFlip.uv = uvs;
 | 
			
		||||
				return (meshToFlip);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								1.5/Source/Mod/JobDrivers/JobDriver_CleanSelf.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
using Verse.AI;
 | 
			
		||||
 | 
			
		||||
namespace rjwcum
 | 
			
		||||
{
 | 
			
		||||
	class JobDriver_CleanSelf : JobDriver
 | 
			
		||||
	{
 | 
			
		||||
		float cleanAmount = 1f;//severity of a single cumHediff removed per cleaning-round; 1f = remove entirely
 | 
			
		||||
		int cleaningTime = 120;//ticks - 120 = 2 real seconds, 3 in-game minutes
 | 
			
		||||
 | 
			
		||||
		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 == HediffDefOf.Hediff_CumController);//fail if cum disappears - means that also all the cum is gone
 | 
			
		||||
			});
 | 
			
		||||
			Toil cleaning = Toils_General.Wait(cleaningTime, TargetIndex.None);//duration of 
 | 
			
		||||
			cleaning.WithProgressBarToilDelay(TargetIndex.A);
 | 
			
		||||
 | 
			
		||||
			yield return cleaning;
 | 
			
		||||
			yield return new Toil()
 | 
			
		||||
			{
 | 
			
		||||
				initAction = delegate ()
 | 
			
		||||
				{
 | 
			
		||||
					//get one of the cum hediffs, reduce its severity
 | 
			
		||||
					Hediff hediff = pawn.health.hediffSet.hediffs.Find(x => (x.def == HediffDefOf.Hediff_Cum || x.def == HediffDefOf.Hediff_InsectSpunk || x.def == HediffDefOf.Hediff_MechaFluids));
 | 
			
		||||
					if (hediff != null)
 | 
			
		||||
					{
 | 
			
		||||
						if (hediff.Severity >= 0.5)
 | 
			
		||||
						{
 | 
			
		||||
							if (hediff.def == HediffDefOf.Hediff_InsectSpunk)
 | 
			
		||||
							{
 | 
			
		||||
								Thing jelly = ThingMaker.MakeThing(ThingDefOf.InsectJelly);
 | 
			
		||||
								jelly.SetForbidden(true, false);
 | 
			
		||||
								GenPlace.TryPlaceThing(jelly, pawn.PositionHeld, pawn.MapHeld, ThingPlaceMode.Near);
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						hediff.Severity -= cleanAmount;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			};
 | 
			
		||||
			yield break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										66
									
								
								1.5/Source/Mod/Patch_AddCumOnOrgasm.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,66 @@
 | 
			
		|||
using Verse;
 | 
			
		||||
using HarmonyLib;
 | 
			
		||||
using rjw;
 | 
			
		||||
using System;
 | 
			
		||||
//using Multiplayer.API;
 | 
			
		||||
 | 
			
		||||
namespace rjwcum
 | 
			
		||||
{
 | 
			
		||||
	///<summary>
 | 
			
		||||
	///apply cum to pawn after vanilla sex
 | 
			
		||||
	///</summary>
 | 
			
		||||
	[HarmonyPatch(typeof(SexUtility), "Aftersex")]
 | 
			
		||||
	[StaticConstructorOnStartup]
 | 
			
		||||
	static class Aftersex_Cum_Apply
 | 
			
		||||
	{
 | 
			
		||||
		[HarmonyPostfix]
 | 
			
		||||
		private static void Aftersex_Cum_Patch(SexProps props)
 | 
			
		||||
		{
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				if (props.isCoreLovin)
 | 
			
		||||
					if (!props.usedCondom)
 | 
			
		||||
					{
 | 
			
		||||
						CumHelper.calculateAndApplyCum(props);
 | 
			
		||||
						//SexUtility.CumFilthGenerator(props.pawn);
 | 
			
		||||
						//SexUtility.CumFilthGenerator(props.partner);
 | 
			
		||||
					}
 | 
			
		||||
			}
 | 
			
		||||
			catch (Exception e)
 | 
			
		||||
			{
 | 
			
		||||
				Log.Error(e.ToString());
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	///<summary>
 | 
			
		||||
	///apply cum to pawn after rjw orgasm
 | 
			
		||||
	///</summary>
 | 
			
		||||
	[HarmonyPatch(typeof(JobDriver_Sex), "Orgasm")]
 | 
			
		||||
	[StaticConstructorOnStartup]
 | 
			
		||||
	static class Orgasm_Cum_Apply
 | 
			
		||||
	{
 | 
			
		||||
		[HarmonyPrefix]
 | 
			
		||||
		private static bool Orgasm_Cum_Patch(JobDriver_Sex __instance)
 | 
			
		||||
		{
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				if (__instance.sex_ticks > __instance.orgasmstick) //~3s at speed 1
 | 
			
		||||
				{
 | 
			
		||||
					return true;
 | 
			
		||||
				}
 | 
			
		||||
				var props = __instance.Sexprops;
 | 
			
		||||
				if (!props.usedCondom)
 | 
			
		||||
				{
 | 
			
		||||
					CumHelper.calculateAndApplyCum(props);
 | 
			
		||||
					//SexUtility.CumFilthGenerator(props.pawn);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			catch (Exception e)
 | 
			
		||||
			{
 | 
			
		||||
				Log.Error(e.ToString());
 | 
			
		||||
			}
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										68
									
								
								1.5/Source/Mod/Patch_AddGizmo.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,68 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
using HarmonyLib;
 | 
			
		||||
using rjw;
 | 
			
		||||
//using Multiplayer.API;
 | 
			
		||||
 | 
			
		||||
namespace rjwcum
 | 
			
		||||
{
 | 
			
		||||
	//adds new gizmo for adding cum for testing
 | 
			
		||||
	[HarmonyPatch(typeof(Pawn), "GetGizmos")]
 | 
			
		||||
	class Patch_AddGizmo
 | 
			
		||||
	{
 | 
			
		||||
		[HarmonyPriority(99),HarmonyPostfix]
 | 
			
		||||
		static IEnumerable<Gizmo> AddCum_test(IEnumerable<Gizmo> __result, Pawn __instance)
 | 
			
		||||
		{
 | 
			
		||||
 | 
			
		||||
			foreach (Gizmo entry in __result)
 | 
			
		||||
			{
 | 
			
		||||
				yield return entry;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (Prefs.DevMode )//&& RJWSettings.DevMode && !MP.IsInMultiplayer)
 | 
			
		||||
			{
 | 
			
		||||
				Command_Action addCum = new Command_Action();
 | 
			
		||||
				addCum.defaultDesc = "AddCumHediff";
 | 
			
		||||
				addCum.defaultLabel = "AddCum";
 | 
			
		||||
				addCum.action = delegate ()
 | 
			
		||||
				{
 | 
			
		||||
					AddCum(__instance);
 | 
			
		||||
				};
 | 
			
		||||
 | 
			
		||||
				yield return addCum; 
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//[SyncMethod]
 | 
			
		||||
		static void AddCum(Pawn pawn)
 | 
			
		||||
		{
 | 
			
		||||
			//Log.Message("add cum button is pressed for " + pawn);
 | 
			
		||||
 | 
			
		||||
			if (!pawn.Dead && pawn.records != null)
 | 
			
		||||
			{
 | 
			
		||||
				//get all acceptable body parts:
 | 
			
		||||
				IEnumerable<BodyPartRecord> filteredParts = CumHelper.getAvailableBodyParts(pawn);
 | 
			
		||||
 | 
			
		||||
				//select random part:
 | 
			
		||||
				BodyPartRecord randomPart;
 | 
			
		||||
				//filteredParts.TryRandomElement<BodyPartRecord>(out randomPart);
 | 
			
		||||
				//for testing - choose either genitals or anus:
 | 
			
		||||
				//Rand.PopState();
 | 
			
		||||
				//Rand.PushState(RJW_Multiplayer.PredictableSeed());
 | 
			
		||||
				if (Rand.Value > 0.5f)
 | 
			
		||||
				{
 | 
			
		||||
					randomPart = pawn.RaceProps.body.AllParts.Find(x => x.def == xxx.anusDef);
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					randomPart = pawn.RaceProps.body.AllParts.Find(x => x.def == xxx.genitalsDef);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (randomPart != null)
 | 
			
		||||
				{
 | 
			
		||||
					CumHelper.cumOn(pawn, randomPart, 0.2f, null, CumHelper.CUM_NORMAL);
 | 
			
		||||
				}
 | 
			
		||||
			};
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										85
									
								
								1.5/Source/Mod/Patch_JobDriver_DubsBadHygiene.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,85 @@
 | 
			
		|||
using System;
 | 
			
		||||
using HarmonyLib;
 | 
			
		||||
using Verse;
 | 
			
		||||
using Verse.AI;
 | 
			
		||||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace rjwcum
 | 
			
		||||
{
 | 
			
		||||
	[HarmonyPatch(typeof(JobDriver), "Cleanup")]
 | 
			
		||||
	internal static class Patch_JobDriver_DubsBadHygiene
 | 
			
		||||
	{
 | 
			
		||||
		//not very good solution, some other mod can have same named jobdriver but w/e
 | 
			
		||||
 | 
			
		||||
		//Dubs Bad Hygiene washing
 | 
			
		||||
		private readonly static Type JobDriver_useWashBucket = AccessTools.TypeByName("JobDriver_useWashBucket");
 | 
			
		||||
		//private readonly static Type JobDriver_washAtCell = AccessTools.TypeByName("JobDriver_washAtCell");
 | 
			
		||||
 | 
			
		||||
		private readonly static Type JobDriver_UseHotTub = AccessTools.TypeByName("JobDriver_UseHotTub");
 | 
			
		||||
		private readonly static Type JobDriver_takeShower = AccessTools.TypeByName("JobDriver_takeShower");
 | 
			
		||||
		private readonly static Type JobDriver_takeBath = AccessTools.TypeByName("JobDriver_takeBath");
 | 
			
		||||
 | 
			
		||||
		[HarmonyPostfix]
 | 
			
		||||
		private static void Cleanup_cum(JobDriver __instance, JobCondition condition)
 | 
			
		||||
		{
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				if (__instance == null)
 | 
			
		||||
					return;
 | 
			
		||||
 | 
			
		||||
				if (condition == JobCondition.Succeeded)
 | 
			
		||||
				{
 | 
			
		||||
					Do_cleanup_cum(__instance);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			catch (Exception e)
 | 
			
		||||
			{
 | 
			
		||||
				Log.Error(e.ToString());
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public static void Do_cleanup_cum(JobDriver __instance)
 | 
			
		||||
		{
 | 
			
		||||
			Pawn pawn = __instance.pawn;
 | 
			
		||||
 | 
			
		||||
			//ModLog.Message("patches_DubsBadHygiene::on_cleanup_driver" + xxx.get_pawnname(pawn));
 | 
			
		||||
 | 
			
		||||
			if (xxx.DubsBadHygieneIsActive)
 | 
			
		||||
				//clear one instance of cum
 | 
			
		||||
				if (
 | 
			
		||||
					__instance.GetType() == JobDriver_useWashBucket// ||
 | 
			
		||||
																   //__instance.GetType() == JobDriver_washAtCell
 | 
			
		||||
					)
 | 
			
		||||
				{
 | 
			
		||||
					Hediff hediff = pawn.health.hediffSet.hediffs.Find(x => (x.def == HediffDefOf.Hediff_Cum
 | 
			
		||||
																			|| x.def == HediffDefOf.Hediff_InsectSpunk
 | 
			
		||||
																			|| x.def == HediffDefOf.Hediff_MechaFluids
 | 
			
		||||
																			));
 | 
			
		||||
					if (hediff != null)
 | 
			
		||||
					{
 | 
			
		||||
						//ModLog.Message("patches_DubsBadHygiene::" + __instance.GetType()  + " clear => " + hediff.Label);
 | 
			
		||||
						hediff.Severity -= 1f;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				//clear all instance of cum
 | 
			
		||||
				else if (
 | 
			
		||||
						__instance.GetType() == JobDriver_UseHotTub ||
 | 
			
		||||
						__instance.GetType() == JobDriver_takeShower ||
 | 
			
		||||
						__instance.GetType() == JobDriver_takeBath
 | 
			
		||||
						)
 | 
			
		||||
				{
 | 
			
		||||
					foreach (Hediff hediff in pawn.health.hediffSet.hediffs)
 | 
			
		||||
					{
 | 
			
		||||
						if (hediff.def == HediffDefOf.Hediff_Cum ||
 | 
			
		||||
							hediff.def == HediffDefOf.Hediff_InsectSpunk ||
 | 
			
		||||
							hediff.def == HediffDefOf.Hediff_MechaFluids
 | 
			
		||||
							)
 | 
			
		||||
						{
 | 
			
		||||
							//ModLog.Message("patches_DubsBadHygiene::" + __instance.GetType() + " clear => " + hediff.Label);
 | 
			
		||||
							hediff.Severity -= 1f;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										56
									
								
								1.5/Source/Mod/Patch_RenderOverBody.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
using System.Collections.Generic;
 | 
			
		||||
using Verse;
 | 
			
		||||
using HarmonyLib;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
using System;
 | 
			
		||||
using RimWorld;
 | 
			
		||||
using static RimWorld.PawnOverlayDrawer;
 | 
			
		||||
//using Multiplayer.API;
 | 
			
		||||
 | 
			
		||||
namespace rjwcum
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	[HarmonyPatch(typeof(RimWorld.PawnOverlayDrawer))]
 | 
			
		||||
	[HarmonyPatch("RenderPawnOverlay")]
 | 
			
		||||
	//[HarmonyPatch(new Type[] { typeof(Vector3), typeof(Mesh), typeof(Quaternion), typeof(bool), typeof(PawnOverlayDrawer.OverlayLayer), typeof(Rot4), typeof(bool) })]
 | 
			
		||||
	[HarmonyPatch(new Type[] { typeof(Matrix4x4), typeof(Mesh), typeof(PawnOverlayDrawer.OverlayLayer), typeof(PawnDrawParms), typeof(bool) })]
 | 
			
		||||
	class Patch_RenderPawnOverlay
 | 
			
		||||
	{
 | 
			
		||||
		[HarmonyPostfix]
 | 
			
		||||
		static void DrawCum(RimWorld.PawnOverlayDrawer __instance, Vector3 drawLoc, Mesh bodyMesh, Quaternion quat, bool drawNow, PawnOverlayDrawer.OverlayLayer layer, Rot4 pawnRot, bool? overApparel = null)
 | 
			
		||||
		{
 | 
			
		||||
			if (!CumBase.cum_overlays) return;
 | 
			
		||||
 | 
			
		||||
			Pawn pawn = Traverse.Create(__instance).Field("pawn").GetValue<Pawn>();//get local variable
 | 
			
		||||
 | 
			
		||||
			//TODO add support for animals? unlikely as they has weird meshes
 | 
			
		||||
			//for now, only draw humans
 | 
			
		||||
			if (pawn.RaceProps.Humanlike) //&& CumOverlayBase.cum_overlays)
 | 
			
		||||
			{
 | 
			
		||||
				//find cum hediff. if it exists, use its draw function
 | 
			
		||||
				List<Hediff> hediffs = pawn.health.hediffSet.hediffs;
 | 
			
		||||
				if (hediffs.Exists(x => x.def == HediffDefOf.Hediff_CumController))
 | 
			
		||||
				{
 | 
			
		||||
					Hediff_CumController h = hediffs.Find(x => x.def == HediffDefOf.Hediff_CumController) as Hediff_CumController;
 | 
			
		||||
 | 
			
		||||
					quat.ToAngleAxis(out float angle, out Vector3 axis);//angle changes when pawn is e.g. downed
 | 
			
		||||
 | 
			
		||||
					//adjustments if the pawn is sleeping in a bed:
 | 
			
		||||
					bool inBed = false;
 | 
			
		||||
					Building_Bed building_Bed = pawn.CurrentBed();
 | 
			
		||||
					if (building_Bed != null)
 | 
			
		||||
					{
 | 
			
		||||
						inBed = !building_Bed.def.building.bed_showSleeperBody;
 | 
			
		||||
						AltitudeLayer altLayer = (AltitudeLayer)Mathf.Max((int)building_Bed.def.altitudeLayer, 15);
 | 
			
		||||
						Vector3 vector2 = pawn.Position.ToVector3ShiftedWithAltitude(altLayer);
 | 
			
		||||
						vector2.y += 0.02734375f+0.01f;//just copied from rimworld code+0.01f
 | 
			
		||||
						drawLoc.y = vector2.y;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					h.DrawCum(drawLoc, quat, layer == PawnOverlayDrawer.OverlayLayer.Head, angle);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										79
									
								
								1.5/Source/Mod/RimJobWorldCum.csproj
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,79 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 | 
			
		||||
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
 | 
			
		||||
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
 | 
			
		||||
    <ProjectGuid>{3FC2D442-19B8-4CF9-9D35-CD13B6AC7B28}</ProjectGuid>
 | 
			
		||||
    <OutputType>Library</OutputType>
 | 
			
		||||
    <RootNamespace>rjwcum</RootNamespace>
 | 
			
		||||
    <AssemblyName>RimJobWorldCum</AssemblyName>
 | 
			
		||||
    <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
 | 
			
		||||
    <FileAlignment>512</FileAlignment>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
 | 
			
		||||
    <PlatformTarget>AnyCPU</PlatformTarget>
 | 
			
		||||
    <DebugSymbols>true</DebugSymbols>
 | 
			
		||||
    <DebugType>full</DebugType>
 | 
			
		||||
    <Optimize>false</Optimize>
 | 
			
		||||
    <OutputPath>..\..\Assemblies\</OutputPath>
 | 
			
		||||
    <DefineConstants>DEBUG;TRACE</DefineConstants>
 | 
			
		||||
    <ErrorReport>prompt</ErrorReport>
 | 
			
		||||
    <WarningLevel>4</WarningLevel>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
 | 
			
		||||
    <PlatformTarget>AnyCPU</PlatformTarget>
 | 
			
		||||
    <DebugType>pdbonly</DebugType>
 | 
			
		||||
    <Optimize>true</Optimize>
 | 
			
		||||
    <OutputPath>..\..\Assemblies\</OutputPath>
 | 
			
		||||
    <DefineConstants>TRACE</DefineConstants>
 | 
			
		||||
    <ErrorReport>prompt</ErrorReport>
 | 
			
		||||
    <WarningLevel>4</WarningLevel>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Reference Include="0Harmony, Version=2.3.3.0, Culture=neutral, processorArchitecture=MSIL">
 | 
			
		||||
      <HintPath>..\packages\Lib.Harmony.2.3.3\lib\net472\0Harmony.dll</HintPath>
 | 
			
		||||
      <Private>False</Private>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="Assembly-CSharp">
 | 
			
		||||
      <HintPath>..\..\..\..\..\RimWorldWin64_Data\Managed\Assembly-CSharp.dll</HintPath>
 | 
			
		||||
      <Private>False</Private>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="HugsLib">
 | 
			
		||||
      <HintPath>..\..\..\..\..\..\..\workshop\content\294100\818773962\v1.5\Assemblies\HugsLib.dll</HintPath>
 | 
			
		||||
      <Private>False</Private>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="RJW">
 | 
			
		||||
      <HintPath>..\..\..\..\rjw\1.5\Assemblies\RJW.dll</HintPath>
 | 
			
		||||
      <Private>False</Private>
 | 
			
		||||
    </Reference>
 | 
			
		||||
    <Reference Include="System" />
 | 
			
		||||
    <Reference Include="System.Runtime.InteropServices.RuntimeInformation" />
 | 
			
		||||
    <Reference Include="UnityEngine.CoreModule">
 | 
			
		||||
      <HintPath>..\..\..\..\..\RimWorldWin64_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
 | 
			
		||||
      <Private>False</Private>
 | 
			
		||||
    </Reference>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <AppDesigner Include="Properties\" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Compile Include="..\Properties\AssemblyInfo.cs" />
 | 
			
		||||
    <Compile Include="Textures.cs" />
 | 
			
		||||
    <Compile Include="DefOf\HediffDefOf.cs" />
 | 
			
		||||
    <Compile Include="DefOf\JobDefOf.cs" />
 | 
			
		||||
    <Compile Include="Hediffs\Hediff_CumController.cs" />
 | 
			
		||||
    <Compile Include="Hediffs\Hediff_Cum.cs" />
 | 
			
		||||
    <Compile Include="JobDrivers\JobDriver_CleanSelf.cs" />
 | 
			
		||||
    <Compile Include="Patch_AddCumOnOrgasm.cs" />
 | 
			
		||||
    <Compile Include="Patch_AddGizmo.cs" />
 | 
			
		||||
    <Compile Include="CumHelper.cs" />
 | 
			
		||||
    <Compile Include="CumBase.cs" />
 | 
			
		||||
    <Compile Include="Patch_JobDriver_DubsBadHygiene.cs" />
 | 
			
		||||
    <Compile Include="WorkGivers\WorkGiver_CleanSelf.cs" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <None Include="packages.config" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 | 
			
		||||
</Project>
 | 
			
		||||
							
								
								
									
										58
									
								
								1.5/Source/Mod/Textures.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,58 @@
 | 
			
		|||
using Verse;
 | 
			
		||||
using UnityEngine;
 | 
			
		||||
//using Multiplayer.API;
 | 
			
		||||
 | 
			
		||||
namespace rjwcum
 | 
			
		||||
{
 | 
			
		||||
	[StaticConstructorOnStartup]
 | 
			
		||||
	public static class CumTextures
 | 
			
		||||
	{
 | 
			
		||||
		//UI:
 | 
			
		||||
		public static readonly Texture2D CumIcon_little = ContentFinder<Texture2D>.Get("CumIcon_little", true);
 | 
			
		||||
		public static readonly Texture2D CumIcon_some = ContentFinder<Texture2D>.Get("CumIcon_some", true);
 | 
			
		||||
		public static readonly Texture2D CumIcon_dripping = ContentFinder<Texture2D>.Get("CumIcon_dripping", true);
 | 
			
		||||
		public static readonly Texture2D CumIcon_drenched = ContentFinder<Texture2D>.Get("CumIcon_drenched", true);
 | 
			
		||||
 | 
			
		||||
		//on pawn:
 | 
			
		||||
		public static readonly Material cumSplatch1 = MaterialPool.MatFrom("splatch_1", ShaderDatabase.Cutout);
 | 
			
		||||
		public static readonly Material cumSplatch2 = MaterialPool.MatFrom("splatch_2", ShaderDatabase.Cutout);
 | 
			
		||||
		public static readonly Material cumSplatch3 = MaterialPool.MatFrom("splatch_3", ShaderDatabase.Cutout);
 | 
			
		||||
		public static readonly Material cumSplatch4 = MaterialPool.MatFrom("splatch_4", ShaderDatabase.Cutout);
 | 
			
		||||
		public static readonly Material cumSplatch5 = MaterialPool.MatFrom("splatch_5", ShaderDatabase.Cutout);
 | 
			
		||||
		public static readonly Material cumSplatch6 = MaterialPool.MatFrom("splatch_6", ShaderDatabase.Cutout);
 | 
			
		||||
		public static readonly Material cumSplatch7 = MaterialPool.MatFrom("splatch_7", ShaderDatabase.Cutout);
 | 
			
		||||
		public static readonly Material cumSplatch8 = MaterialPool.MatFrom("splatch_8", ShaderDatabase.Cutout);
 | 
			
		||||
		public static readonly Material cumSplatch9 = MaterialPool.MatFrom("splatch_9", ShaderDatabase.Cutout);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		//[SyncMethod]
 | 
			
		||||
		public static Material pickRandomSplatch()
 | 
			
		||||
		{
 | 
			
		||||
			//Rand.PopState();
 | 
			
		||||
			//Rand.PushState(RJW_Multiplayer.PredictableSeed());
 | 
			
		||||
			int rand = Rand.Range(0, 8);
 | 
			
		||||
			switch (rand)
 | 
			
		||||
			{
 | 
			
		||||
				case 0:
 | 
			
		||||
					return cumSplatch1;
 | 
			
		||||
				case 1:
 | 
			
		||||
					return cumSplatch2;
 | 
			
		||||
				case 2:
 | 
			
		||||
					return cumSplatch3;
 | 
			
		||||
				case 3:
 | 
			
		||||
					return cumSplatch4;
 | 
			
		||||
				case 4:
 | 
			
		||||
					return cumSplatch5;
 | 
			
		||||
				case 5:
 | 
			
		||||
					return cumSplatch6;
 | 
			
		||||
				case 6:
 | 
			
		||||
					return cumSplatch7;
 | 
			
		||||
				case 7:
 | 
			
		||||
					return cumSplatch8;
 | 
			
		||||
				case 8:
 | 
			
		||||
					return cumSplatch9;
 | 
			
		||||
			}
 | 
			
		||||
			return null;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										76
									
								
								1.5/Source/Mod/WorkGivers/WorkGiver_CleanSelf.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,76 @@
 | 
			
		|||
using RimWorld;
 | 
			
		||||
using Verse;
 | 
			
		||||
using Verse.AI;
 | 
			
		||||
using rjw;
 | 
			
		||||
 | 
			
		||||
namespace rjwcum
 | 
			
		||||
{
 | 
			
		||||
	public class WorkGiver_CleanSelf : WorkGiver_Scanner
 | 
			
		||||
	{
 | 
			
		||||
		public override PathEndMode PathEndMode
 | 
			
		||||
		{
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return PathEndMode.InteractionCell;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override Danger MaxPathDanger(Pawn pawn)
 | 
			
		||||
		{
 | 
			
		||||
			return Danger.Deadly;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override ThingRequest PotentialWorkThingRequest
 | 
			
		||||
		{
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				return ThingRequest.ForGroup(ThingRequestGroup.Pawn);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//conditions for self-cleaning job to be available
 | 
			
		||||
		public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
 | 
			
		||||
		{
 | 
			
		||||
			if (xxx.DubsBadHygieneIsActive && CumBase.dubsDBH_block_CleanSelf) // selfclean only in shower/bath etc
 | 
			
		||||
				return false;
 | 
			
		||||
 | 
			
		||||
			if (pawn != t)
 | 
			
		||||
				return false;
 | 
			
		||||
 | 
			
		||||
			if (!pawn.CanReserve(t, 1, -1, null, forced))
 | 
			
		||||
				return false;
 | 
			
		||||
 | 
			
		||||
			if (pawn.IsDesignatedHero())
 | 
			
		||||
			{
 | 
			
		||||
				if (!forced && CumBase.manual_hero_CleanSelf)
 | 
			
		||||
				{
 | 
			
		||||
					//ModLog.Message("WorkGiver_CleanSelf::not player interaction for hero, exit");
 | 
			
		||||
					return false;
 | 
			
		||||
				}
 | 
			
		||||
				if (!pawn.IsHeroOwner())
 | 
			
		||||
				{
 | 
			
		||||
					//ModLog.Message("WorkGiver_CleanSelf::player interaction for not owned hero, exit");
 | 
			
		||||
					return false;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			Hediff hediff = pawn.health.hediffSet.hediffs.Find(x => (x.def == HediffDefOf.Hediff_CumController));
 | 
			
		||||
			if (hediff == null)
 | 
			
		||||
				return false;
 | 
			
		||||
 | 
			
		||||
			int minAge = 3 * 2500;//3 hours in-game must have passed
 | 
			
		||||
			if (!forced)
 | 
			
		||||
				if (!(hediff.ageTicks > minAge))
 | 
			
		||||
				{
 | 
			
		||||
					//ModLog.Message("WorkGiver_CleanSelf:: 3 hours in-game must pass to self-clean, exit");
 | 
			
		||||
					return false;
 | 
			
		||||
				}
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
 | 
			
		||||
		{
 | 
			
		||||
			return JobMaker.MakeJob(JobDefOf.CleanSelf);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								1.5/Source/Mod/packages.config
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<packages>
 | 
			
		||||
  <package id="Lib.Harmony" version="2.3.3" targetFramework="net472" />
 | 
			
		||||
</packages>
 | 
			
		||||
							
								
								
									
										32
									
								
								1.5/Source/Properties/AssemblyInfo.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
using System.Reflection;
 | 
			
		||||
using System.Runtime.CompilerServices;
 | 
			
		||||
using System.Runtime.InteropServices;
 | 
			
		||||
 | 
			
		||||
// General Information about an assembly is controlled through the following 
 | 
			
		||||
// set of attributes. Change these attribute values to modify the information
 | 
			
		||||
// associated with an assembly.
 | 
			
		||||
[assembly: AssemblyTitle("RimJobWorld Cum")]
 | 
			
		||||
[assembly: AssemblyDescription("")]
 | 
			
		||||
[assembly: AssemblyConfiguration("")]
 | 
			
		||||
[assembly: AssemblyCompany("")]
 | 
			
		||||
[assembly: AssemblyProduct("RimJobWorld Cum")]
 | 
			
		||||
[assembly: AssemblyCopyright("Copyright © 2022")]
 | 
			
		||||
[assembly: AssemblyTrademark("")]
 | 
			
		||||
[assembly: AssemblyCulture("")]
 | 
			
		||||
 | 
			
		||||
// Setting ComVisible to false makes the types in this assembly not visible 
 | 
			
		||||
// to COM components. If you need to access a type in this assembly from 
 | 
			
		||||
// COM, set the ComVisible attribute to true on that type.
 | 
			
		||||
[assembly: ComVisible(false)]
 | 
			
		||||
 | 
			
		||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
 | 
			
		||||
[assembly: Guid("c2825019-7f0b-456d-85a3-479c1a2a8805")]
 | 
			
		||||
 | 
			
		||||
// Version information for an assembly consists of the following four values:
 | 
			
		||||
//
 | 
			
		||||
//      Major Version
 | 
			
		||||
//      Minor Version 
 | 
			
		||||
//      Build Number
 | 
			
		||||
//      Revision
 | 
			
		||||
//
 | 
			
		||||
[assembly: AssemblyVersion("1.0.0.0")]
 | 
			
		||||
							
								
								
									
										25
									
								
								1.5/Source/mod.sln
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
 | 
			
		||||
Microsoft Visual Studio Solution File, Format Version 12.00
 | 
			
		||||
# Visual Studio Version 16
 | 
			
		||||
VisualStudioVersion = 16.0.30907.101
 | 
			
		||||
MinimumVisualStudioVersion = 10.0.40219.1
 | 
			
		||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RimJobWorldCum", "Mod\RimJobWorldCum.csproj", "{3FC2D442-19B8-4CF9-9D35-CD13B6AC7B28}"
 | 
			
		||||
EndProject
 | 
			
		||||
Global
 | 
			
		||||
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 | 
			
		||||
		Debug|Any CPU = Debug|Any CPU
 | 
			
		||||
		Release|Any CPU = Release|Any CPU
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 | 
			
		||||
		{3FC2D442-19B8-4CF9-9D35-CD13B6AC7B28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{3FC2D442-19B8-4CF9-9D35-CD13B6AC7B28}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{3FC2D442-19B8-4CF9-9D35-CD13B6AC7B28}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{3FC2D442-19B8-4CF9-9D35-CD13B6AC7B28}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
	GlobalSection(SolutionProperties) = preSolution
 | 
			
		||||
		HideSolutionNode = FALSE
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
	GlobalSection(ExtensibilityGlobals) = postSolution
 | 
			
		||||
		SolutionGuid = {5A0C2732-36A9-4ACA-807E-019E02C37E10}
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
EndGlobal
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								1.5/Textures/CumIcon_drenched.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 419 B  | 
							
								
								
									
										
											BIN
										
									
								
								1.5/Textures/CumIcon_dripping.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 385 B  | 
							
								
								
									
										
											BIN
										
									
								
								1.5/Textures/CumIcon_little.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 226 B  | 
							
								
								
									
										
											BIN
										
									
								
								1.5/Textures/CumIcon_some.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 265 B  | 
							
								
								
									
										
											BIN
										
									
								
								1.5/Textures/splatch_1.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.3 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								1.5/Textures/splatch_2.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								1.5/Textures/splatch_3.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.9 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								1.5/Textures/splatch_4.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.9 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								1.5/Textures/splatch_5.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.9 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								1.5/Textures/splatch_6.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3.4 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								1.5/Textures/splatch_7.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.2 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								1.5/Textures/splatch_8.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.4 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								1.5/Textures/splatch_9.png
									
										
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 3 KiB  | 
| 
						 | 
				
			
			@ -7,6 +7,7 @@
 | 
			
		|||
	<supportedVersions>
 | 
			
		||||
		<li>1.3</li>
 | 
			
		||||
		<li>1.4</li>
 | 
			
		||||
		<li>1.5</li>
 | 
			
		||||
	</supportedVersions>
 | 
			
		||||
	<packageId>rjw.cum</packageId>
 | 
			
		||||
	<modDependencies>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||