diff --git a/1.4/Defs/RaceSupport/_base.xml b/1.4/Defs/RaceSupport/_base.xml
index a9db357cd9e179af0398286d518a2d875090f267..bf19d4534728dfeb92da7c902efe4d3a7c17fa2a 100644
--- a/1.4/Defs/RaceSupport/_base.xml
+++ b/1.4/Defs/RaceSupport/_base.xml
@@ -12,6 +12,7 @@
 		<pawnKindNames>
 		</pawnKindNames>
 		
+		<!-- TODO? rewrite old lists-->
 		<!-- A empty list means default part adding sequence will run. -->
 		<!-- Do weird shit here ... like dicktails. -->
 		<!-- Chance to add -->
@@ -29,7 +30,7 @@
 				</bodyParts>
 			</li>
 		</partAdders>
-		 -->
+		-->
 
 		<!-- A missing list means to use the regular part picking code for that sex part type. -->
 		<!-- A empty list means no part will be added. -->
@@ -187,6 +188,8 @@
 			<li>1.0</li>
 		</chancemaleGenitals>
 
+		
+		<!-- mostly for quirks -->
 		<tags>
 			<!--
 			<li>Chitin</li>
@@ -221,6 +224,7 @@
 			<li>Slime.PawnKindDef.defname</li> - some slime PawnKindDef
 			<li>MotherKindDef</li> - use mother PawnKindDef
 			<li>FatherKindDef</li> - use father PawnKindDef
+			<li>your.PawnKindDef.defname</li> - birth something shouldnt exist
 			-->
 		</hybridChildKindDef>
 		
@@ -240,18 +244,17 @@
 		<raceSexDrive>1.0</raceSexDrive>			<!--how fast race sex need reduces(no effect for animals, not shown in sex stats, goes directly to sex need calc )-->
 		<hasSingleGender>false</hasSingleGender>	<!--if genderless race, set futa without gender change to female. -->
 		<hasSexNeed>true</hasSexNeed>				<!--asexual pawns, mechanoids, droids, etc-->
-		<!--<limitedSex>12</limitedSex>-->					<!--humanlikes teen/can have sex with pawns within 2.5% age difference, for humans: 80*0.025= +-2y-->
-		<!--<freeSex>18</freeSex>-->						<!--humanlikes adult/can have sex with everyone-->
+		<!--<limitedSex>13</limitedSex>-->			<!--Default 13; humanlikes teen/can have sex with pawns within 2.5% age difference until adulthood, for humans: 80*0.025= +-2y-->
+		<!--<limitedSex>13</limitedSex>-->			<!--can be used to disable sex for animals with sokmething like 999-->
 
 		<!--normal pregnancy-->
 		<hasFertility>true</hasFertility>			<!--can be pregnant or fertilize, not mechanoids(always can impregnate/implant), droids, etc-->
 		<hasPregnancy>true</hasPregnancy>			<!--can be pregnant, not mechanoids, droids, etc-->
-		<!--<pPregnancyGrowth>12</pPregnancyGrowth>-->		<!--phantasy Pregnancy rapid Growth to age or until pawn is considered adult-->
 		
 		<!--egg laying-->
-		<oviPregnancy>false</oviPregnancy>			<!--ovi pregnancy, produces and birth eggs instead of normal pregnancy, eggs will be either mother race or w/e they are defined in eggDef-->
+		<oviPregnancy>false</oviPregnancy>			<!--ovi pregnancy, produces and births eggs instead of normal pregnancy, eggs will be either mother race or w/e they are defined in eggDef-->
 		<!--overrides CompProperties_EggLayer properties, requires oviPregnancy=true -->
-		<eggFertilizedDef>RJW_EggFertilized</eggFertilizedDef>		<!--default falback outcome: chicken-->
+		<eggFertilizedDef>RJW_EggFertilized</eggFertilizedDef>		<!--produces w/e you defin in egg. Default falback outcome: chicken-->
 		<eggUnfertilizedDef>RJW_EggUnfertilized</eggUnfertilizedDef>
 		<eggProgressUnfertilizedMax>1.0</eggProgressUnfertilizedMax>
 		<eggLayIntervalDays>3.5</eggLayIntervalDays>
diff --git a/1.4/Source/Common/Data/RaceGroupDef.cs b/1.4/Source/Common/Data/RaceGroupDef.cs
index 2b530244016e765fd2d794ff6692f548b72fb7d3..c28a8f75f2c957498bcf4b5e1e309c3f316a394f 100644
--- a/1.4/Source/Common/Data/RaceGroupDef.cs
+++ b/1.4/Source/Common/Data/RaceGroupDef.cs
@@ -40,9 +40,7 @@ namespace rjw
 		public bool oviPregnancy = false;
 		public bool ImplantEggs = false;
 		public bool HasUdder = false;
