code:
using System;
using System.Collections.Generic;
using RimWorld;
using Verse;

namespace rjw
{
	public class Need_Sex : Need_Seeker
	{
		public bool isInvisible => pawn.Map == null;

		private static float decay_per_day = 0.3f;

		// TODO: make these threshold values constants or at least static
		// readonly properties, if they're meant for patching.

		public float thresh_frustrated() => 0.05f;

		public float thresh_horny() => 0.25f;

		public float thresh_neutral() => 0.50f;

		public float thresh_satisfied() => 0.75f;

		public float thresh_ahegao() => 0.95f;

		public Need_Sex(Pawn pawn) : base(pawn)
		{
			//if (xxx.is_mechanoid(pawn)) return; //Added by nizhuan-jjr:Misc.Robots are not allowed to have sex, so they don't need sex actually.
			threshPercents = new List<float>
			{
				thresh_frustrated(),
				thresh_horny(),
				thresh_neutral(),
				thresh_satisfied(),
				thresh_ahegao()
			};
		}

		// These are overridden just for other mods to patch and alter their behavior.
		// Without it, they would need to patch `Need` itself, adding a type check to
		// every single need IN THE GAME before executing the new behavior.
		public override float CurInstantLevel
		{
			get { return base.CurInstantLevel; }
		}

		public override float CurLevel
		{
			get { return base.CurLevel; }
			set { base.CurLevel = value; }
		}

		//public override bool ShowOnNeedList
		//{
		//	get
		//	{
		//		if (Genital_Helper.has_genitals(pawn))
		//			return true;

		//		ModLog.Message("curLevelInt " + curLevelInt);
		//		return false;
		//	}
		//}

		//public override string GetTipString()
		//{
		//	return string.Concat(new string[]
		//	{
		//		this.LabelCap,
		//		": ",
		//		this.CurLevelPercentage.ToStringPercent(),
		//		"\n",
		//		this.def.description,
		//		"\n",
		//	});
		//}

		public static float brokenbodyfactor(Pawn pawn)
		{
			//This adds in the broken body system
			float broken_body_factor = 1f;
			if (pawn.health.hediffSet.HasHediff(xxx.feelingBroken))
			{
				switch (pawn.health.hediffSet.GetFirstHediffOfDef(xxx.feelingBroken).CurStageIndex)
				{
					case 0:
						return 0.75f;
					case 1:
						return 1.4f;
					case 2:
						return 2f;
				}
			}
			return broken_body_factor;
		}

		public static float druggedfactor(Pawn pawn)
		{
			if (pawn.health.hediffSet.HasHediff(RJWHediffDefOf.HumpShroomEffect))
			{
				//ModLog.Message("Need_Sex::druggedfactor 3 pawn is " + xxx.get_pawnname(pawn));
				return 3f;
			}

			// No humpshroom effect but addicted?
			if (pawn.health.hediffSet.HasHediff(RJWHediffDefOf.HumpShroomAddiction))
			{
				//ModLog.Message("Need_Sex::druggedfactor 0.5 pawn is " + xxx.get_pawnname(pawn));
				return 0.5f;
			}

			//ModLog.Message("Need_Sex::druggedfactor 1 pawn is " + xxx.get_pawnname(pawn));
			return 1f;
		}

		static float diseasefactor(Pawn pawn)
		{
			return 1f;
		}

		static float futafactor(Pawn pawn)
		{
			// Checks for doubly-fertile futa.
			// Presumably, they got twice the hormones coursing through their brain.
			return Genital_Helper.is_futa(pawn) ? 2.0f : 1.0f;
		}

		static float agefactor(Pawn pawn)
		{
			// Age check was moved to start of `NeedInterval` and this factor
			// is no longer useful in base RJW.  It is left here in case any
			// mod patches this factor.
			return 1f;
		}

		/// <summary>
		/// Gets the cumulative factors affecting decay for a given pawn.
		/// </summary>
		public static float GetFallFactorFor(Pawn pawn)
		{
			return brokenbodyfactor(pawn) *
				druggedfactor(pawn) *
				diseasefactor(pawn) *
				agefactor(pawn) *
				futafactor(pawn);
		}

		static float fall_per_tick(Pawn pawn)
		{
			var fall_per_tick = decay_per_day / GenDate.TicksPerDay * GetFallFactorFor(pawn);
			//--ModLog.Message("Need_Sex::NeedInterval is called - pawn is " + xxx.get_pawnname(pawn) + " is has both genders " + (Genital_Helper.has_penis(pawn) && Genital_Helper.has_vagina(pawn)));
			//ModLog.Message(" " + xxx.get_pawnname(pawn) + "'s sex need stats:: fall_per_tick: " + fall_per_tick + ", sex_need_factor_from_lifestage: " + sex_need_factor_from_lifestage(pawn) );
			return fall_per_tick;
		}

		public override void NeedInterval()
		{
			if (isInvisible) return; // no caravans

			// Asexual or too young.
			if (xxx.is_asexual(pawn) || !xxx.can_do_loving(pawn))
			{
				CurLevel = 0.5f;
				return;
			}

			//--ModLog.Message("Need_Sex::NeedInterval is called0 - pawn is "+xxx.get_pawnname(pawn));

			if (!def.freezeWhileSleeping || pawn.Awake())
			{
				// `NeedInterval` is called by `Pawn_NeedsTracker` once every 150 ticks, which is around .06 game hours.
				var fallPerCall = 150 * fall_per_tick(pawn);
				var sexDriveModifier = xxx.get_sex_drive(pawn);
				var decayRateModifier = RJWSettings.sexneed_decay_rate;
				var decayThisCall = fallPerCall * sexDriveModifier * decayRateModifier;
				CurLevel -= decayThisCall;

				// ModLog.Message($" {xxx.get_pawnname(pawn)}'s sex need stats:: Decay/call: {decayThisCall}, Dec. rate: {decayRateModifier}, Cur.lvl: {CurLevel}, Sex drive: {sexDriveModifier}");
			}

			//--ModLog.Message("Need_Sex::NeedInterval is called1");
		}
	}
}


code:
using Verse;

namespace rjw
{
	/// <summary>
	/// Looks up and returns a BodyPartTagDef defined in the XML
	/// </summary>
	public static class BodyPartTagDefOf {
		public static BodyPartTagDef RJW_Fertility
		{
			get
			{
				if (a == null) a = (BodyPartTagDef)GenDefDatabase.GetDef(typeof(BodyPartTagDef), "RJW_Fertility");
				return a;
			}
		}
		private static BodyPartTagDef a;
	}

}

repo_name: PhaetonYT/rjw

license: mit


code:
using RimWorld;
using System;
using System.Collections.Generic;
using UnityEngine;
using Verse;

namespace rjw
{
	/// <summary>
	/// Calculates a pawn's fertility based on its age and fertility sources
	/// </summary>
	public class PawnCapacityWorker_Fertility : PawnCapacityWorker
	{
		public override float CalculateCapacityLevel(HediffSet diffSet, List<PawnCapacityUtility.CapacityImpactor> impactors = null)
		{
			Pawn pawn = diffSet.pawn;
			var parts = pawn.GetGenitalsList();

			if (!Genital_Helper.has_penis_fertile(pawn, parts) && !Genital_Helper.has_vagina(pawn, parts))
				return 0;

			if (Genital_Helper.has_ovipositorF(pawn, parts) || Genital_Helper.has_ovipositorM(pawn, parts))
				return 0;

			//ModLog.Message("PawnCapacityWorker_Fertility::CalculateCapacityLevel is called for: " + xxx.get_pawnname(pawn));

			if (!pawn.RaceHasFertility())
			{
				//Log.Message(" Fertility_filter, no fertility for : " + pawn.kindDef.defName);
				return 0f;
			}

			//androids only fertile with archotech parts
			if (AndroidsCompatibility.IsAndroid(pawn) && !(AndroidsCompatibility.AndroidPenisFertility(pawn) || AndroidsCompatibility.AndroidVaginaFertility(pawn)))
			{
				//Log.Message(" Android has no archotech genitals set fertility to 0 for: " + pawn.kindDef.defName);
				return 0f;
			}

			float result = 1;

			if (RJWPregnancySettings.UseVanillaPregnancy && pawn.RaceProps.Humanlike)
			{
				float fertilityStat = pawn.GetStatValue(StatDefOf.Fertility);
				if (fertilityStat != 1)
				{
					result *= fertilityStat;
					impactors?.Add(new CapacityImpactorVanillaFertility());
				}
			}
			else
			{
				float ageFactor = CalculateAgeImpact(pawn);
				if (ageFactor != 1)
				{
					result *= ageFactor;
					impactors?.Add(new CapacityImpactorAge());
				}
			}

			result *= PawnCapacityUtility.CalculateTagEfficiency(diffSet, BodyPartTagDefOf.RJW_Fertility, 1f, FloatRange.ZeroToOne, impactors);

			//ModLog.Message("PawnCapacityWorker_Fertility::CalculateCapacityLevel result is: " + result);
			return result;

		}

		public override bool CanHaveCapacity(BodyDef body)
		{
			return body.HasPartWithTag(BodyPartTagDefOf.RJW_Fertility);
		}

		private float CalculateAgeImpact(Pawn pawn)
		{
			RaceProperties race = pawn.RaceProps;
			float startAge = 0f;	//raise fertility
			float startMaxAge = 0f;	//max fertility
			float endAge = race.lifeExpectancy * (RJWPregnancySettings.fertility_endage_male * 0.7f); // Age when males start to lose potency.
			float zeroFertility = race.lifeExpectancy * RJWPregnancySettings.fertility_endage_male;	// Age when fertility hits 0%.

			if (xxx.is_female(pawn))
			{
				if (xxx.is_animal(pawn))
				{
					endAge = race.lifeExpectancy * (RJWPregnancySettings.fertility_endage_female_animal * 0.6f);
					zeroFertility = race.lifeExpectancy * RJWPregnancySettings.fertility_endage_female_animal;
				}
				else
				{
					endAge = race.lifeExpectancy * (RJWPregnancySettings.fertility_endage_female_humanlike * 0.6f); // Age when fertility begins to drop.
					zeroFertility = race.lifeExpectancy * RJWPregnancySettings.fertility_endage_female_humanlike; // Age when fertility hits 0%.
				}
			}
			//If pawn is an animal, first reproductive lifestage is (usually) adult, so set startMaxAge at first reproductive stage, and startAge at stage before that.
			int adult;
			if (xxx.is_animal(pawn) && (adult = race.lifeStageAges.FirstIndexOf((ls) => ls.def.reproductive)) > 0)
			{
				startAge = race.lifeStageAges[adult - 1].minAge;
				startMaxAge = race.lifeStageAges[adult].minAge;
			}
			else
			{
				foreach (LifeStageAge lifestage in race.lifeStageAges)
				{
					if (lifestage.def.reproductive)
						//presumably teen stage
						if (startAge == 0f && startMaxAge == 0f)
						{
							startAge = lifestage.minAge;
							startMaxAge = (Mathf.Max(startAge + (startAge + endAge) * 0.08f, startAge));
						}
						//presumably adult stage
						else
						{
							if (startMaxAge > lifestage.minAge) // ensure peak fertility stays at start or a bit before adult stage
								startMaxAge = lifestage.minAge;
						}
				}
			}
			//Log.Message(" Fertility ages for " + pawn.Name + " are: " + startAge + ", " + startMaxAge + ", " + endAge + ", " + endMaxAge);

			return GenMath.FlatHill(startAge, startMaxAge, endAge, zeroFertility, pawn.ageTracker.AgeBiologicalYearsFloat);
		}

		// Tooltips are hardcoded to only use concrete vanilla CapacityImpactors(?!), so we need to subclass one
		// in order to show anything without gratuitous patching (and possibly stepping on the toes of any mod that
		// happens to mess with these tooltips). CapacityImpactorPain doesn't have any fields or specialised methods,
		// so that's what we'll use.
		public class CapacityImpactorAge : PawnCapacityUtility.CapacityImpactorPain
		{
			public override string Readable(Pawn pawn)
			{
				return "AgeImpactor".Translate() + pawn.ageTracker.AgeBiologicalYearsFloat.ToStringApproxAge();
			}
		}