-		[Obsolete("isDemon is obsolete, use tags instead.")]
 		public bool isDemon = false;
-		[Obsolete("isSlime is obsolete, use tags instead.")]
 		public bool isSlime = false;
 		public float raceSexDrive = 1.0f;
 
@@ -51,8 +49,10 @@ namespace rjw
 		public float eggProgressUnfertilizedMax = 1.0f;
 		public float eggLayIntervalDays = 3.5f;
 
-		//public int limitedSex = 12;
-		//public int freeSex = 18;
+		/// <summary>
+		/// limit age at which sex becomes available for humans/animals
+		/// </summary>
+		public int limitedSex;
 		//public int pPregnancyGrowth = 12;
 
 		//public float eggCountRange = 3.5f;
diff --git a/1.4/Source/Common/Helpers/SexUtility.cs b/1.4/Source/Common/Helpers/SexUtility.cs
index 21e8c0bd010a2ccb0921b6c350271fc32a3463d3..15acb972a60da3698cbffdddddb627d1d6323cf5 100644
--- a/1.4/Source/Common/Helpers/SexUtility.cs
+++ b/1.4/Source/Common/Helpers/SexUtility.cs
@@ -1059,13 +1059,14 @@ namespace rjw
 
 					if (gainrest)
 					{
-						Need_Rest need = props.pawn.needs.TryGetNeed<Need_Rest>();
-						if (need != null)
+						Need_Rest need1 = props.pawn.needs?.TryGetNeed<Need_Rest>();
+						Need_Rest need2 = props.partner.needs?.TryGetNeed<Need_Rest>();
+						if (need1 != null && need2 != null)
 						{
 							//Log.Message("TransferNutritionSucc() " + xxx.get_pawnname(partner) + " increase rest");
-							props.partner.needs.TryGetNeed(need.def).CurLevel += 0.25f;
+							props.partner.needs.TryGetNeed(need2.def).CurLevel += 0.25f;
 							//Log.Message("TransferNutritionSucc() " + xxx.get_pawnname(pawn) + " decrease rest");
-							props.pawn.needs.TryGetNeed(need.def).CurLevel -= 0.25f;
+							props.pawn.needs.TryGetNeed(need1.def).CurLevel -= 0.25f;
 						}
 					}
 				}
@@ -1100,13 +1101,14 @@ namespace rjw
 
 					if (gainrest)
 					{
-						Need_Rest need = props.partner.needs.TryGetNeed<Need_Rest>();
-						if (need != null)
+						Need_Rest need1 = props.partner.needs.TryGetNeed<Need_Rest>();
+						Need_Rest need2 = props.pawn.needs.TryGetNeed<Need_Rest>();
+						if (need1 != null && need2 != null)
 						{
 							//Log.Message("TransferNutritionSucc() " + xxx.get_pawnname(pawn) + " increase rest");
-							props.pawn.needs.TryGetNeed(need.def).CurLevel += 0.25f;
+							props.pawn.needs.TryGetNeed(need2.def).CurLevel += 0.25f;
 							//Log.Message("TransferNutritionSucc() " + xxx.get_pawnname(partner) + " decrease rest");
-							props.partner.needs.TryGetNeed(need.def).CurLevel -= 0.25f;
+							props.partner.needs.TryGetNeed(need1.def).CurLevel -= 0.25f;
 						}
 					}
 				}
diff --git a/1.4/Source/Common/SexAppraiser.cs b/1.4/Source/Common/SexAppraiser.cs
index 7ab54ae952f4f6f7259313bebc749e55f01f04f8..ff01cea0831cebd245acfb3ca05ce80e30b6e3a9 100644
--- a/1.4/Source/Common/SexAppraiser.cs
+++ b/1.4/Source/Common/SexAppraiser.cs
@@ -316,6 +316,7 @@ namespace rjw
 
 			// --- Orientation checks ---
 			float orientation_factor = GetOrientationFactor(fucker, fucked, ignore_gender);
+			//retry vanilla if 0
 			if (orientation_factor == 0.0f)
 			{
 				orientation_factor = fucker.relations.SecondaryLovinChanceFactor(fucked);
@@ -348,6 +349,12 @@ namespace rjw
 			return Mathf.Min(final_att, fuckability_per_reserved.Evaluate(reservedPercentage));
 		}
 