		public class CapacityImpactorVanillaFertility : PawnCapacityUtility.CapacityImpactorPain
		{
			public override string Readable(Pawn pawn)
			{
				return "VanillaFertilityImpactor".Translate(
					((int) (pawn.GetStatValue(StatDefOf.Fertility) * 100)).Named("VALUE")
				);
			}
		}
	}
}


code:
using System;
using System.Collections.Generic;
using System.Linq;
using Verse;
using UnityEngine;
using RimWorld;
using Verse.Sound;

namespace rjw.MainTab
{
	[StaticConstructorOnStartup]
	public static class DesignatorCheckbox
	{
		public static readonly Texture2D CheckboxOnTex = ContentFinder<Texture2D>.Get("UI/Commands/Service_on");
		public static readonly Texture2D CheckboxOffTex = ContentFinder<Texture2D>.Get("UI/Commands/Service_off");
		public static readonly Texture2D CheckboxDisabledTex = ContentFinder<Texture2D>.Get("UI/Commands/Service_Refuse");

		private static bool checkboxPainting;
		private static bool checkboxPaintingState;

		public static void Checkbox(Vector2 topLeft, ref bool checkOn, float size = 24f, bool disabled = false, Texture2D texChecked = null, Texture2D texUnchecked = null, Texture2D texDisabled = null)
		{
			Checkbox(topLeft.x, topLeft.y, ref checkOn, size, disabled, texChecked, texUnchecked);
		}

		public static void Checkbox(float x, float y, ref bool checkOn, float size = 24f, bool disabled = false, Texture2D texChecked = null, Texture2D texUnchecked = null, Texture2D texDisabled = null)
		{
			Rect rect = new Rect(x, y, size, size);
			CheckboxDraw(x, y, checkOn, disabled, size, texChecked, texUnchecked,texDisabled);
			if (!disabled)
			{
				MouseoverSounds.DoRegion(rect);
				bool flag = false;
				Widgets.DraggableResult draggableResult = Widgets.ButtonInvisibleDraggable(rect, false);
				if (draggableResult == Widgets.DraggableResult.Pressed)
				{
					checkOn = !checkOn;
					flag = true;
				}
				else if (draggableResult == Widgets.DraggableResult.Dragged)
				{
					checkOn = !checkOn;
					flag = true;
					checkboxPainting = true;
					checkboxPaintingState = checkOn;
				}
				if (Mouse.IsOver(rect) && checkboxPainting && Input.GetMouseButton(0) && checkOn != checkboxPaintingState)
				{
					checkOn = checkboxPaintingState;
					flag = true;
				}
				if (flag)
				{
					if (checkOn)
					{
						SoundDefOf.Checkbox_TurnedOn.PlayOneShotOnCamera(null);
					}
					else
					{
						SoundDefOf.Checkbox_TurnedOff.PlayOneShotOnCamera(null);
					}
				}
			}
		}

		private static void CheckboxDraw(float x, float y, bool active, bool disabled, float size = 24f, Texture2D texChecked = null, Texture2D texUnchecked = null, Texture2D texDisabled = null)
		{
			Texture2D image;
			if (disabled)
			{
				image = ((!(texDisabled != null)) ? CheckboxDisabledTex : texDisabled);
			}
			else if (active)
			{
				image = ((!(texChecked != null)) ? CheckboxOnTex : texChecked);
			}
			else
			{
				image = ((!(texUnchecked != null)) ? CheckboxOffTex : texUnchecked);
			}
			Rect position = new Rect(x, y, size, size);
			GUI.DrawTexture(position, image);
		}

	}
}


code:
using System;
using System.Collections.Generic;
using System.Linq;
using Verse;
using UnityEngine;
using RimWorld;
using Verse.Sound;

namespace rjw.MainTab.Checkbox
{
	[StaticConstructorOnStartup]
	public abstract class PawnColumnCheckbox : PawnColumnWorker
	{
		public static readonly Texture2D CheckboxOnTex;
		public static readonly Texture2D CheckboxOffTex;
		public static readonly Texture2D CheckboxDisabledTex;

		public const int HorizontalPadding = 2;

		public override void DoCell(Rect rect, Pawn pawn, RimWorld.PawnTable table)
		{
			if (!this.HasCheckbox(pawn))
			{
				return;
			}
			if (Find.TickManager.TicksGame % 60 == 0)
			{
				pawn.UpdatePermissions();
				//Log.Message("GetDisabled UpdateCanDesignateService for " + xxx.get_pawnname(pawn));
				//Log.Message("UpdateCanDesignateService " + pawn.UpdateCanDesignateService());
				//Log.Message("CanDesignateService " + pawn.CanDesignateService());
				//Log.Message("GetDisabled " + GetDisabled(pawn));
			}
			int num = (int)((rect.width - 24f) / 2f);
			int num2 = Mathf.Max(3, 0);
			Vector2 vector = new Vector2(rect.x + (float)num, rect.y + (float)num2);
			Rect rect2 = new Rect(vector.x, vector.y, 24f, 24f);
			bool disabled = this.GetDisabled(pawn);
			bool value;
			if (disabled)
			{
				value = false;
			}
			else
			{
				value = this.GetValue(pawn);
			}
			bool flag = value;
			Vector2 topLeft = vector;
			//Widgets.Checkbox(topLeft, ref value, 24f, disabled, CheckboxOnTex, CheckboxOffTex, CheckboxDisabledTex);
			MakeCheckbox(topLeft, ref value, 24f, disabled, CheckboxOnTex, CheckboxOffTex, CheckboxDisabledTex);
			if (Mouse.IsOver(rect2))
			{
				string tip = this.GetTip(pawn);
				if (!tip.NullOrEmpty())
				{
					TooltipHandler.TipRegion(rect2, tip);
				}
			}
			if (value != flag)
			{
				this.SetValue(pawn, value);
			}
		}

		protected void MakeCheckbox(Vector2 topLeft, ref bool value, float v = 24f, bool disabled = false, Texture2D checkboxOnTex = null, Texture2D checkboxOffTex = null, Texture2D checkboxDisabledTex = null)
		{
			Widgets.Checkbox(topLeft, ref value, v, disabled, checkboxOnTex, checkboxOffTex, checkboxDisabledTex);
		}

		protected virtual string GetTip(Pawn pawn)
		{
			return null;
		}

		protected virtual bool HasCheckbox(Pawn pawn)
		{
			return false;
		}

		protected abstract bool GetValue(Pawn pawn);

		protected abstract void SetValue(Pawn pawn, bool value);

		protected virtual bool GetDisabled(Pawn pawn)
		{
			return false;
		}
	}
}


code:
using RimWorld;
using UnityEngine;
using Verse;

namespace rjw.MainTab.Checkbox
{
	[StaticConstructorOnStartup]
	public class PawnColumnWorker_BreedAnimal : PawnColumnWorker_Checkbox
	{
		public static readonly Texture2D CheckboxOnTex = ContentFinder<Texture2D>.Get("UI/Commands/Breeding_Pawn_on");
		public static readonly Texture2D CheckboxOffTex = ContentFinder<Texture2D>.Get("UI/Commands/Breeding_Pawn_off");
		public static readonly Texture2D CheckboxDisabledTex = ContentFinder<Texture2D>.Get("UI/Commands/Breeding_Pawn_Refuse");
		protected override bool HasCheckbox(Pawn pawn)
		{
			return pawn.CanDesignateBreeding();
		}
		protected bool GetDisabled(Pawn pawn)
		{
			return !pawn.CanDesignateBreeding();
		}

		protected override bool GetValue(Pawn pawn)
		{
			return pawn.IsDesignatedBreeding() && xxx.is_animal(pawn);
		}

		protected override void SetValue(Pawn pawn, bool value, PawnTable table)
		{
			if (value == this.GetValue(pawn)) return;
			pawn.ToggleBreeding();
		}
	}
}


code:
using RimWorld;
using UnityEngine;
using Verse;

namespace rjw.MainTab.Checkbox
{
	[StaticConstructorOnStartup]
	public class PawnColumnWorker_BreedHumanlike : PawnColumnWorker_Checkbox
	{
		public static readonly Texture2D CheckboxOnTex = ContentFinder<Texture2D>.Get("UI/Commands/Breeding_Pawn_on");
		public static readonly Texture2D CheckboxOffTex = ContentFinder<Texture2D>.Get("UI/Commands/Breeding_Pawn_off");
		public static readonly Texture2D CheckboxDisabledTex = ContentFinder<Texture2D>.Get("UI/Commands/Breeding_Pawn_Refuse");
		protected override bool HasCheckbox(Pawn pawn)
		{
			return pawn.CanDesignateBreeding();
		}
		protected bool GetDisabled(Pawn pawn)
		{
			return !pawn.CanDesignateBreeding();
		}

		protected override bool GetValue(Pawn pawn)
		{
			return pawn.IsDesignatedBreeding() && xxx.is_human(pawn);
		}

		protected override void SetValue(Pawn pawn, bool value, PawnTable table)
		{
			if (value == this.GetValue(pawn)) return;
			pawn.ToggleBreeding();
		}
	}
}


code:
using RimWorld;
using UnityEngine;
using Verse;

namespace rjw.MainTab.Checkbox
{
	[StaticConstructorOnStartup]
	public class PawnColumnWorker_BreederAnimal : PawnColumnWorker_Checkbox
	{
		public static readonly Texture2D CheckboxOnTex = ContentFinder<Texture2D>.Get("UI/Commands/Breeding_Pawn_on");
		public static readonly Texture2D CheckboxOffTex = ContentFinder<Texture2D>.Get("UI/Commands/Breeding_Pawn_off");
		public static readonly Texture2D CheckboxDisabledTex = ContentFinder<Texture2D>.Get("UI/Commands/Breeding_Pawn_Refuse");
		protected override bool HasCheckbox(Pawn pawn)
		{
			return pawn.CanDesignateBreedingAnimal();
		}
		protected bool GetDisabled(Pawn pawn)
		{
			return !pawn.CanDesignateBreedingAnimal();
		}

		protected override bool GetValue(Pawn pawn)
		{
			return pawn.IsDesignatedBreedingAnimal() && xxx.is_animal(pawn);
		}

		protected override void SetValue(Pawn pawn, bool value, PawnTable table)
		{
			if (value == this.GetValue(pawn)) return;
			pawn.ToggleBreedingAnimal();
		}
	}
}


code:
using RimWorld;
using UnityEngine;
using Verse;

namespace rjw.MainTab.Checkbox
{
	[StaticConstructorOnStartup]
	public class PawnColumnWorker_Comfort : PawnColumnWorker_Checkbox
	{
		public static readonly Texture2D CheckboxOnTex = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_on");
		public static readonly Texture2D CheckboxOffTex = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_off");
		public static readonly Texture2D CheckboxDisabledTex = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_Refuse");
		protected override bool HasCheckbox(Pawn pawn)
		{
			return pawn.CanDesignateComfort();
		}
		protected bool GetDisabled(Pawn pawn)
		{
			return !pawn.CanDesignateComfort();
		}

		protected override bool GetValue(Pawn pawn)
		{
			return pawn.IsDesignatedComfort();
		}

		protected override void SetValue(Pawn pawn, bool value, PawnTable table)
		{
			pawn.ToggleComfort();
		}
	}
}


code:
using RimWorld;
using UnityEngine;
using Verse;

namespace rjw.MainTab.Checkbox
{
	[StaticConstructorOnStartup]
	public class PawnColumnWorker_Hero : PawnColumnCheckbox
	{
		//public static readonly Texture2D CheckboxOnTex = ContentFinder<Texture2D>.Get("UI/Commands/Hero_on");
		//public static readonly Texture2D CheckboxOffTex = ContentFinder<Texture2D>.Get("UI/Commands/Hero_off");
		//public static readonly Texture2D CheckboxDisabledTex = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_Refuse");

		//public static readonly Texture2D iconAccept = ContentFinder<Texture2D>.Get("UI/Commands/Hero_off");
		//static readonly Texture2D iconCancel = ContentFinder<Texture2D>.Get("UI/Commands/Hero_on");
		//protected override Texture2D GetIconFor(Pawn pawn)
		//{
		//	return pawn.CanDesignateHero() ? pawn.IsDesignatedHero() ? iconAccept : iconCancel : null;
		//}

		//protected override string GetIconTip(Pawn pawn)
		//{
		//	return "PawnColumnWorker_IsHero".Translate();
		//	;
		//}

		//public static Texture2D CheckboxOnTex = ContentFinder<Texture2D>.Get("UI/Commands/Hero_on");
		//public static Texture2D CheckboxOffTex = ContentFinder<Texture2D>.Get("UI/Commands/Hero_off");
		protected override bool HasCheckbox(Pawn pawn)
		{
			return pawn.CanDesignateHero() || pawn.IsDesignatedHero();
		}

		protected override bool GetValue(Pawn pawn)
		{
			return pawn.IsDesignatedHero();
		}

		protected override void SetValue(Pawn pawn, bool value)
		{
			if (pawn.IsDesignatedHero()) return;
			pawn.ToggleHero();

			//reload/update tab
			var rjwtab = DefDatabase<MainButtonDef>.GetNamed("RJW_MainButton");
			Find.MainTabsRoot.ToggleTab(rjwtab, false);//off
			Find.MainTabsRoot.ToggleTab(rjwtab, false);//on
		}
	}
}


code:
using RimWorld;
using UnityEngine;
using Verse;

namespace rjw.MainTab.Checkbox
{
	[StaticConstructorOnStartup]
	public class PawnColumnWorker_Whore : PawnColumnWorker_Checkbox
	{
		public static readonly Texture2D CheckboxOnTex = ContentFinder<Texture2D>.Get("UI/Commands/Service_on");
		public static readonly Texture2D CheckboxOffTex = ContentFinder<Texture2D>.Get("UI/Commands/Service_off");
		public static readonly Texture2D CheckboxDisabledTex = ContentFinder<Texture2D>.Get("UI/Commands/Service_Refuse");
		protected override bool HasCheckbox(Pawn pawn)
		{
			return pawn.CanDesignateService();
		}
		protected bool GetDisabled(Pawn pawn)
		{
			return !pawn.CanDesignateService();
		}

		protected override bool GetValue(Pawn pawn)
		{
			return pawn.IsDesignatedService();
		}

		protected override void SetValue(Pawn pawn, bool value, PawnTable table)
		{
			pawn.ToggleService();
		}
	}
}


code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;

namespace rjw.MainTab.DefModExtensions
{
	public class RJW_PawnTable : DefModExtension
	{
		public string label;
	}
}


code:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RimWorld;
using RimWorld.Planet;
using UnityEngine;
using Verse;

namespace rjw.MainTab.Icon
{
	[StaticConstructorOnStartup]
	public class PawnColumnWorker_IsBreeder : PawnColumnWorker_Icon
	{
		private static readonly Texture2D comfortOn = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_on");
		private readonly Texture2D comfortOff = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_off");
		private readonly Texture2D comfortOff_nobg = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_off_nobg");
		protected override Texture2D GetIconFor(Pawn pawn)
		{
			return pawn.CanDesignateBreeding() ? pawn.IsDesignatedBreeding() ? comfortOn : comfortOff : comfortOff_nobg;
			//return xxx.is_slave(pawn) ? comfortOff : null;
		}
		protected override string GetIconTip(Pawn pawn)
		{
			return "PawnColumnWorker_IsBreeder".Translate();
			;
		}
	}
}


code:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RimWorld;
using RimWorld.Planet;
using UnityEngine;
using Verse;

namespace rjw.MainTab.Icon
{
	[StaticConstructorOnStartup]
	public class PawnColumnWorker_IsComfort : PawnColumnWorker_Icon
	{
		private readonly Texture2D comfortOn = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_on");
		private readonly Texture2D comfortOff = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_off");
		private readonly Texture2D comfortOff_nobg = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_off_nobg");
		protected override Texture2D GetIconFor(Pawn pawn)
		{
			return pawn.CanDesignateComfort() ? pawn.IsDesignatedComfort() ? comfortOn : comfortOff : comfortOff_nobg;
		}
		protected override string GetIconTip(Pawn pawn)
		{
			return "PawnColumnWorker_IsComfort".Translate();
			;
		}
	}
}


code:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RimWorld;
using RimWorld.Planet;
using UnityEngine;
using Verse;

namespace rjw.MainTab.Icon
{
	[StaticConstructorOnStartup]
	public class PawnColumnWorker_IsPrisoner : PawnColumnWorker_Icon
	{
		private static readonly Texture2D comfortOn = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_on");
		private readonly Texture2D comfortOff = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_off");
		private readonly Texture2D comfortOff_nobg = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_off_nobg");

		protected override Texture2D GetIconFor(Pawn pawn)
		{
			return pawn.IsPrisonerOfColony ? comfortOff_nobg : null;
		}
		protected override string GetIconTip(Pawn pawn)
		{
			return "PawnColumnWorker_IsPrisoner".Translate();
		}
	}
}


code:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RimWorld;
using RimWorld.Planet;
using UnityEngine;
using Verse;

namespace rjw.MainTab.Icon
{
	[StaticConstructorOnStartup]
	public class PawnColumnWorker_IsSlave : PawnColumnWorker_Icon
	{
		private readonly Texture2D comfortOn = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_on");
		private readonly Texture2D comfortOff = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_off");
		private readonly Texture2D comfortOff_nobg = ContentFinder<Texture2D>.Get("UI/Commands/ComfortPrisoner_off_nobg");
		protected override Texture2D GetIconFor(Pawn pawn)
		{
			return xxx.is_slave(pawn) ? ModsConfig.IdeologyActive ? GuestUtility.SlaveIcon : comfortOff_nobg : null;
		}
		protected override string GetIconTip(Pawn pawn)
		{
			return "PawnColumnWorker_IsSlave".Translate();
			;
		}
	}
}


code:
using RimWorld;
using UnityEngine;
using Verse;

using static rjw.GenderHelper;

namespace rjw.MainTab.Icon
{
	[StaticConstructorOnStartup]
	public class PawnColumnWorker_RJWGender : PawnColumnWorker_Gender
	{
		public static readonly Texture2D hermIcon = ContentFinder<Texture2D>.Get("UI/Icons/Gender/Genders", true);

		protected override Texture2D GetIconFor(Pawn pawn) => GetSex(pawn) switch
		{
			Sex.futa => hermIcon,
			_ => pawn.gender.GetIcon()
		};
		protected override string GetIconTip(Pawn pawn) => GetSex(pawn) switch
		{
			Sex.futa => "PawnColumnWorker_RJWGender_IsHerm".Translate(),
			_ => pawn.GetGenderLabel().CapitalizeFirst()
		};
	}
}


code:
using System.Collections.Generic;
using System.Linq;
using Verse;
using RimWorld;
using RimWorld.Planet;
using UnityEngine;
using rjw.MainTab.DefModExtensions;

namespace rjw.MainTab
{
	[StaticConstructorOnStartup]
	public class RJW_PawnTableList
	{
		public List<PawnTableDef> getdefs()
		{
			var defs = new List<PawnTableDef>();
			defs.AddRange(DefDatabase<PawnTableDef>.AllDefs.Where(x => x.HasModExtension<RJW_PawnTable>()));
			return defs;
		}
	}
	public class MainTabWindow : MainTabWindow_PawnTable
	{
		protected override float ExtraBottomSpace
		{
			get
			{
				return 53f; //default 53
			}
		}

		protected override float ExtraTopSpace
		{
			get
			{
				return 40f; //default 0
			}
		}

		protected override PawnTableDef PawnTableDef => pawnTableDef;

		protected override IEnumerable<Pawn> Pawns => pawns;

		public IEnumerable<Pawn> pawns = Find.CurrentMap.mapPawns.AllPawns.Where(p => p.RaceProps.Humanlike && p.IsColonist && !xxx.is_slave(p));
		public PawnTableDef pawnTableDef = DefDatabase<PawnTableDef>.GetNamed("RJW_PawnTable_Colonists");

		/// <summary>
		/// draw table
		/// </summary>
		/// <param name="rect"></param>
		public override void DoWindowContents(Rect rect)
		{
			base.DoWindowContents(rect);
			if (Widgets.ButtonText(new Rect(rect.x + 5f, rect.y + 5f, Mathf.Min(rect.width, 260f), 32f), "MainTabWindow_Designators".Translate(), true, true, true))
			{
				MakeMenu();
			}
		}

		public override void PostOpen()
		{
			base.PostOpen();
			Find.World.renderer.wantedMode = WorldRenderMode.None;
		}

		/// <summary>
		/// reload/update tab
		/// </summary>
		public static void Reloadtab()
		{
			var rjwtab = DefDatabase<MainButtonDef>.GetNamed("RJW_MainButton");
			Find.MainTabsRoot.ToggleTab(rjwtab, false);//off
			Find.MainTabsRoot.ToggleTab(rjwtab, false);//on
		}

		public void MakeMenu()
		{
			Find.WindowStack.Add(new FloatMenu(MakeOptions()));
		}

		/// <summary>
		/// switch pawnTable's
		/// patch this
		/// </summary>
		public List<FloatMenuOption> MakeOptions()
		{
			List<FloatMenuOption> opts = new List<FloatMenuOption>();
			PawnTableDef tabC = DefDatabase<PawnTableDef>.GetNamed("RJW_PawnTable_Colonists");
			PawnTableDef tabA = DefDatabase<PawnTableDef>.GetNamed("RJW_PawnTable_Animals");
			PawnTableDef tabP = DefDatabase<PawnTableDef>.GetNamed("RJW_PawnTable_Property");

			opts.Add(new FloatMenuOption(tabC.GetModExtension<RJW_PawnTable>().label, () =>
			{
				pawnTableDef = tabC;
				pawns = Find.CurrentMap.mapPawns.AllPawns.Where(p => p.RaceProps.Humanlike && p.IsColonist && !xxx.is_slave(p));
				Notify_ResolutionChanged();
				Reloadtab();
			}, MenuOptionPriority.Default));

			opts.Add(new FloatMenuOption(tabA.GetModExtension<RJW_PawnTable>().label, () =>
			{
				pawnTableDef = tabA;
				pawns = Find.CurrentMap.mapPawns.PawnsInFaction(Faction.OfPlayer).Where(p => xxx.is_animal(p));
				Notify_ResolutionChanged();
				Reloadtab();
			}, MenuOptionPriority.Default));

			opts.Add(new FloatMenuOption(tabP.GetModExtension<RJW_PawnTable>().label, () =>
			{
				pawnTableDef = tabP;
				pawns = Find.CurrentMap.mapPawns.AllPawns.Where(p => p.RaceProps.Humanlike && (p.IsColonist && xxx.is_slave(p) || p.IsPrisonerOfColony));
				Notify_ResolutionChanged();
				Reloadtab();
			}, MenuOptionPriority.Default));

			return opts;
		}
	}
}


code:
using System;
using UnityEngine;
using Verse;
using Verse.Sound;

namespace RimWorld
{
	// Token: 0x020013F0 RID: 5104
	public class PawnColumnWorker_Master : PawnColumnWorker
	{
		// Token: 0x17001618 RID: 5656
		// (get) Token: 0x06007D97 RID: 32151 RVA: 0x00012AE6 File Offset: 0x00010CE6
		protected override GameFont DefaultHeaderFont
		{
			get
			{
				return GameFont.Tiny;
			}
		}

		// Token: 0x06007D98 RID: 32152 RVA: 0x002CCC79 File Offset: 0x002CAE79
		public override int GetMinWidth(PawnTable table)
		{
			return Mathf.Max(base.GetMinWidth(table), 100);
		}

		// Token: 0x06007D99 RID: 32153 RVA: 0x002CCC89 File Offset: 0x002CAE89
		public override int GetOptimalWidth(PawnTable table)
		{
			return Mathf.Clamp(170, this.GetMinWidth(table), this.GetMaxWidth(table));
		}