+		/// <summary>
+		/// rjw settings gender sex limiters homo/nohomo
+		/// </summary>
+		/// <param name="fucker"></param>
+		/// <param name="fucked"></param>
+		/// <returns></returns>
 		private static bool IsGenderOk(Pawn fucker, Pawn fucked)
 		{
 			if (fucker.gender == Gender.Male)
@@ -625,33 +632,18 @@ namespace rjw
 				{
 					age_ok = true;
 				}
-				//else if (xxx.is_human(fucker) && xxx.is_animal(fucked))
-				//{
-				//	float li = fucked.RaceProps.lifeExpectancy;
-				//	if (fucked_age > li * 0.07f && fucked_age < li * 0.625f)
-				//	{
-				//		return true;
-				//	}
-				//}
 				else
 					age_ok = false;
 
 				if (age_ok && xxx.is_human(fucker) && xxx.is_human(fucked))
 				{
-					if (RJWSettings.sex_age_legacymode)
-					{
-						if (fucker_age < RJWSettings.sex_free_for_all_age || fucked_age < RJWSettings.sex_free_for_all_age)
-							age_ok = Math.Abs(fucker.ageTracker.AgeBiologicalYearsFloat - fucked.ageTracker.AgeBiologicalYearsFloat) < 2.05f;
-					}
-					else
+					if (fucker.ageTracker.Growth < 1 || fucked.ageTracker.Growth < 1)
 					{
 						float scaledFuckerAge = AgeHelper.ScaleToHumanAge(fucker);
 						float scaledFuckedAge = AgeHelper.ScaleToHumanAge(fucked);
-
-						if (fucker.ageTracker.Growth < 1 || fucked.ageTracker.Growth < 1)
-							age_ok = Math.Abs(scaledFuckerAge - scaledFuckedAge) < 2.05f;
-						//Log.Message(" AdultMinAge " + fucker.ageTracker.AdultMinAge);
+						age_ok = Math.Abs(scaledFuckerAge - scaledFuckedAge) < 2.05f;
 					}
+					//Log.Message(" AdultMinAge " + fucker.ageTracker.AdultMinAge);
 				}
 			}
 			//Log.Message("would_fuck() - age_ok = " + age_ok.ToString());
diff --git a/1.4/Source/Common/xxx.cs b/1.4/Source/Common/xxx.cs
index 29870bcc57b1cb9e40f8a2919e7ec3943a6003cf..821453c04a893a7e271efb15ff08eca55d0c75c9 100644
--- a/1.4/Source/Common/xxx.cs
+++ b/1.4/Source/Common/xxx.cs
@@ -713,28 +713,18 @@ namespace rjw
 
 			if (is_human(pawn))
 			{
-				//TODO: fix races with weird ages
-				//if (pawn.RaceProps.lifeExpectancy > 100 || pawn.RaceProps.lifeExpectancy < 60)
-				//var age_ok = false;
-				//if (pawn.kindDef.race.ToStringSafe() != "Human") // non humans
-				//{
-				//	//Log.Message("human");
-				//	if (pawn.ageTracker.CurLifeStage.reproductive)
-				//		age_ok = true;
-				//}
-
-				if (RJWSettings.sex_age_legacymode)
+				int age = pawn.ageTracker.AgeBiologicalYears;
+				var t = 13;
+				if (pawn.GetRJWPawnData().RaceSupportDef?.limitedSex != null && pawn.GetRJWPawnData().RaceSupportDef?.limitedSex != 0)
 				{
-					//if (!age_ok) //humans def 13+
-					int age = pawn.ageTracker.AgeBiologicalYears;
-					if (age < RJWSettings.sex_minimum_age)
-						return false;
+					t = pawn.GetRJWPawnData().RaceSupportDef.limitedSex;
 				}
-				else
-				{
-					if (pawn.ageTracker.Growth < 1 && !pawn.ageTracker.CurLifeStage.reproductive)
+				else if (!pawn.ageTracker.CurLifeStage.reproductive)
+					if (pawn.ageTracker.Growth < 1)
 						return false;
-				}
+
+				if (age <= t)
+					return false;
 
 				if (!pawn.apparel.WornApparel.NullOrEmpty())
 					if (pawn.apparel.WornApparel.Where(x => x.def.defName.ToLower().Contains("warcasket")).Any())
@@ -744,8 +734,20 @@ namespace rjw
 			}
 			if (is_animal(pawn))
 			{
-				//CurLifeStageIndex for insects since they are not reproductive
-				return (pawn.ageTracker.Growth >= 1 || pawn.ageTracker.CurLifeStage.reproductive);
+				int age = pawn.ageTracker.AgeBiologicalYears;
+				var t = 1;
+				if (pawn.GetRJWPawnData().RaceSupportDef?.limitedSex != null && pawn.GetRJWPawnData().RaceSupportDef?.limitedSex != 0)
+				{
+					t = pawn.GetRJWPawnData().RaceSupportDef.limitedSex;
+				}
+				//CurLifeStageIndex/Growth for insects since they are not reproductive
+				if (pawn.ageTracker.Growth >= 1 || pawn.ageTracker.CurLifeStage.reproductive)
+				{
+					if (age <= t)
+						return false;
+				}
+				else
+					return true;
 			}
 			return false;
 		}