		// Token: 0x06007D9A RID: 32154 RVA: 0x002CB126 File Offset: 0x002C9326
		public override void DoHeader(Rect rect, PawnTable table)
		{
			base.DoHeader(rect, table);
			MouseoverSounds.DoRegion(rect);
		}

		// Token: 0x06007D9B RID: 32155 RVA: 0x002CCCA3 File Offset: 0x002CAEA3
		public override void DoCell(Rect rect, Pawn pawn, PawnTable table)
		{
			if (!this.CanAssignMaster(pawn))
			{
				return;
			}
			TrainableUtility.MasterSelectButton(rect.ContractedBy(2f), pawn, true);
		}

		// Token: 0x06007D9C RID: 32156 RVA: 0x002CCCC4 File Offset: 0x002CAEC4
		public override int Compare(Pawn a, Pawn b)
		{
			int valueToCompare = this.GetValueToCompare1(a);
			int valueToCompare2 = this.GetValueToCompare1(b);
			if (valueToCompare != valueToCompare2)
			{
				return valueToCompare.CompareTo(valueToCompare2);
			}
			return this.GetValueToCompare2(a).CompareTo(this.GetValueToCompare2(b));
		}

		// Token: 0x06007D9D RID: 32157 RVA: 0x002CCD01 File Offset: 0x002CAF01
		private bool CanAssignMaster(Pawn pawn)
		{
			return pawn.RaceProps.Animal && pawn.Faction == Faction.OfPlayer && pawn.training.HasLearned(TrainableDefOf.Obedience);
		}

		// Token: 0x06007D9E RID: 32158 RVA: 0x002CCD34 File Offset: 0x002CAF34
		private int GetValueToCompare1(Pawn pawn)
		{
			if (!this.CanAssignMaster(pawn))
			{
				return 0;
			}
			if (pawn.playerSettings.Master == null)
			{
				return 1;
			}
			return 2;
		}

		// Token: 0x06007D9F RID: 32159 RVA: 0x002CCD51 File Offset: 0x002CAF51
		private string GetValueToCompare2(Pawn pawn)
		{
			if (pawn.playerSettings != null && pawn.playerSettings.Master != null)
			{
				return pawn.playerSettings.Master.Label;
			}
			return "";
		}
	}
}


code:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RimWorld;
using RimWorld.Planet;
using UnityEngine;
using Verse;

namespace rjw.MainTab
{
	public abstract class PawnColumnWorker_TextCenter : PawnColumnWorker_Text
	{
		public override void DoCell(Rect rect, Pawn pawn, PawnTable table)
		{
			Rect rect2 = new Rect(rect.x, rect.y, rect.width, Mathf.Min(rect.height, 30f));
			string textFor = GetTextFor(pawn);
			if (textFor != null)
			{
				Text.Font = GameFont.Small;
				Text.Anchor = TextAnchor.MiddleCenter;
				Text.WordWrap = false;
				Widgets.Label(rect2, textFor);
				Text.WordWrap = true;
				Text.Anchor = TextAnchor.UpperLeft;
				string tip = GetTip(pawn);
				if (!tip.NullOrEmpty())
				{
					TooltipHandler.TipRegion(rect2, tip);
				}
			}
		}
	}
}


code:
using System;
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using rjw;
using Verse;

namespace rjw.MainTab
{
	public class RJW_PawnTable_Animals : PawnTable_Animals
	{
		public RJW_PawnTable_Animals(PawnTableDef def, Func<IEnumerable<Pawn>> pawnsGetter, int uiWidth, int uiHeight) : base(def, pawnsGetter, uiWidth, uiHeight) { }

		//default sorting
		protected override IEnumerable<Pawn> LabelSortFunction(IEnumerable<Pawn> input)
		{
			//return input.OrderBy(p => p.Name);
			foreach (Pawn p in input)
				p.UpdatePermissions();
			return input.OrderByDescending(p => xxx.get_pawnname(p));
			//return input.OrderByDescending(p => (p.IsPrisonerOfColony || p.IsSlaveOfColony) != false).ThenBy(p => (p.Name.ToStringShort.Colorize(Color.yellow)));
			//return input.OrderBy(p => xxx.get_pawnname(p));
		}

		protected override IEnumerable<Pawn> PrimarySortFunction(IEnumerable<Pawn> input)
		{
			foreach (Pawn p in input)
				p.UpdatePermissions();
			return input;
			//return base.PrimarySortFunction(input);
		}

		//public IEnumerable<Pawn> FilterPawns
		//{
		//	get
		//	{
		//		ModLog.Message("FilterPawnsGet");
		//		var x = Find.CurrentMap.mapPawns.PawnsInFaction(Faction.OfPlayer).Where(p => xxx.is_animal(p));
		//		ModLog.Message("x: " + x);
		//		return x;
		//	}
		//}
	}
}


code:
using System;
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using rjw;
using Verse;

namespace rjw.MainTab
{
	public class RJW_PawnTable_Humanlikes : PawnTable_PlayerPawns
	{
		public RJW_PawnTable_Humanlikes(PawnTableDef def, Func<IEnumerable<Pawn>> pawnsGetter, int uiWidth, int uiHeight) : base(def, pawnsGetter, uiWidth, uiHeight) { }

		//default sorting
		protected override IEnumerable<Pawn> LabelSortFunction(IEnumerable<Pawn> input)
		{
			//return input.OrderBy(p => p.Name);
			foreach (Pawn p in input)
				p.UpdatePermissions();
			return input.OrderByDescending(p => (p.IsPrisonerOfColony || p.IsSlaveOfColony) != false).ThenBy(p => xxx.get_pawnname(p));
			//return input.OrderByDescending(p => (p.IsPrisonerOfColony || p.IsSlaveOfColony) != false).ThenBy(p => (p.Name.ToStringShort.Colorize(Color.yellow)));
			//return input.OrderBy(p => xxx.get_pawnname(p));
		}

		protected override IEnumerable<Pawn> PrimarySortFunction(IEnumerable<Pawn> input)
		{
			foreach (Pawn p in input)
				p.UpdatePermissions();
			return input;
			//return base.PrimarySortFunction(input);
		}

		//public static IEnumerable<Pawn> FilterPawns()
		//{
		//	return Find.CurrentMap.mapPawns.PawnsInFaction(Faction.OfPlayer).Where(p => xxx.is_animal(p));
		//}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;

namespace rjw
{
	public class Recipe_InstallAnus : Recipe_InstallPrivates
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{
			var gen_blo = Genital_Helper.anus_blocked(p);
			foreach (BodyPartRecord part in base.GetPartsToApplyOn(p, r))
				if ((!gen_blo) || (part != xxx.anus))
					yield return part;
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;

namespace rjw
{
	public class Recipe_InstallBreasts : Recipe_InstallPrivates
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{
			var gen_blo = Genital_Helper.breasts_blocked(p);
			foreach (BodyPartRecord part in base.GetPartsToApplyOn(p, r))
				if ((!gen_blo) || (part != xxx.breasts))
					yield return part;
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;

namespace rjw
{
	public class Recipe_InstallGenitals : Recipe_InstallPrivates
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{
			var gen_blo = Genital_Helper.genitals_blocked(p);
			foreach (BodyPartRecord part in base.GetPartsToApplyOn(p, r))
				if ((!gen_blo) || (part != xxx.genitals))
					yield return part;

		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;

namespace rjw
{
	public class Recipe_InstallPart : rjw_CORE_EXPOSED.Recipe_InstallOrReplaceBodyPart
	{
		public override void ApplyOnPawn(Pawn pawn, BodyPartRecord part, Pawn billDoer, List<Thing> ingredients, Bill bill)
		{
			GenderHelper.Sex before = GenderHelper.GetSex(pawn);

			base.ApplyOnPawn(pawn, part, billDoer, ingredients, bill);

			GenderHelper.Sex after = GenderHelper.GetSex(pawn);

			GenderHelper.ChangeSex(pawn, before, after);
		}
	}

	public class Recipe_InstallGenitals : Recipe_InstallPart
	{
		public override bool blocked(Pawn p)
		{
			return (Genital_Helper.genitals_blocked(p) || xxx.is_slime(p));//|| xxx.is_demon(p)
		}
	}

	public class Recipe_InstallBreasts : Recipe_InstallPart
	{
		public override bool blocked(Pawn p)
		{
			return (Genital_Helper.breasts_blocked(p) || xxx.is_slime(p));//|| xxx.is_demon(p)
		}
	}

	public class Recipe_InstallAnus : Recipe_InstallPart
	{
		public override bool blocked(Pawn p)
		{
			return (Genital_Helper.anus_blocked(p) || xxx.is_slime(p));//|| xxx.is_demon(p)
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;
using System.Linq;
using System;

namespace rjw
{
	public class Recipe_GrowBreasts : Recipe_Surgery
	{
		public override void ApplyOnPawn(Pawn pawn, BodyPartRecord part, Pawn billDoer, List<Thing> ingredients, Bill bill)
		{
			if (billDoer != null)
			{
				if (CheckSurgeryFail(billDoer, pawn, ingredients, part, bill))
				{
					return;
				}
				TaleRecorder.RecordTale(TaleDefOf.DidSurgery, new object[]
				{
					billDoer,
					pawn
				});
			}

			var oldBoobs = pawn.health.hediffSet.hediffs.FirstOrDefault(hediff => hediff.def == bill.recipe.removesHediff);
			var newBoobs = bill.recipe.addsHediff;
			var newSize = BreastSize_Helper.GetSize(newBoobs);

			GenderHelper.ChangeSex(pawn, () =>
			{
				BreastSize_Helper.HurtBreasts(pawn, part, 3 * (newSize - 1));
				if (pawn.health.hediffSet.PartIsMissing(part))
				{
					return;
				}
				if (oldBoobs != null)
				{
					pawn.health.RemoveHediff(oldBoobs);
				}
				pawn.health.AddHediff(newBoobs, part);
			});
		}

		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn pawn, RecipeDef recipeDef)
		{
			yield break;
			var chest = Genital_Helper.get_breastsBPR(pawn);

			if (pawn.health.hediffSet.PartIsMissing(chest)
				|| Genital_Helper.breasts_blocked(pawn))
			{
				yield break;
			}

			var old = recipeDef.removesHediff;
			if (old == null ? BreastSize_Helper.HasNipplesOnly(pawn, chest) : pawn.health.hediffSet.HasHediff(old, chest))
			{
				yield return chest;
			}
		}
	}
}


code:
using RimWorld;
using System.Collections.Generic;
using Verse;

namespace rjw
{
	/// <summary>
	/// Removes heddifs (restraints/cocoon)
	/// </summary>
	public class Recipe_RemoveRestraints : Recipe_RemoveHediff
	{
		public override bool AvailableOnNow(Thing pawn, BodyPartRecord part = null)
		{
			return true;
		}

		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn pawn, RecipeDef recipe)
		{
			List<Hediff> allHediffs = pawn.health.hediffSet.hediffs;
			int i = 0;
			while (true)
			{
				if (i >= allHediffs.Count)
				{
					yield break;
				}
				if (allHediffs[i].def == recipe.removesHediff && allHediffs[i].Visible)
				{
					break;
				}
				i++;
			}

			yield return allHediffs[i].Part;
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;
using System.Linq;
using System;

namespace rjw
{
	public class Recipe_ShrinkBreasts : Recipe_Surgery
	{
		public override void ApplyOnPawn(Pawn pawn, BodyPartRecord part, Pawn billDoer, List<Thing> ingredients, Bill bill)
		{
			if (billDoer != null)
			{
				if (CheckSurgeryFail(billDoer, pawn, ingredients, part, bill))
				{
					return;
				}
				TaleRecorder.RecordTale(TaleDefOf.DidSurgery, new object[]
				{
					billDoer,
					pawn
				});
			}

			if (!BreastSize_Helper.TryGetBreastSize(pawn, out var oldSize))
			{
				throw new ApplicationException("Recipe_ShrinkBreasts could not find any breasts to shrink.");
			}

			var oldBoobs = pawn.health.hediffSet.GetFirstHediffOfDef(BreastSize_Helper.GetHediffDef(oldSize));
			var newSize = oldSize - 1;
			var newBoobs = BreastSize_Helper.GetHediffDef(newSize);

			// I can't figure out how to spawn a stack of 2 meat.
			for (var i = 0; i < 2; i++)
			{
				GenSpawn.Spawn(pawn.RaceProps.meatDef, billDoer.Position, billDoer.Map);
			}

			GenderHelper.ChangeSex(pawn, () =>
			{
				BreastSize_Helper.HurtBreasts(pawn, part, 5);
				if (pawn.health.hediffSet.PartIsMissing(part))
				{
					return;
				}
				pawn.health.RemoveHediff(oldBoobs);
				pawn.health.AddHediff(newBoobs, part);
			});
		}

		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn pawn, RecipeDef recipeDef)
		{
			yield break;
			var chest = Genital_Helper.get_breastsBPR(pawn);

			if (Genital_Helper.breasts_blocked(pawn))
			{
				yield break;
			}

			if (BreastSize_Helper.TryGetBreastSize(pawn, out var size)
				//&& size > BreastSize_Helper.GetSize(Genital_Helper.flat_breasts))
				)
			{
				yield return chest;
			}
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;

namespace rjw
{
	public class Recipe_RemoveAnus : Recipe_RemovePart
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{
			if (Genital_Helper.has_anus(p))
			{
				bool blocked = Genital_Helper.anus_blocked(p) || xxx.is_slime(p);//|| xxx.is_demon(p)

				foreach (BodyPartRecord part in p.health.hediffSet.GetNotMissingParts())
					if (r.appliedOnFixedBodyParts.Contains(part.def) && (!blocked))
						yield return part;
			}
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;

namespace rjw
{
	public class Recipe_RemoveBreasts : Recipe_RemovePart
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{
			if (Genital_Helper.has_breasts(p))
			{
				bool blocked = Genital_Helper.breasts_blocked(p) || xxx.is_slime(p);//|| xxx.is_demon(p)

				foreach (BodyPartRecord part in p.health.hediffSet.GetNotMissingParts())
					if (r.appliedOnFixedBodyParts.Contains(part.def) && (!blocked))
						yield return part;
			}
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;

namespace rjw
{
	public class Recipe_RemoveGenitals : Recipe_RemovePart
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{
			if (Genital_Helper.has_genitals(p))
			{
				bool blocked = Genital_Helper.genitals_blocked(p) || xxx.is_slime(p);//|| xxx.is_demon(p)

				foreach (BodyPartRecord part in p.health.hediffSet.GetNotMissingParts())
					if (r.appliedOnFixedBodyParts.Contains(part.def) && (!blocked))
						yield return part;
			}
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;

namespace rjw
{
	public class Recipe_RemovePart : rjw_CORE_EXPOSED.Recipe_RemoveBodyPart
	{
		// Quick and dirty method to guess whether the player is harvesting the genitals or amputating them
		// due to infection. The core code can't do this properly because it considers the private part
		// hediffs as "unclean".
		public override bool blocked(Pawn p)
		{
			return xxx.is_slime(p);//|| xxx.is_demon(p)
		}

		public bool is_harvest(Pawn p, BodyPartRecord part)
		{
			foreach (Hediff hed in p.health.hediffSet.hediffs)
			{
				if ((hed.Part?.def == part.def) && hed.def.isBad && (hed.Severity >= 0.70f))
					return false;
			}
			return true;
		}

		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{
			foreach (BodyPartRecord part in base.GetPartsToApplyOn(p, r))
			{
				if (r.appliedOnFixedBodyParts.Contains(part.def) && !blocked(p))
					yield return part;
			}
		}

		public override void ApplyOnPawn(Pawn p, BodyPartRecord part, Pawn doer, List<Thing> ingredients, Bill bill)
		{
			var har = is_harvest(p, part);

			base.ApplyOnPawn(p, part, doer, ingredients, bill);

			if (har)
			{
				if (!p.Dead)
				{
					//Log.Message("alive harvest " + part);
					ThoughtUtility.GiveThoughtsForPawnOrganHarvested(p, doer);
				}
				else
				{
					//Log.Message("dead harvest " + part);
					ThoughtUtility.GiveThoughtsForPawnExecuted(p, doer, PawnExecutionKind.OrganHarvesting);
				}
			}
		}

		public override string GetLabelWhenUsedOn(Pawn p, BodyPartRecord part)
		{
			return recipe.label.CapitalizeFirst();
		}
	}
	/*
	public class Recipe_RemovePenis : Recipe_RemovePart
	{
		public override bool blocked(Pawn p)
		{
			return (Genital_Helper.genitals_blocked(p)
				|| !(Genital_Helper.has_penis(p)
					&& Genital_Helper.has_penis_infertile(p)
					&& Genital_Helper.has_ovipositorF(p)));
		}
	}

	public class Recipe_RemoveVagina : Recipe_RemovePart
	{
		public override bool blocked(Pawn p)
		{
			return (Genital_Helper.genitals_blocked(p)
				|| !Genital_Helper.has_vagina(p));
		}
	}

	public class Recipe_RemoveGenitals : Recipe_RemovePart
	{
		public override bool blocked(Pawn p)
		{
			return (Genital_Helper.genitals_blocked(p)
				|| !Genital_Helper.has_genitals(p));
		}
	}

	public class Recipe_RemoveBreasts : Recipe_RemovePart
	{
		public override bool blocked(Pawn p)
		{
			return (Genital_Helper.breasts_blocked(p)
				|| !Genital_Helper.has_breasts(p));
		}
	}

	public class Recipe_RemoveAnus : Recipe_RemovePart
	{
		public override bool blocked(Pawn p)
		{
			return (Genital_Helper.anus_blocked(p)
				|| !Genital_Helper.has_anus(p));
		}
	}
	*/
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;

namespace rjw
{
	public class Recipe_RemovePenis : Recipe_RemovePart
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{
			if (Genital_Helper.has_penis(p) || Genital_Helper.has_penis_infertile(p) || Genital_Helper.has_ovipositorF(p))
			{
				bool blocked = Genital_Helper.genitals_blocked(p) || xxx.is_slime(p);

				foreach (var part in p.health.hediffSet.GetNotMissingParts())
					if (r.appliedOnFixedBodyParts.Contains(part.def) && (!blocked))
						yield return part;
			}
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;

namespace rjw
{
	public class Recipe_RemoveUdder : Recipe_RemovePart
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{

			if (Genital_Helper.has_udder(p))
			{
				bool blocked = Genital_Helper.udder_blocked(p) || xxx.is_slime(p);//|| xxx.is_demon(p)

				foreach (BodyPartRecord part in p.health.hediffSet.GetNotMissingParts())
					if (r.appliedOnFixedBodyParts.Contains(part.def) && (!blocked))
						yield return part;
			}
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;

namespace rjw
{
	public class Recipe_RemoveVagina : Recipe_RemovePart
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{
			if (Genital_Helper.has_vagina(p) )
			{
				bool blocked = Genital_Helper.genitals_blocked(p) || xxx.is_slime(p);

				foreach (var part in p.health.hediffSet.GetNotMissingParts())
					if (r.appliedOnFixedBodyParts.Contains(part.def) && (!blocked))
						yield return part;
			}
		}
	}
}


code:
using System.Collections.Generic;
using RimWorld;
using Verse;

namespace rjw
{
	public class Recipe_MakeFuta : rjw_CORE_EXPOSED.Recipe_AddBodyPart
	{
		public override void ApplyOnPawn(Pawn pawn, BodyPartRecord part, Pawn billDoer, List<Thing> ingredients, Bill bill)
		{
			GenderHelper.Sex before = GenderHelper.GetSex(pawn);

			base.ApplyOnPawn(pawn, part, billDoer, ingredients, bill);

			GenderHelper.Sex after = GenderHelper.GetSex(pawn);

			GenderHelper.ChangeSex(pawn, before, after);
		}
	}

	//Female to futa
	public class Recipe_MakeFutaF : Recipe_MakeFuta
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{
			var parts = p.GetGenitalsList();

			bool blocked = Genital_Helper.genitals_blocked(p) || xxx.is_slime(p); //|| xxx.is_demon(p);
			bool has_vag = Genital_Helper.has_vagina(p, parts);
			bool has_cock = Genital_Helper.has_male_bits(p, parts);

			foreach (BodyPartRecord part in base.GetPartsToApplyOn(p, r))
				if (r.appliedOnFixedBodyParts.Contains(part.def) && !blocked && (has_vag && !has_cock))
					yield return part;
		}
	}

	//Male to futa
	public class Recipe_MakeFutaM : Recipe_MakeFuta
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{
			var parts = p.GetGenitalsList();

			bool blocked = Genital_Helper.genitals_blocked(p) || xxx.is_slime(p); //|| xxx.is_demon(p);
			bool has_vag = Genital_Helper.has_vagina(p, parts);
			bool has_cock = Genital_Helper.has_male_bits(p, parts);

			foreach (BodyPartRecord part in base.GetPartsToApplyOn(p, r))
				if (r.appliedOnFixedBodyParts.Contains(part.def) && !blocked && (!has_vag && has_cock))
					yield return part;
		}
	}

	//TODO: maybe merge with above to make single recipe, but meh for now just copy-paste recipes or some filter to disable multiparts if normal part doesn't exist yet

	//add multi parts
	public class Recipe_AddMultiPart : Recipe_MakeFuta
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{
			//don't add artificial - peg, hydraulics, bionics, archo, ovi
			if (r.addsHediff.addedPartProps?.solid ?? false)
				yield break;

			//don't add if artificial parts present
			if (p.health.hediffSet.hediffs.Any((Hediff hed) =>
				(hed.Part != null) &&
				r.appliedOnFixedBodyParts.Contains(hed.Part.def) &&
				(hed.def.addedPartProps?.solid ?? false)))
				yield break;

			var parts = p.GetGenitalsList();

			//don't add if no ovi
			//if (Genital_Helper.has_ovipositorF(p, parts) || Genital_Helper.has_ovipositorM(p, parts))
			//	yield break;

			//don't add if same part type not present yet
			if (!Genital_Helper.has_vagina(p, parts) && r.defName.ToLower().Contains("vagina"))
				yield break;
			if (!Genital_Helper.has_penis_fertile(p, parts) && r.defName.ToLower().Contains("penis"))
				yield break;

			//cant install parts when part blocked, on slimes, on demons
			bool blocked = (xxx.is_slime(p) //|| xxx.is_demon(p)
				|| (Genital_Helper.genitals_blocked(p) && r.appliedOnFixedBodyParts.Contains(xxx.genitalsDef))
				|| (Genital_Helper.anus_blocked(p) && r.appliedOnFixedBodyParts.Contains(xxx.anusDef))
				|| (Genital_Helper.breasts_blocked(p) && r.appliedOnFixedBodyParts.Contains(xxx.breastsDef)));

			foreach (BodyPartRecord part in base.GetPartsToApplyOn(p, r))
				if (r.appliedOnFixedBodyParts.Contains(part.def) && !blocked)
					yield return part;
		}
	}

	public class Recipe_AddSinglePart : Recipe_MakeFuta
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{
			//cant install parts when part blocked, on slimes, or when already has one
			bool blocked = xxx.is_slime(p) || p.health.hediffSet.HasHediff(r.addsHediff);

			foreach (BodyPartRecord part in base.GetPartsToApplyOn(p, r))
				if (r.appliedOnFixedBodyParts.Contains(part.def) && !blocked)
					yield return part;
		}
	}

	public class Recipe_RemoveSinglePart : Recipe_MakeFuta
	{
		public override IEnumerable<BodyPartRecord> GetPartsToApplyOn(Pawn p, RecipeDef r)
		{
			//cant install parts when part blocked, on slimes, or when already has one
			bool blocked = xxx.is_slime(p) || !p.health.hediffSet.HasHediff(r.removesHediff);

			foreach (BodyPartRecord part in base.GetPartsToApplyOn(p, r))
				if (r.appliedOnFixedBodyParts.Contains(part.def) && !blocked)
					yield return part;
		}
	}
}


code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;

namespace rjw
{
	public class PawnRelationWorker_Child_Beast : PawnRelationWorker_Child
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isChildOf(other, me);
		}
	}

	public class PawnRelationWorker_Sibling_Beast : PawnRelationWorker_Sibling
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isSiblingOf(other, me);
		}
	}
	public class PawnRelationWorker_HalfSibling_Beast : PawnRelationWorker_HalfSibling
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isHalfSiblingOf(other, me);
		}
	}
	public class PawnRelationWorker_Grandparent_Beast : PawnRelationWorker_Grandparent
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isGrandchildOf(me, other);
		}
	}
	public class PawnRelationWorker_Grandchild_Beast : PawnRelationWorker_Grandchild
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isGrandparentOf(me, other);  //if other isGrandchildOf of me, me is their grandparent
		}
	}
	public class PawnRelationWorker_NephewOrNiece_Beast : PawnRelationWorker_NephewOrNiece
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isUncleOrAuntOf(me, other);
		}
	}
	public class PawnRelationWorker_UncleOrAunt_Beast : PawnRelationWorker_UncleOrAunt
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isNephewOrNieceOf(me, other);
		}
	}

	public class PawnRelationWorker_Cousin_Beast : PawnRelationWorker_Cousin
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isCousinOf(me, other);
		}
	}

	public class PawnRelationWorker_GreatGrandparent_Beast : PawnRelationWorker_GreatGrandparent
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isGreatGrandChildOf(me, other);
		}
	}