diff --git a/1.4/Source/Comps/CompRJW.cs b/1.4/Source/Comps/CompRJW.cs
index 7656d995f9d0d4f51c07ce2812dea95d131e8a43..8e16c0bb8c903cc85ffdffc2d6286aa378d1d8f2 100644
--- a/1.4/Source/Comps/CompRJW.cs
+++ b/1.4/Source/Comps/CompRJW.cs
@@ -222,6 +222,12 @@ namespace rjw
 			}
 		}
 
+		/// <summary>
+		/// check try vanilla traits/mods, check rjw genitals, futa check, some rng rolls
+		/// </summary>
+		/// <param name="pawn"></param>
+		/// <param name="partner"></param>
+		/// <returns></returns>
 		public static bool CheckPreference(Pawn pawn, Pawn partner)
 		{
 			if (RJWPreferenceSettings.sexuality_distribution == RJWPreferenceSettings.Rjw_sexuality.Vanilla)
diff --git a/1.4/Source/Needs/Need_Sex.cs b/1.4/Source/Needs/Need_Sex.cs
index bb7d6886660d6056599896b33bbeb0442c8d318e..aa03f3f9fd0b3761149530e276d38652248872e5 100644
--- a/1.4/Source/Needs/Need_Sex.cs
+++ b/1.4/Source/Needs/Need_Sex.cs
@@ -128,38 +128,9 @@ namespace rjw
 
 		static float agefactor(Pawn pawn)
 		{
-			if (xxx.is_human(pawn))
-			{
-				//countdown
-				Need_Sex horniness = pawn.needs.TryGetNeed<Need_Sex>();
-				if (horniness.CurLevel > 0.5f)
-					return 1f;
-
-				//set to 50% for underage
+			if (!xxx.can_do_loving(pawn))
+				return 0f;
 
-				if (RJWSettings.sex_age_legacymode)
-				{
-					int age = pawn.ageTracker.AgeBiologicalYears;
-					if (age < RJWSettings.sex_minimum_age)
-						return 0f;
-				}
-				//{
-				//	int age = pawn.ageTracker.AgeBiologicalYears;
-				//	int t = 12; // humans teen/reproductive stage
-				//	if (pawn.GetRJWPawnData().RaceSupportDef?.limitedSex != null)
-				//	{
-				//		t = pawn.GetRJWPawnData().RaceSupportDef.limitedSex;
-				//	}
-				//	else if (!pawn.ageTracker.CurLifeStage.reproductive)
-				//		if (pawn.ageTracker.Growth < 1)
-				//			return 0f;
-
-				//	if (age < t)
-				//		return 0f;
-				//}
-				if (pawn.ageTracker.Growth < 1 && !pawn.ageTracker.CurLifeStage.reproductive)
-					return 0f;
-			}
 			return 1f;
 		}
 
diff --git a/1.4/Source/Settings/RJWSettings.cs b/1.4/Source/Settings/RJWSettings.cs
index c3c4f8f321abfa6016379ba3b70db240f2f73d37..5b15aa91f0ab6878012227c66b89723a8b19ede5 100644
--- a/1.4/Source/Settings/RJWSettings.cs
+++ b/1.4/Source/Settings/RJWSettings.cs
@@ -44,8 +44,6 @@ namespace rjw
 
 		public static bool sex_age_legacymode = false;
 		public static bool sexneed_fix = true;
-		public static int sex_minimum_age = 13;
-		public static int sex_free_for_all_age = 18;
 		public static float sexneed_decay_rate = 1.0f;
 		public static int Animal_mating_cooldown = 0;
 
@@ -241,13 +239,6 @@ namespace rjw
 			Animal_mating_cooldown = (int)listingStandard.Slider(Animal_mating_cooldown, 0, 100);
 			listingStandard.Gap(5f);
 			listingStandard.CheckboxLabeled("sex_age_legacymode".Translate(), ref sex_age_legacymode, "sex_age_legacymode_desc".Translate());
-			if (sex_age_legacymode)
-			{
-				listingStandard.Label("SexMinimumAge".Translate() + ": " + sex_minimum_age, -1f, "SexMinimumAge_desc".Translate());
-				sex_minimum_age = (int)listingStandard.Slider(sex_minimum_age, 0, 100);
-				listingStandard.Label("SexFreeForAllAge".Translate() + ": " + sex_free_for_all_age, -1f, "SexFreeForAllAge_desc".Translate());
-				sex_free_for_all_age = (int)listingStandard.Slider(sex_free_for_all_age, 0, 999);
-			}
 			if (rape_enabled)
 			{
 				listingStandard.Label("NonFutaWomenRaping_MaxVulnerability".Translate() + ": " + (int)(nonFutaWomenRaping_MaxVulnerability * 100), -1f, "NonFutaWomenRaping_MaxVulnerability_desc".Translate());
@@ -335,8 +326,6 @@ namespace rjw
 			Scribe_Values.Look(ref cum_filth, "cum_filth", cum_filth, true);
 			Scribe_Values.Look(ref sex_age_legacymode, "sex_age_legacymode", sex_age_legacymode, true);
 			Scribe_Values.Look(ref sexneed_fix, "sexneed_fix", sexneed_fix, true);
-			Scribe_Values.Look(ref sex_minimum_age, "sex_minimum_age", sex_minimum_age, true);
-			Scribe_Values.Look(ref sex_free_for_all_age, "sex_free_for_all", sex_free_for_all_age, true);
 			Scribe_Values.Look(ref sexneed_decay_rate, "sexneed_decay_rate", sexneed_decay_rate, true);
 			Scribe_Values.Look(ref Animal_mating_cooldown, "Animal_mating_cooldown", Animal_mating_cooldown, true);
 			Scribe_Values.Look(ref nonFutaWomenRaping_MaxVulnerability, "nonFutaWomenRaping_MaxVulnerability", nonFutaWomenRaping_MaxVulnerability, true);
diff --git a/1.4/Source/ThinkTreeNodes/ThinkNode_ConditionalSexChecks.cs b/1.4/Source/ThinkTreeNodes/ThinkNode_ConditionalSexChecks.cs
index 6f34c9876f79e7e49b5c848c44bce35ecd190c05..ea86a665151f3bd2be25d31f572b3b6e152a9c14 100644
--- a/1.4/Source/ThinkTreeNodes/ThinkNode_ConditionalSexChecks.cs
+++ b/1.4/Source/ThinkTreeNodes/ThinkNode_ConditionalSexChecks.cs
@@ -26,8 +26,7 @@ namespace rjw
 				return false;
 
 			// Setting checks.
-			if (xxx.is_human(p) && ((RJWSettings.sex_age_legacymode && p.ageTracker.AgeBiologicalYears < RJWSettings.sex_minimum_age) ||
-				(!RJWSettings.sex_age_legacymode && !p.ageTracker.CurLifeStage.reproductive)))
+			if (!xxx.can_do_loving(p))
 				return false;
 			else if (xxx.is_animal(p) && !RJWSettings.bestiality_enabled && !RJWSettings.animal_on_animal_enabled)
 				return false;
diff --git a/1.4/Source/Thoughts/ThoughtWorker_NeedSex.cs b/1.4/Source/Thoughts/ThoughtWorker_NeedSex.cs
index b957789a9365856a571d53148ecbe3f333a4758c..e9aa3d9e9cd424cd85796fa57f0b6f5659e29265 100644
--- a/1.4/Source/Thoughts/ThoughtWorker_NeedSex.cs
+++ b/1.4/Source/Thoughts/ThoughtWorker_NeedSex.cs
@@ -10,10 +10,7 @@ namespace rjw
 			var sex_need = p.needs.TryGetNeed<Need_Sex>();
 
 			if (sex_need != null)
-				if ((!xxx.is_human(p) && p.ageTracker.CurLifeStage.reproductive) ||
-					(xxx.is_human(p) &&
-					(!RJWSettings.sex_age_legacymode && p.ageTracker.CurLifeStage.reproductive || 
-					(RJWSettings.sex_age_legacymode && (p.ageTracker.AgeBiologicalYears >= RJWSettings.sex_minimum_age)))))
+				if (xxx.can_do_loving(p))
 			{
 				var lev = sex_need.CurLevel;
 				if (lev <= sex_need.thresh_frustrated())