	public class PawnRelationWorker_GreatGrandchild_Beast : PawnRelationWorker_GreatGrandchild
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isGreatGrandparentOf(me, other);
		}
	}

	public class PawnRelationWorker_GranduncleOrGrandaunt_Beast : PawnRelationWorker_GranduncleOrGrandaunt
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isGrandnephewOrGrandnieceOf(me, other);
		}
	}

	public class PawnRelationWorker_GrandnephewOrGrandniece_Beast : PawnRelationWorker_GrandnephewOrGrandniece
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isGreatUncleOrAuntOf(me, other);
		}
	}

	public class PawnRelationWorker_CousinOnceRemoved_Beast : PawnRelationWorker_CousinOnceRemoved
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isCousinOnceRemovedOf(me, other);
		}
	}

	public class PawnRelationWorker_SecondCousin_Beast : PawnRelationWorker_SecondCousin
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isSecondCousinOf(me, other);
		}
	}
	/*
	public class PawnRelationWorker_Kin_Beast : PawnRelationWorker_Kin
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (!xxx.is_animal(other) || me == other)
			{
				return false;
			}

			if (base.InRelation(me, other) == true)
			{
				return true;
			}
			return false;
		}
	}
	*/
}


code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;

namespace rjw
{
	public class PawnRelationWorker_Child_Humanlike : PawnRelationWorker_Child
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			if (base.InRelation(me, other) == true)
			{
				return true;
			}
			return false;
		}
	}

	public class PawnRelationWorker_Sibling_Humanlike : PawnRelationWorker_Sibling
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			if (base.InRelation(me, other) == true)
			{
				return true;
			}
			return false;
		}
	}
	public class PawnRelationWorker_HalfSibling_Humanlike : PawnRelationWorker_HalfSibling
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isHalfSiblingOf(other, me);
		}
	}
	public class PawnRelationWorker_Grandparent_Humanlike : PawnRelationWorker_Grandparent
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isGrandchildOf(me, other);
		}
	}
	public class PawnRelationWorker_Grandchild_Humanlike : PawnRelationWorker_Grandchild
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isGrandparentOf(me, other);
		}
	}
	public class PawnRelationWorker_NephewOrNiece_Humanlike : PawnRelationWorker_NephewOrNiece
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isUncleOrAuntOf(me, other);
		}
	}
	public class PawnRelationWorker_UncleOrAunt_Humanlike : PawnRelationWorker_UncleOrAunt
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isNephewOrNieceOf(me, other);
		}
	}

	public class PawnRelationWorker_Cousin_Humanlike : PawnRelationWorker_Cousin
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isCousinOf(me, other);
		}
	}

	public class PawnRelationWorker_GreatGrandparent_Humanlike : PawnRelationWorker_GreatGrandparent
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isGreatGrandChildOf(me, other);
		}
	}

	public class PawnRelationWorker_GreatGrandchild_Humanlike : PawnRelationWorker_GreatGrandchild
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isGreatGrandparentOf(me, other);
		}
	}

	public class PawnRelationWorker_GranduncleOrGrandaunt_Humanlike : PawnRelationWorker_GranduncleOrGrandaunt
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isGrandnephewOrGrandnieceOf(me, other);
		}
	}

	public class PawnRelationWorker_GrandnephewOrGrandniece_Humanlike : PawnRelationWorker_GrandnephewOrGrandniece
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isGreatUncleOrAuntOf(me, other);
		}
	}

	public class PawnRelationWorker_CousinOnceRemoved_Humanlike : PawnRelationWorker_CousinOnceRemoved
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isCousinOnceRemovedOf(me, other);
		}
	}

	public class PawnRelationWorker_SecondCousin_Humanlike : PawnRelationWorker_SecondCousin
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			return RelationChecker.isSecondCousinOf(me, other);
		}
	}

	public class PawnRelationWorker_Kin_Humanlike : PawnRelationWorker_Kin
	{
		public override bool InRelation(Pawn me, Pawn other)
		{
			if (xxx.is_animal(other) || me == other)
			{
				return false;
			}

			if (base.InRelation(me, other) == true)
			{
				return true;
			}
			return false;
		}
	}
}


code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RimWorld;
using Verse;

namespace rjw
{
	/// <summary>
	/// Checks for relations, workaround for relation checks that rely on other relation checks, since the vanilla inRelation checks have been prefixed.
	///
	/// Return true if first pawn is specified relation of the second pawn
	///
	///  If "me" isRelationOf "other" return true
	/// </summary>
	///
	public static class RelationChecker
	{
		public static bool isChildOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}
			if (me.GetMother() != other)
			{
				return me.GetFather() == other;
			}
			//else "other" is mother
			return true;
		}

		public static bool isSiblingOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}
			if (me.GetMother() != null && me.GetFather() != null && me.GetMother() == other.GetMother() && me.GetFather() == other.GetFather())
			{
				return true;
			}
			return false;
		}

		public static bool isHalfSiblingOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}
			if (isSiblingOf(me, other))
			{
				return false;
			}
			return ((me.GetMother() != null && me.GetMother() == other.GetMother()) || (me.GetFather() != null && me.GetFather() == other.GetFather()));
		}

		public static bool isAnySiblingOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}
			if ((me.GetMother() != null && me.GetMother() == other.GetMother()) || (me.GetFather() != null && me.GetFather() == other.GetFather()))
			{
				return true;
			}
			return false;
		}

		public static bool isGrandchildOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}
			if ((me.GetMother() != null && isChildOf(me.GetMother(), other)) || (me.GetFather() != null && isChildOf(me.GetFather(), other)))
			{
				return true;
			}
			return false;
		}

		public static bool isGrandparentOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}
			if (isGrandchildOf(other, me))
			{
				return true;
			}
			return false;
		}

		public static bool isNephewOrNieceOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}
			if ((me.GetMother() != null && (isAnySiblingOf(other, me.GetMother()))) || (me.GetFather() != null && (isAnySiblingOf(other, me.GetFather()))))
			{
				return true;
			}
			return false;
		}

		public static bool isUncleOrAuntOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}
			if (isNephewOrNieceOf(other, me))
			{
				return true;
			}
			return false;
		}

		public static bool isCousinOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}

			if ((other.GetMother() != null && isNephewOrNieceOf(me, other.GetMother())) || (other.GetFather() != null && isNephewOrNieceOf(me, other.GetFather())))
			{
				return true;
			}
			return false;
		}

		public static bool isGreatGrandparentOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}

			return isGreatGrandChildOf(other, me);
		}

		public static bool isGreatGrandChildOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}

			if ((me.GetMother() != null && isGrandchildOf(me.GetMother(), other)) || (me.GetFather() != null && isGrandchildOf(me.GetFather(), other)))
			{
				return true;
			}
			return false;
		}

		public static bool isGreatUncleOrAuntOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}

			return isGrandnephewOrGrandnieceOf(other, me);
		}

		public static bool isGrandnephewOrGrandnieceOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}

			if ((me.GetMother() != null && isUncleOrAuntOf(other, me.GetMother())) || (me.GetFather() != null && isUncleOrAuntOf(other, me.GetFather())))
			{
				return true;
			}
			return false;
		}

		public static bool isCousinOnceRemovedOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}
			if ((other.GetMother() != null && isCousinOf(me, other.GetMother())) || (other.GetFather() != null && isCousinOf(me, other.GetFather())))
			{
				return true;
			}
			if ((other.GetMother() != null && isGrandnephewOrGrandnieceOf(me, other.GetMother())) || (other.GetFather() != null && isGrandnephewOrGrandnieceOf(me, other.GetFather())))
			{
				return true;
			}
			return false;
		}

		public static bool isSecondCousinOf(Pawn me, Pawn other)
		{
			if (me == null || me == other)
			{
				return false;
			}
			PawnRelationWorker worker = PawnRelationDefOf.GranduncleOrGrandaunt.Worker;
			Pawn mother = other.GetMother();
			if (mother != null && ((mother.GetMother() != null && isGrandnephewOrGrandnieceOf(me, mother.GetMother())) || (mother.GetFather() != null && isGrandnephewOrGrandnieceOf(me, mother.GetFather()))))
			{
				return true;
			}
			Pawn father = other.GetFather();
			if (father != null && ((father.GetMother() != null && isGrandnephewOrGrandnieceOf(me, father.GetMother())) || (father.GetFather() != null && isGrandnephewOrGrandnieceOf(me, father.GetFather()))))
			{
				return true;
			}
			return false;
		}
	}
}


code:
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{22F82FFF-8BD4-4CEE-9F22-C7DA71281E72}</ProjectGuid>
    <OutputType>Library</OutputType>
    <NoStandardLibraries>false</NoStandardLibraries>
    <AssemblyName>RJW</AssemblyName>
    <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <TargetFrameworkProfile />
    <ShouldCreateLogs>True</ShouldCreateLogs>
    <AdvancedSettingsExpanded>True</AdvancedSettingsExpanded>
    <UpdateAssemblyVersion>True</UpdateAssemblyVersion>
    <UpdateAssemblyFileVersion>True</UpdateAssemblyFileVersion>
    <UpdateAssemblyInfoVersion>True</UpdateAssemblyInfoVersion>
    <AssemblyVersionSettings>None.None.IncrementOnDemand.Increment</AssemblyVersionSettings>
    <AssemblyFileVersionSettings>None.None.IncrementOnDemand.None</AssemblyFileVersionSettings>
    <AssemblyInfoVersionSettings>None.None.IncrementOnDemand.None</AssemblyInfoVersionSettings>
    <PrimaryVersionType>AssemblyVersionAttribute</PrimaryVersionType>
    <AssemblyVersion>1.6.0.493</AssemblyVersion>
    <LangVersion>10</LangVersion>
    <NuGetPackageImportStamp>
    </NuGetPackageImportStamp>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>..\Assemblies\</OutputPath>
    <DefineConstants>TRACE;DEBUG</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <FileAlignment>4096</FileAlignment>
    <Prefer32Bit>false</Prefer32Bit>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>none</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>..\Assemblies\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <LangVersion>latest</LangVersion>
    <Prefer32Bit>false</Prefer32Bit>
  </PropertyGroup>
  <!-- Set the `BENCHMARK` environment variable to "1" to enable benchmarking. -->
  <PropertyGroup Condition="'$(BENCHMARK)' == '1'">
    <DefineConstants>$(DefineConstants);BENCHMARK</DefineConstants>
  </PropertyGroup>
  <PropertyGroup>
    <RootNamespace>rjw</RootNamespace>
  </PropertyGroup>
  <Choose>
    <!-- Mod-folder Relative -->
    <When Condition="Exists('..\..\..\..\Mods')">
      <PropertyGroup>
        <RWPath>..\..\..\..</RWPath>
      </PropertyGroup>
    </When>
    <!-- Windows x86 -->
    <When Condition="Exists('C:\Program Files (x86)\Steam\steamapps\common\RimWorld')">
      <PropertyGroup>
        <RWPath>C:\Program Files (x86)\Steam\steamapps\common\RimWorld</RWPath>
      </PropertyGroup>
    </When>
    <!-- Windows x64 -->
    <When Condition="Exists('C:\Program Files\Steam\steamapps\common\RimWorld')">
      <PropertyGroup>
        <RWPath>C:\Program Files\Steam\steamapps\common\RimWorld</RWPath>
      </PropertyGroup>
    </When>
    <!-- Linux -->
    <When Condition="Exists('$(HOME)\.steam\steam')">
      <PropertyGroup>
        <RWPath>$(HOME)\.steam\steam\steamapps\common\RimWorld</RWPath>
      </PropertyGroup>
    </When>
    <!-- MacOS -->
    <When Condition="Exists('$(HOME)\Library\Application Support\Steam')">
      <PropertyGroup>
        <RWPath>$(HOME)\Library\Application Support\Steam\steamapps\common\RimWorld</RWPath>
      </PropertyGroup>
    </When>
    <!-- Fallback option: define the RIMWORLD environment variable, pointing to RimWorld's install folder -->
    <When Condition="Exists('$(RIMWORLD)')">
      <PropertyGroup>
        <RWPath>$(RIMWORLD)</RWPath>
      </PropertyGroup>
    </When>
  </Choose>
  <PropertyGroup>
    <ReferencePath>
      $(RWPath)\RimWorldWin_Data\Managed;
      $(RWPath)\RimWorldWin64_Data\Managed;
      $(RWPath)\RimWorldLinux_Data\Managed;
      $(RWPath)\RimWorldMac.app\Contents\Resources\Data\Managed;
      $(ReferencePath)
    </ReferencePath>
  </PropertyGroup>
  <!-- Prevents copying DLLs on build. -->
  <!-- If you do still get copies, wipe out the `obj` folder and re-run the `restore` task. -->
  <!-- You can do this on the command line with: `msbuild /t:restore` -->
  <ItemDefinitionGroup>
    <Reference><Private>False</Private></Reference>
    <ProjectReference><Private>False</Private></ProjectReference>
    <PackageReference><ExcludeAssets>runtime</ExcludeAssets></PackageReference>
  </ItemDefinitionGroup>
  <ItemGroup>
    <Compile Include=".\**\*.cs" />
    <!-- Ignore files in `obj`; they'll be included else where, as needed. -->
    <Compile Remove=".\obj\**\*.cs" />
    <!-- Things in trash are in trash for a reason, I presume.  Maybe delete them? -->
    <Compile Remove=".\0trash\**\*.cs" />
    <!-- Exclude files not currently in use here. -->
    <!-- Better yet, clean up your garbage.  If we need it again, Git keeps a copy for us. -->
    <Compile Remove=".\Common\ExpandedPawnCharacterCard.cs" />
    <Compile Remove=".\Common\Verb_Fuck.cs" />
    <Compile Remove=".\Common\CORE_EXPOSED\HealthCardUtility.cs" />
    <Compile Remove=".\JobDrivers\JobRJWSex.cs" />
    <Compile Remove=".\JobDrivers\JobDriver_AbortMechPregnancy.cs" />
    <Compile Remove=".\RJWTab\PawnColumnWorker_Master.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_BestialityForFemale.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_Quickie.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_ViolateCorpse.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_BestialityForMale.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_Masturbate_Quick.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_RapeEnemy.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_BestialityF.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_Rape.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_Sex.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_CleanSexStuff.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_RapeCP.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_Masturbate_Bed.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_BestialityM.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_Solicit.cs" />
    <Compile Remove=".\WorkGivers\WorkGiver_Masturbate_Chair.cs" />
    <Compile Remove=".\Harmony\patch_PartIsMissing.cs" />
    <Compile Remove=".\Harmony\d.cs" />
    <Compile Remove=".\Harmony\patch_need.cs" />
    <Compile Remove=".\Harmony\test.cs" />
    <Compile Remove=".\Harmony\patch_CnPBnC.cs" />
    <Compile Remove=".\Harmony\Building_Bed_Patch.cs" />
    <Compile Remove=".\Harmony\CnPcompatibility.cs" />
    <Compile Remove=".\Harmony\patch_AnimalTab.cs" />
    <Compile Remove=".\DefOf\RJW_RecipeDefOf.cs" />
    <Compile Remove=".\DefOf\JobDriver_AdjustParts.cs" />
    <Compile Remove=".\DefOf\JobDefOf.cs" />
    <Compile Remove=".\Modules\Bondage\Comps\CompCryptoStamped.cs" />
    <Compile Remove=".\Modules\Genitals\Enums\LewdablePartKind.cs" />
    <Compile Remove=".\Recipes\Install_Part\Recipe_InstallGenitals.cs" />
    <Compile Remove=".\Recipes\Install_Part\Recipe_InstallBreasts.cs" />
    <Compile Remove=".\Recipes\Install_Part\Recipe_InstallAnus.cs" />
    <Compile Remove=".\Recipes\Recipe_ShrinkBreasts.cs" />
    <Compile Remove=".\Recipes\Recipe_GrowBreasts.cs" />
    <Compile Remove=".\Recipes\Remove_Part\Recipe_RemovePenis.cs" />
    <Compile Remove=".\Recipes\Remove_Part\Recipe_RemoveVagina.cs" />
  </ItemGroup>
  <ItemGroup>
    <Reference Include="0MultiplayerAPI, Version=0.3.0.0, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>0trash\packages\RimWorld.MultiplayerAPI.0.3.0\lib\net472\0MultiplayerAPI.dll</HintPath>
    </Reference>
    <Reference Include="Psychology">
      <HintPath>0trash\modpackages\Psychology.2018-11-18\Assemblies\Psychology.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="RimWorldChildren">
      <HintPath>0trash\modpackages\ChildrenAndPregnancy.0.4e\Assemblies\RimWorldChildren.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="SyrTraits">
      <HintPath>0trash\modpackages\SYR.Individuality.1.1.7\1.1\Assemblies\SyrTraits.dll</HintPath>
      <Private>False</Private>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Runtime.InteropServices.RuntimeInformation" />
    <!-- RimWorld references -->
    <Reference Include="Assembly-CSharp" />
    <Reference Include="ISharpZipLib" />
    <Reference Include="Unity.TextMeshPro" />
    <Reference Include="UnityEngine.AIModule" />
    <Reference Include="UnityEngine.AccessibilityModule" />
    <Reference Include="UnityEngine.AndroidJNIModule" />
    <Reference Include="UnityEngine.AnimationModule" />
    <Reference Include="UnityEngine.AssetBundleModule" />
    <Reference Include="UnityEngine.AudioModule" />
    <Reference Include="UnityEngine.ClothModule" />
    <Reference Include="UnityEngine.ClusterInputModule" />
    <Reference Include="UnityEngine.ClusterRendererModule" />
    <Reference Include="UnityEngine.CoreModule" />
    <Reference Include="UnityEngine.CrashReportingModule" />
    <Reference Include="UnityEngine.DSPGraphModule" />
    <Reference Include="UnityEngine.DirectorModule" />
    <Reference Include="UnityEngine.GameCenterModule" />
    <Reference Include="UnityEngine.GridModule" />
    <Reference Include="UnityEngine.HotReloadModule" />
    <Reference Include="UnityEngine.IMGUIModule" />
    <Reference Include="UnityEngine.ImageConversionModule" />
    <Reference Include="UnityEngine.InputLegacyModule" />
    <Reference Include="UnityEngine.InputModule" />
    <Reference Include="UnityEngine.JSONSerializeModule" />
    <Reference Include="UnityEngine.LocalizationModule" />
    <Reference Include="UnityEngine.ParticleSystemModule" />
    <Reference Include="UnityEngine.PerformanceReportingModule" />
    <Reference Include="UnityEngine.Physics2DModule" />
    <Reference Include="UnityEngine.PhysicsModule" />
    <Reference Include="UnityEngine.ProfilerModule" />
    <Reference Include="UnityEngine.ScreenCaptureModule" />
    <Reference Include="UnityEngine.SharedInternalsModule" />
    <Reference Include="UnityEngine.SpriteMaskModule" />
    <Reference Include="UnityEngine.SpriteShapeModule" />
    <Reference Include="UnityEngine.StreamingModule" />
    <Reference Include="UnityEngine.SubstanceModule" />
    <Reference Include="UnityEngine.TLSModule" />
    <Reference Include="UnityEngine.TerrainModule" />
    <Reference Include="UnityEngine.TerrainPhysicsModule" />
    <Reference Include="UnityEngine.TextCoreModule" />
    <Reference Include="UnityEngine.TextRenderingModule" />
    <Reference Include="UnityEngine.TilemapModule" />
    <Reference Include="UnityEngine.UI" />
    <Reference Include="UnityEngine.UIElementsModule" />
    <Reference Include="UnityEngine.UIModule" />
    <Reference Include="UnityEngine.UNETModule" />
    <Reference Include="UnityEngine.UmbraModule" />
    <Reference Include="UnityEngine.UnityAnalyticsModule" />
    <Reference Include="UnityEngine.UnityConnectModule" />
    <Reference Include="UnityEngine.UnityTestProtocolModule" />
    <Reference Include="UnityEngine.UnityWebRequestAssetBundleModule" />
    <Reference Include="UnityEngine.UnityWebRequestAudioModule" />
    <Reference Include="UnityEngine.UnityWebRequestModule" />
    <Reference Include="UnityEngine.UnityWebRequestTextureModule" />
    <Reference Include="UnityEngine.UnityWebRequestWWWModule" />
    <Reference Include="UnityEngine.VFXModule" />
    <Reference Include="UnityEngine.VRModule" />
    <Reference Include="UnityEngine.VehiclesModule" />
    <Reference Include="UnityEngine.VideoModule" />
    <Reference Include="UnityEngine.WindModule" />
    <Reference Include="UnityEngine.XRModule" />
    <Reference Include="UnityEngine" />
    <!-- The following are not available on all platforms, IE Linux. -->
      <!-- <Reference Include="UnityEngine.ARModule" /> -->
      <!-- <Reference Include="NAudio" /> -->
      <!-- <Reference Include="NVorbis" /> -->
    <!-- end RimWorld references -->
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Lib.Harmony" Version="2.2.2" />
    <PackageReference Include="UnlimitedHugs.Rimworld.HugsLib" Version="10.0.1" />
  </ItemGroup>
  <ItemGroup />
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <ProjectExtensions>
    <VisualStudio AllowExistingFolder="true" />
  </ProjectExtensions>
</Project>


code:
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2024
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RimJobWorld.Main", "RimJobWorld.Main.csproj", "{22F82FFF-8BD4-4CEE-9F22-C7DA71281E72}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Release|Any CPU = Release|Any CPU
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{22F82FFF-8BD4-4CEE-9F22-C7DA71281E72}.Debug|Any CPU.ActiveCfg = Release|Any CPU
		{22F82FFF-8BD4-4CEE-9F22-C7DA71281E72}.Debug|Any CPU.Build.0 = Release|Any CPU
		{22F82FFF-8BD4-4CEE-9F22-C7DA71281E72}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{22F82FFF-8BD4-4CEE-9F22-C7DA71281E72}.Release|Any CPU.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
		SolutionGuid = {16BA61E5-4C97-4E73-926D-6718DE8E4776}
	EndGlobalSection
EndGlobal


code:
using System;
using UnityEngine;
using Verse;
using System.Collections.Generic;

namespace rjw
{
	public class RJWDebugSettings : ModSettings
	{
		public static void DoWindowContents(Rect inRect)
		{
			Listing_Standard listingStandard = new Listing_Standard();
			listingStandard.ColumnWidth = inRect.width / 2.05f;
			listingStandard.Begin(inRect);
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("submit_button_enabled".Translate(), ref RJWSettings.submit_button_enabled, "submit_button_enabled_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("RJW_designation_box".Translate(), ref RJWSettings.show_RJW_designation_box, "RJW_designation_box_desc".Translate());
			listingStandard.Gap(5f);
			if (listingStandard.ButtonText("Rjw Parts " + RJWSettings.ShowRjwParts))
			{
				Find.WindowStack.Add(new FloatMenu(new List<FloatMenuOption>()
					{
					  new FloatMenuOption("Extended", (() => RJWSettings.ShowRjwParts = RJWSettings.ShowParts.Extended)),
					  new FloatMenuOption("Show", (() => RJWSettings.ShowRjwParts = RJWSettings.ShowParts.Show)),
					  //new FloatMenuOption("Known".Translate(), (() => RJWSettings.ShowRjwParts = RJWSettings.ShowParts.Known)),
					  new FloatMenuOption("Hide", (() => RJWSettings.ShowRjwParts = RJWSettings.ShowParts.Hide))
					}));
			}
			listingStandard.Gap(30f);

			GUI.contentColor = Color.yellow;
			listingStandard.Label("YOU PATHETIC CHEATER ");
			GUI.contentColor = Color.white;
			listingStandard.CheckboxLabeled("override_RJW_designation_checks_name".Translate(), ref RJWSettings.override_RJW_designation_checks, "override_RJW_designation_checks_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("override_control".Translate(), ref RJWSettings.override_control, "override_control_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("AddTrait_Rapist".Translate(), ref RJWSettings.AddTrait_Rapist, "AddTrait_Rapist_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("AddTrait_Masocist".Translate(), ref RJWSettings.AddTrait_Masocist, "AddTrait_Masocist_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("AddTrait_Nymphomaniac".Translate(), ref RJWSettings.AddTrait_Nymphomaniac, "AddTrait_Nymphomaniac_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("AddTrait_Necrophiliac".Translate(), ref RJWSettings.AddTrait_Necrophiliac, "AddTrait_Necrophiliac_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("AddTrait_Nerves".Translate(), ref RJWSettings.AddTrait_Nerves, "AddTrait_Nerves_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("AddTrait_Zoophiliac".Translate(), ref RJWSettings.AddTrait_Zoophiliac, "AddTrait_Zoophiliac_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("AddTrait_FootSlut".Translate(), ref RJWSettings.AddTrait_FootSlut, "AddTrait_FootSlut_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("AddTrait_CumSlut".Translate(), ref RJWSettings.AddTrait_CumSlut, "AddTrait_CumSlut_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("AddTrait_ButtSlut".Translate(), ref RJWSettings.AddTrait_ButtSlut, "AddTrait_ButtSlut_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("Allow_RMB_DeepTalk".Translate(), ref RJWSettings.Allow_RMB_DeepTalk, "Allow_RMB_DeepTalk_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("Disable_bestiality_pregnancy_relations".Translate(), ref RJWSettings.Disable_bestiality_pregnancy_relations, "Disable_bestiality_pregnancy_relations_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("Disable_MeditationFocusDrain".Translate(), ref RJWSettings.Disable_MeditationFocusDrain, "Disable_MeditationFocusDrain_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("Disable_RecreationDrain".Translate(), ref RJWSettings.Disable_RecreationDrain, "Disable_RecreationDrain_desc".Translate());
			listingStandard.Gap(5f);

			listingStandard.NewColumn();
			listingStandard.Gap(4f);
			GUI.contentColor = Color.yellow;
			listingStandard.CheckboxLabeled("designated_freewill".Translate(), ref RJWSettings.designated_freewill, "designated_freewill_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("override_lovin".Translate(), ref RJWSettings.override_lovin, "override_lovin_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("override_matin".Translate(), ref RJWSettings.override_matin, "override_matin_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("matin_crossbreed".Translate(), ref RJWSettings.matin_crossbreed, "matin_crossbreed_desc".Translate());
			listingStandard.Gap(5f);
			listingStandard.CheckboxLabeled("DevMode_name".Translate(), ref RJWSettings.DevMode, "DevMode_desc".Translate());
			listingStandard.Gap(5f);
			if (RJWSettings.DevMode)
			{
				listingStandard.CheckboxLabeled("WildMode_name".Translate(), ref RJWSettings.WildMode, "WildMode_desc".Translate());
				listingStandard.Gap(5f);
				listingStandard.CheckboxLabeled("HippieMode_name".Translate(), ref RJWSettings.HippieMode, "HippieMode_desc".Translate());
				listingStandard.Gap(5f);
				listingStandard.CheckboxLabeled("DebugLogJoinInBed".Translate(), ref RJWSettings.DebugLogJoinInBed, "DebugLogJoinInBed_desc".Translate());
				listingStandard.Gap(5f);
				listingStandard.CheckboxLabeled("DebugRape".Translate(), ref RJWSettings.DebugRape, "DebugRape_desc".Translate());
				listingStandard.Gap(5f);
				listingStandard.CheckboxLabeled("DebugInteraction".Translate(), ref RJWSettings.DebugInteraction, "DebugInteraction_desc".Translate());
				listingStandard.Gap(5f);
				listingStandard.CheckboxLabeled("DebugNymph".Translate(), ref RJWSettings.DebugNymph, "DebugNymph_desc".Translate());
				listingStandard.Gap(5f);
			}
			else
			{
				RJWSettings.DebugLogJoinInBed = false;
				RJWSettings.DebugRape = false;
			}
			listingStandard.CheckboxLabeled("GenderlessAsFuta_name".Translate(), ref RJWSettings.GenderlessAsFuta, "GenderlessAsFuta_desc".Translate());
			listingStandard.Gap(5f);
			GUI.contentColor = Color.white;

			listingStandard.Gap(30f);
			listingStandard.Label("maxDistanceCellsCasual_name".Translate() + ": " + (RJWSettings.maxDistanceCellsCasual), -1f, "maxDistanceCellsCasual_desc".Translate());
			RJWSettings.maxDistanceCellsCasual = listingStandard.Slider((int)RJWSettings.maxDistanceCellsCasual, 0, 10000);
			listingStandard.Label("maxDistanceCellsRape_name".Translate() + ": " + (RJWSettings.maxDistanceCellsRape), -1f, "maxDistanceCellsRape_desc".Translate());
			RJWSettings.maxDistanceCellsRape = listingStandard.Slider((int)RJWSettings.maxDistanceCellsRape, 0, 10000);
			listingStandard.Label("maxDistancePathCost_name".Translate() + ": " + (RJWSettings.maxDistancePathCost), -1f, "maxDistancePathCost_desc".Translate());
			RJWSettings.maxDistancePathCost = listingStandard.Slider((int)RJWSettings.maxDistancePathCost, 0, 5000);

			listingStandard.End();
		}

		public override void ExposeData()
		{
			base.ExposeData();
			Scribe_Values.Look(ref RJWSettings.submit_button_enabled, "submit_button_enabled", RJWSettings.submit_button_enabled, true);
			Scribe_Values.Look(ref RJWSettings.show_RJW_designation_box, "show_RJW_designation_box", RJWSettings.show_RJW_designation_box, true);
			Scribe_Values.Look(ref RJWSettings.ShowRjwParts, "ShowRjwParts", RJWSettings.ShowRjwParts, true);
			Scribe_Values.Look(ref RJWSettings.maxDistanceCellsCasual, "maxDistanceCellsCasual", RJWSettings.maxDistanceCellsCasual, true);
			Scribe_Values.Look(ref RJWSettings.maxDistanceCellsRape, "maxDistanceCellsRape", RJWSettings.maxDistanceCellsRape, true);
			Scribe_Values.Look(ref RJWSettings.maxDistancePathCost, "maxDistancePathCost", RJWSettings.maxDistancePathCost, true);

			Scribe_Values.Look(ref RJWSettings.AddTrait_Rapist, "AddTrait_Rapist", RJWSettings.AddTrait_Rapist, true);
			Scribe_Values.Look(ref RJWSettings.AddTrait_Masocist, "AddTrait_Masocist", RJWSettings.AddTrait_Masocist, true);
			Scribe_Values.Look(ref RJWSettings.AddTrait_Nymphomaniac, "AddTrait_Nymphomaniac", RJWSettings.AddTrait_Nymphomaniac, true);
			Scribe_Values.Look(ref RJWSettings.AddTrait_Necrophiliac, "AddTrait_Necrophiliac", RJWSettings.AddTrait_Necrophiliac, true);
			Scribe_Values.Look(ref RJWSettings.AddTrait_Nerves, "AddTrait_Nerves", RJWSettings.AddTrait_Nerves, true);
			Scribe_Values.Look(ref RJWSettings.AddTrait_Zoophiliac, "AddTrait_Zoophiliac", RJWSettings.AddTrait_Zoophiliac, true);
			Scribe_Values.Look(ref RJWSettings.AddTrait_FootSlut, "AddTrait_FootSlut", RJWSettings.AddTrait_FootSlut, true);
			Scribe_Values.Look(ref RJWSettings.AddTrait_CumSlut, "AddTrait_CumSlut", RJWSettings.AddTrait_CumSlut, true);
			Scribe_Values.Look(ref RJWSettings.AddTrait_ButtSlut, "AddTrait_ButtSlut", RJWSettings.AddTrait_ButtSlut, true);

			Scribe_Values.Look(ref RJWSettings.Allow_RMB_DeepTalk, "Allow_RMB_DeepTalk", RJWSettings.Allow_RMB_DeepTalk, true);
			Scribe_Values.Look(ref RJWSettings.Allow_RMB_DeepTalk, "Allow_RMB_DeepTalk", RJWSettings.Allow_RMB_DeepTalk, true);
			Scribe_Values.Look(ref RJWSettings.Disable_bestiality_pregnancy_relations, "Disable_bestiality_pregnancy_relations", RJWSettings.Disable_bestiality_pregnancy_relations, true);
			Scribe_Values.Look(ref RJWSettings.Disable_MeditationFocusDrain, "Disable_MeditationFocusDrain", RJWSettings.Disable_MeditationFocusDrain, true);
			Scribe_Values.Look(ref RJWSettings.Disable_RecreationDrain, "Disable_RecreationDrain", RJWSettings.Disable_RecreationDrain, true);

			Scribe_Values.Look(ref RJWSettings.GenderlessAsFuta, "GenderlessAsFuta", RJWSettings.GenderlessAsFuta, true);
			Scribe_Values.Look(ref RJWSettings.override_lovin, "override_lovin", RJWSettings.override_lovin, true);
			Scribe_Values.Look(ref RJWSettings.override_matin, "override_matin", RJWSettings.override_matin, true);
			Scribe_Values.Look(ref RJWSettings.matin_crossbreed, "matin_crossbreed", RJWSettings.matin_crossbreed, true);
			Scribe_Values.Look(ref RJWSettings.WildMode, "Wildmode", RJWSettings.WildMode, true);
			Scribe_Values.Look(ref RJWSettings.HippieMode, "Hippiemode", RJWSettings.HippieMode, true);
			Scribe_Values.Look(ref RJWSettings.override_RJW_designation_checks, "override_RJW_designation_checks", RJWSettings.override_RJW_designation_checks, true);
			Scribe_Values.Look(ref RJWSettings.override_control, "override_control", RJWSettings.override_control, true);
			Scribe_Values.Look(ref RJWSettings.DevMode, "DevMode", RJWSettings.DevMode, true);
			Scribe_Values.Look(ref RJWSettings.DebugLogJoinInBed, "DebugLogJoinInBed", RJWSettings.DebugLogJoinInBed, true);
			Scribe_Values.Look(ref RJWSettings.DebugRape, "DebugRape", RJWSettings.DebugRape, true);
			Scribe_Values.Look(ref RJWSettings.DebugInteraction, "DebugInteraction", RJWSettings.DebugInteraction, true);
			Scribe_Values.Look(ref RJWSettings.DebugNymph, "DebugNymph", RJWSettings.DebugNymph, true);
		}
	}
}