diff --git a/CHANGELOG.md b/CHANGELOG.md
index 592fcd0e5450d0104e2a98a4a80eaabb9f8263b5..ce2630792d4929be6510245a72735aecafee42cb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
 
 ## Unreleased
 
+* added penetrative skill
+* added toggle for RA-sort, toggle for Favorites Passage, search history for Find Slave + L hotkey
+* fixes
+* ai art improvements
+
 ## 0.10.7.1-4.0.0-alpha.27 - 2023-08-29
 
 * added a series of consumer reduction drugs
diff --git a/devTools/types/FC/gameState.d.ts b/devTools/types/FC/gameState.d.ts
index 67334d95bb3b014769355d281ceecbecb05a47ef..679a39535d05e2c0922db60b5b3d1e069a7ff940 100644
--- a/devTools/types/FC/gameState.d.ts
+++ b/devTools/types/FC/gameState.d.ts
@@ -76,7 +76,7 @@ declare namespace FC {
 	}
 
 	export type HeadGirlTraining = "health" | "paraphilia" | "soften" | "flaw" | "obedience" |
-		"entertain skill" | "oral skill" | "fuck skill" | "anal skill" | "whore skill";
+		"entertain skill" | "oral skill" | "fuck skill" | "penetrative skill" | "anal skill" | "whore skill";
 
 	export interface HeadGirlTrainee {
 		ID: number;
diff --git a/js/003-data/slaveSummaryData.js b/js/003-data/slaveSummaryData.js
index 5377c2e43bab6874433760680d40cb8d703534b9..8d8a128d7dae20b8b2c113903a6988619762ee9e 100644
--- a/js/003-data/slaveSummaryData.js
+++ b/js/003-data/slaveSummaryData.js
@@ -611,13 +611,15 @@ App.Data.SlaveSummary = {
 				99: {desc: "Expert entertainer", style: "skill"},
 				999: {desc: "Masterful entertainer", style: "skill"}
 			},
-			sex: { // indices: [sexSkills, hasVagina(0,1)]
+			sex: { // indices: [sexSkills, hasVagina(0,1) + hasPenis(0,2)] 5.0.0 needs to better address male/female here
 				30: {desc: "Sexually unskilled", style: "skill"},
 				90: {desc: "Sexually skilled", style: "skill"},
 				120: {desc: "Sexual expert", style: "skill"},
 				180: {
-					0: {desc: "Masterful shemale", style: "skill"},
-					1: {desc: "Sexual expert", style: "skill"}
+					0: {desc: "Masterful null", style: "skill"},
+					1: {desc: "Sexual expert", style: "skill"},
+					2: {desc: "Masterful shemale", style: "skill"},
+					3: {desc: "Masterful hermaphrodite", style: "skill"}
 				},
 				9999: {desc: "Sex master", style: "skill"}
 			},
@@ -1395,13 +1397,15 @@ App.Data.SlaveSummary = {
 				99: {desc: "E++", style: "skill"},
 				999: {desc: "E+++", style: "skill"}
 			},
-			sex: { // indices: [sexSkills, hasVagina(0,1)]
+			sex: { // indices: [sexSkills, hasVagina(0,1), hasPenis(0,2)]
 				30: {desc: "S-", style: "skill"},
 				90: {desc: "S+", style: "skill"},
 				120: {desc: "S++", style: "skill"},
 				180: {
-					0: {desc: "Sh++", style: "skill"},
-					1: {desc: "S++", style: "skill"}
+					0: {desc: "S0++", style: "skill"},
+					1: {desc: "S++", style: "skill"},
+					2: {desc: "Sh++", style: "skill"},
+					3: {desc: "SF++", style: "skill"}
 				},
 				9999: {desc: "S++", style: "skill"}
 			},
diff --git a/js/rulesAssistant/conditionEvaluation.js b/js/rulesAssistant/conditionEvaluation.js
index 82d7dfc6976184bcd37d5678def1fe6b7f0817e3..4041965755d6d5d40af09b52818a9b1b6deb74eb 100644
--- a/js/rulesAssistant/conditionEvaluation.js
+++ b/js/rulesAssistant/conditionEvaluation.js
@@ -695,6 +695,11 @@ App.RA.Activation.populateGetters = function() {
 		description: "Unskilled: (-∞, 10), Basic: [10, 30), Skilled: [30, 60), Expert: [60, 99), Master: [99, ∞)",
 		val: c => c.slave.skill.vaginal
 	});
+	gm.addNumber("penetrativeskill", {
+		name: "Penetrative Skill",
+		description: "Unskilled: (-∞, 10), Basic: [10, 30), Skilled: [30, 60), Expert: [60, 99), Master: [99, ∞)",
+		val: c => c.slave.skill.penetrative
+	});
 	gm.addNumber("whoringskill", {
 		name: "Whoring Skill",
 		description: "Unskilled: (-∞, 10), Basic: [10, 30), Skilled: [30, 60), Expert: [60, 99), Master: [99, ∞)",
diff --git a/saveTools/fc_edit_save.py b/saveTools/fc_edit_save.py
index 3925dfcf2caa96433c0f18cef7684120e599e8f5..955f8dfb2b24b7a628f48bbf2d217657a9d71d2d 100755
--- a/saveTools/fc_edit_save.py
+++ b/saveTools/fc_edit_save.py
@@ -95,9 +95,9 @@ IGNORE_IN_PC = [
     "skill.bodyguard", "skill.combat", "skill.entertainer",
     "skill.entertainment", "skill.farmer", "skill.headGirl", "skill.madam",
     "skill.matron", "skill.milkmaid", "skill.nurse", "skill.oral",
-    "skill.recruiter", "skill.servant", "skill.stewardess", "skill.teacher",
-    "skill.vaginal", "skill.wardeness", "skill.whore", "skill.whoring",
-    "slaveCost", "subTarget", "toyHole", "training", "trust",
+    "skill.penetrative", "skill.recruiter", "skill.servant", "skill.stewardess",
+    "skill.teacher", "skill.vaginal", "skill.wardeness", "skill.whore",
+    "skill.whoring", "slaveCost", "subTarget", "toyHole", "training", "trust",
     "useRulesAssistant", "weekAcquired", "whoreClass"
 ]
 
@@ -385,7 +385,8 @@ SLAVE_ACTIONS = {
     ],
     "master": [
         "skill.vaginal=100", "skill.oral=100", "skill.anal=100",
-        "skill.whoring=100", "skill.entertainment=100", "skill.combat=1"
+        "skill.penetrative=100", "skill.whoring=100",
+        "skill.entertainment=100", "skill.combat=1"
     ],
     "allroles": [
         "skill.headGirl=100~200", "skill.recruiter=100~200",
diff --git a/src/002-config/fc-version.js b/src/002-config/fc-version.js
index 39138692d1fe73c0d7b0cd6078b070241a3ef5f3..027b5b36644c63851fda1bb2167478179fb3bfa3 100644
--- a/src/002-config/fc-version.js
+++ b/src/002-config/fc-version.js
@@ -2,5 +2,5 @@ App.Version = {
 	base: "0.10.7.1", // The vanilla version the mod is based off of, this should never be changed.
 	pmod: "4.0.0-alpha.27",
 	commitHash: null,
-	release: 1211, // When getting close to 2000, please remove the check located within the onLoad() function defined at line five of src/js/eventHandlers.js.
+	release: 1212, // When getting close to 2000, please remove the check located within the onLoad() function defined at line five of src/js/eventHandlers.js.
 };
diff --git a/src/Mods/SecExp/events/secExpSmilingMan3.js b/src/Mods/SecExp/events/secExpSmilingMan3.js
index a18b3ce48fedb652e8bfcec15099caee7b99f7b3..aa081eb37156f8fe64005eeebd1e90e0e9ae0ad9 100644
--- a/src/Mods/SecExp/events/secExpSmilingMan3.js
+++ b/src/Mods/SecExp/events/secExpSmilingMan3.js
@@ -41,6 +41,7 @@ App.Events.secExpSmilingMan3 = class secExpSmilingMan3 extends App.Events.BaseEv
 		smileSlave.lips = 15;
 		smileSlave.behavioralFlaw = "odd";
 		smileSlave.skill.vaginal = 0;
+		smileSlave.skill.penetrative = 0;
 		smileSlave.skill.oral = 0;
 		smileSlave.skill.anal = 0;
 		smileSlave.skill.whoring = 0;
diff --git a/src/data/backwardsCompatibility/datatypeCleanup.js b/src/data/backwardsCompatibility/datatypeCleanup.js
index 5731b7ca5718ab2b59e531d70dfe8aee935c80cc..5f401ffb15b50c7933050f1973d25681a49a0c9c 100644
--- a/src/data/backwardsCompatibility/datatypeCleanup.js
+++ b/src/data/backwardsCompatibility/datatypeCleanup.js
@@ -195,6 +195,18 @@ App.Entity.Utils.SlaveDataSchemeCleanup = (function() {
 				}
 			}
 		}
+		if (!slave.skill.hasOwnProperty("penetrative")) {
+			slave.skill.penetrative = 0;
+			if (slave.pubertyXY === 1) {
+				slave.skill.penetrative += 15;
+			}
+			if (slave.dick > 0 || slave.clit >= 3) {
+				slave.skill.penetrative += 15;
+			}
+			if (slave.fetish === Fetish.DOM) {
+				slave.skill.penetrative += 15;
+			}
+		}
 	}
 
 	/**
@@ -944,6 +956,7 @@ globalThis.SlaveDatatypeCleanup = (function SlaveDatatypeCleanup() {
 	function slaveSkillsDatatypeCleanup(slave) {
 		slave.skill.oral = Math.clamp(+slave.skill.oral, 0, 100) || 0;
 		slave.skill.vaginal = Math.clamp(+slave.skill.vaginal, 0, 100) || 0;
+		slave.skill.penetrative = Math.clamp(+slave.skill.penetrative, 0, 100) || 0;
 		slave.skill.anal = Math.clamp(+slave.skill.anal, 0, 100) || 0;
 		slave.skill.whoring = Math.clamp(+slave.skill.whoring, 0, 100) || 0;
 		slave.skill.entertainment = Math.clamp(+slave.skill.entertainment, 0, 100) || 0;
diff --git a/src/descriptions/officeDescription.js b/src/descriptions/officeDescription.js
index a4db22c287404776cc253240c8eb0a7a0c5a395d..8382fe23fe45a2f5cdf1863bc77bc3a33a4b55de 100644
--- a/src/descriptions/officeDescription.js
+++ b/src/descriptions/officeDescription.js
@@ -30,8 +30,20 @@ App.Desc.officeDescription = function(lastElement) {
 
 				if (random(1, 2) === 1 || !canStand(modeledSlave)) {
 					r.push(`This includes a sex toy based on ${modeledSlave.slaveName}'s`);
-					if (random(1, 3) === 1 &&
-						modeledSlave.skill.vaginal >= 100) {
+					if (random(1, 4) === 1 && modeledSlave.skill.penetrative >= 100 && canAchieveErection(modeledSlave) && penetrativeSocialUse(modeledSlave) > 70) {
+						if (modeledSlave.dick >= 10) {
+							r.push(`dick; there is no way that thing is fitting in someone.`);
+						} else if (modeledSlave.dick > 6) {
+							r.push(`massive penis`);
+						} else if (modeledSlave.dick > 3) {
+							r.push(`huge cock`);
+						} else if (modeledSlave.dick > 2) {
+							r.push(`dick`);
+						} else {
+							r.push(`tiny little erection`);
+						}
+						r.push(r.pop() + ".");				
+					} else if (random(1, 3) === 1 && modeledSlave.skill.vaginal >= 100) {
 						if (modeledSlave.vagina > 3) {
 							r.push(`massive vagina`);
 						} else if (modeledSlave.vagina > 2) {
@@ -71,7 +83,15 @@ App.Desc.officeDescription = function(lastElement) {
 					}
 				} else {
 					r.push(`There is a figurine of ${modeledSlave.slaveName}. ${He}'s depicted`);
-					if (random(1, 3) === 1 && modeledSlave.skill.vaginal >= 100) {
+					if (random(1, 4) === 1 && modeledSlave.skill.penetrative >= 100 && canAchieveErection(modeledSlave) && penetrativeSocialUse(modeledSlave) > 70) {
+						r.push(`thrusting ${his} hips and showing off ${his}`);
+						if (modeledSlave.dick < 10) {
+							r.push(["former","tiny","little","","big","huge","gigantic","massive","truly imposing","monstrous","inhuman"][modeledSlave.dick]);
+						} else {
+							r.push(`hypertrophied`)
+						}
+						r.push(`erection.`)						
+					} else if (random(1, 3) === 1 && modeledSlave.skill.vaginal >= 100) {
 						r.push(`lying nude on ${his} back, spreading ${his} legs to`);
 						if (modeledSlave.vagina > 3) {
 							r.push(`exhibit ${his} massive vagina`);
diff --git a/src/endWeek/economics/neighborsDevelopment.js b/src/endWeek/economics/neighborsDevelopment.js
index c7ac0fcb3efb1b8e92fa8fedc3bd6de352f1434b..1ebdfcbaa757fb30f580f96b3cf5d5ed84beed75 100644
--- a/src/endWeek/economics/neighborsDevelopment.js
+++ b/src/endWeek/economics/neighborsDevelopment.js
@@ -1976,7 +1976,7 @@ App.EndWeek.neighborsDevelopment = function() {
 					candidates.push({fs: "FSDegradationist", msg: `since as a sexual sadist, ${he}'s excited by the idea of leading a society that applauds ${his} cruelest impulses.`});
 				}
 				if (leader.intelligence + leader.intelligenceImplant >= 120) {
-					if (leader.skill.vaginal + leader.skill.oral + leader.skill.anal + leader.skill.whoring + leader.skill.entertainment >= 400) {
+					if (leader.skill.penetrative + leader.skill.vaginal + leader.skill.oral + leader.skill.anal + leader.skill.whoring + leader.skill.entertainment >= 400) {
 						candidates.push({fs: "FSSlaveProfessionalism", msg: `since ${he} wishes to produce slaves you can be proud of.`});
 					}
 					if (leader.behavioralFlaw === BehavioralFlaw.ARROGANT) {
diff --git a/src/endWeek/endWeek.js b/src/endWeek/endWeek.js
index bb00808edd4b00dc95f997053c7c97be7e65200a..c0e964866fdeada60db69d565878388c66bb4fbf 100644
--- a/src/endWeek/endWeek.js
+++ b/src/endWeek/endWeek.js
@@ -48,7 +48,7 @@ globalThis.endWeek = (function() {
 		V.vaginalUseWeight = 5;
 		V.analUseWeight = 5;
 		V.mammaryUseWeight = 1;
-		V.penetrativeUseWeight = 1;
+		V.penetrativeUseWeight = 1 + Math.trunc(penetrativeSocialUse() / 25);
 
 		if (V.policies.oralAppeal === 1) {
 			V.oralUseWeight += 2;
diff --git a/src/endWeek/nextWeek/nextWeek.js b/src/endWeek/nextWeek/nextWeek.js
index ce2e8668df3399915d46244260a2564e5cd2eb8e..25a238545ab7ad511c58c5f2fbe27899f97b4e53 100644
--- a/src/endWeek/nextWeek/nextWeek.js
+++ b/src/endWeek/nextWeek/nextWeek.js
@@ -283,6 +283,7 @@ App.EndWeek.nextWeek = function() {
 		slave.lips = Math.clamp(slave.lips.toFixed(1), 0, 100);
 		slave.skill.oral = Math.clamp(slave.skill.oral.toFixed(1), 0, 100);
 		slave.skill.vaginal = Math.clamp(slave.skill.vaginal.toFixed(1), 0, 100);
+		slave.skill.penetrative = Math.clamp(slave.skill.penetrative.toFixed(1), 0, 100);
 		slave.skill.anal = Math.clamp(slave.skill.anal.toFixed(1), 0, 100);
 		slave.skill.whoring = Math.clamp(slave.skill.whoring.toFixed(1), 0, 100);
 		slave.skill.entertainment = Math.clamp(slave.skill.entertainment.toFixed(1), 0, 100);
diff --git a/src/endWeek/reports/brothelReport.js b/src/endWeek/reports/brothelReport.js
index b6fc41d5978ae6b8d19ee85cf1be426968953bf4..1d4f23f32323912d5fdf353613cc773fcc72d147 100644
--- a/src/endWeek/reports/brothelReport.js
+++ b/src/endWeek/reports/brothelReport.js
@@ -111,7 +111,14 @@ App.EndWeek.brothelReport = function() {
 				r.push(`${He} is a clever manager.`);
 			}
 			if (S.Madam.dick > 2 && canPenetrate(S.Madam)) {
-				r.push(`${His} turgid dick helps ${him} manage the bitches.`);
+				if (S.Madam.skill.penetrative > 90) {
+					r.push(`${His} skilled dick incentivizes the bitches to behave.`);
+				} else if (S.Madam.skill.penetrative > 10) {
+					r.push(`${His} turgid dick helps ${him} manage the bitches.`);
+				} else {
+					r.push(`${He} tries to use ${his} turgid cock to keep the bitches in line, but ${his} lack of skill only leaves them off kilter.`);
+				}
+				slaveSkillIncrease('penetrative', S.Madam, 2);
 			}
 			App.Events.addParagraph(el, r);
 
diff --git a/src/endWeek/reports/cellblockReport.js b/src/endWeek/reports/cellblockReport.js
index d6b0b9326cecc6cd5d753bed9b74266e57d339b8..040234e7dff8fe3d92a9e672081a31ae883af4da 100644
--- a/src/endWeek/reports/cellblockReport.js
+++ b/src/endWeek/reports/cellblockReport.js
@@ -117,6 +117,7 @@ App.EndWeek.cellblockReport = function() {
 			trustMalus++;
 			idleBonus++;
 			r.push(`${His} molestation of the prisoners is more varied and effective because ${he} has a dick to fuck them with.`);
+			slaveSkillIncrease('penetrative', S.Wardeness, 2);
 		}
 		if (S.Wardeness.muscles > 35) {
 			devBonus++;
diff --git a/src/endWeek/reports/dairyReport.js b/src/endWeek/reports/dairyReport.js
index 57c1352659e3ef332be297d3d21034bdabfd5add..07c87179dc38512d2c312d72f5b7227ce24c375a 100644
--- a/src/endWeek/reports/dairyReport.js
+++ b/src/endWeek/reports/dairyReport.js
@@ -271,9 +271,18 @@ App.EndWeek.dairyReport = function() {
 			r.push(slaveSkillIncrease('milkmaid', S.Milkmaid, skillIncrease));
 		}
 		if (prostateStim === 1) {
-			r.push(`${He} uses ${his} turgid cock to give prostate stimulation to slaves that need help ejaculating.`);
+			if (S.Milkmaid.skill.penetrative > 90) {
+				r.push(`${He} uses ${his} turgid cock and masterful technique to milk each slave's prostate dry.`);
+			} else if (S.Milkmaid.skill.penetrative > 10) {
+				r.push(`${He} uses ${his} turgid cock to give prostate stimulation to slaves that need help ejaculating.`);
+			} else {
+				r.push(`${He} tries to use ${his} turgid cock to give prostate stimulation and help slaves ejaculate, but has no idea where ${he} needs to aim to do so.`);
+			}
 			S.Milkmaid.need -= 50;
 		}
+		if (milkmaidImpregnated || prostateStim) {
+			slaveSkillIncrease('penetrative', S.Milkmaid, 2);
+		}
 		V.milkmaidDevotionThreshold += (5 * V.milkmaidDevotionBonus);
 		V.milkmaidTrustThreshold += (5 * V.milkmaidTrustBonus);
 		for (const slave of slaves) {
@@ -834,15 +843,18 @@ App.EndWeek.dairyReport = function() {
 						if (slave.trust < -65) {
 							horrified.push(slave);
 						}
-					} else if (slave.skill.vaginal > 0) {
-						slave.skill.vaginal -= 10;
-						skillsLost.push(slave);
 					} else if (slave.skill.oral > 0) {
 						slave.skill.oral -= 10;
 						skillsLost.push(slave);
 					} else if (slave.skill.anal > 0) {
 						slave.skill.anal -= 10;
 						skillsLost.push(slave);
+					} else if (slave.skill.vaginal > 0) {
+						slave.skill.vaginal -= 10;
+						skillsLost.push(slave);
+					} else if (slave.skill.penetrative > 0) {
+						slave.skill.penetrative -= 10;
+						skillsLost.push(slave);
 					} else if (slave.career !== "a bioreactor") {
 						slave.career = "a bioreactor";
 						careerForgotten.push(slave);
@@ -899,15 +911,18 @@ App.EndWeek.dairyReport = function() {
 					if (slave.trust < -70) {
 						horrified.push(slave);
 					}
-				} else if (slave.skill.vaginal >= 20) {
-					slave.skill.vaginal -= 10;
-					skillsLost.push(slave);
 				} else if (slave.skill.oral >= 20) {
 					slave.skill.oral -= 10;
 					skillsLost.push(slave);
 				} else if (slave.skill.anal >= 20) {
 					slave.skill.anal -= 10;
 					skillsLost.push(slave);
+				} else if (slave.skill.vaginal >= 20) {
+					slave.skill.vaginal -= 10;
+					skillsLost.push(slave);
+				} else if (slave.skill.penetrative >= 20) {
+					slave.skill.penetrative -= 10;
+					skillsLost.push(slave);
 				} else if (slave.career !== "a bioreactor") {
 					slave.career = "a bioreactor";
 					careerForgotten.push(slave);
diff --git a/src/endWeek/reports/masterSuiteReport.js b/src/endWeek/reports/masterSuiteReport.js
index 131fb2f8028043adb51502d7dbfb0564e936c4c8..e4676e7a9ba0921fe34c37f84e20cb8a8c468ba8 100644
--- a/src/endWeek/reports/masterSuiteReport.js
+++ b/src/endWeek/reports/masterSuiteReport.js
@@ -88,7 +88,7 @@ App.EndWeek.masterSuiteReport = function() {
 			S.Concubine.devotion += 2;
 			S.Concubine.trust += 2;
 		}
-		repX(Beauty(S.Concubine) * 5 + (S.Concubine.skill.vaginal || 0) + (S.Concubine.skill.anal || 0) + (S.Concubine.skill.oral || 0) + (S.Concubine.skill.whoring || 0) + (S.Concubine.skill.entertainment || 0), "concubine", S.Concubine);
+		repX(Beauty(S.Concubine) * 5 + (adjustedPenSkill(S.Concubine, true) || 0) + (S.Concubine.skill.vaginal || 0) + (S.Concubine.skill.anal || 0) + (S.Concubine.skill.oral || 0) + (S.Concubine.skill.whoring || 0) + (S.Concubine.skill.entertainment || 0), "concubine", S.Concubine);
 
 		App.Events.addNode(frag, r);
 
diff --git a/src/endWeek/reports/penthouseReport.js b/src/endWeek/reports/penthouseReport.js
index 6de1a22d0bf5abb178ff264726b003853b665769..93b6e502abe1771e64db66721e835825b2b01a8f 100644
--- a/src/endWeek/reports/penthouseReport.js
+++ b/src/endWeek/reports/penthouseReport.js
@@ -246,6 +246,9 @@ App.EndWeek.penthouseReport = function() {
 			case "fuck skill":
 				r.push(`isn't as skilled at vaginal intercourse as ${he} is.`);
 				break;
+			case "penetrative skill":
+				r.push(`isn't as skilled at penetration as ${he} is.`);
+				break;
 			case "whore skill":
 				r.push(`isn't as skilled at the fine art of sex for money as ${he} is.`);
 				break;
@@ -382,6 +385,7 @@ App.EndWeek.penthouseReport = function() {
 				slave.trust += 1;
 			}
 
+			// These all need to be have sex act incrementors added to them. Or is it handled somewhere else?
 			if (headGirlsTraining === "obedience") {
 				slave.training = 0;
 				effectiveness -= (slave.intelligence + slave.intelligenceImplant) / 3;
@@ -476,13 +480,28 @@ App.EndWeek.penthouseReport = function() {
 				} else if (S.HeadGirl.dick > 0 && canPenetrate(S.HeadGirl)) {
 					r.push(`In spare moments ${he} teaches ${slave.slaveName} how to take a dick. Your Head Girl uses ${his} penis as an effective teaching tool. ${slave.slaveName}'s <span class="green">vanilla sex skills have improved.</span>`);
 					slaveSkillIncrease('vaginal', slave, random(5, 10));
-				} else if (S.HeadGirl.clit > 2) {
+				} else if (S.HeadGirl.clit >= 3) {
 					r.push(`In spare moments ${he} teaches ${slave.slaveName} how to take a phallus. Your Head Girl uses ${his} pseudophallus-sized clit as an effective teaching tool. ${slave.slaveName}'s <span class="green">vanilla sex skills have improved.</span>`);
 					slaveSkillIncrease('vaginal', slave, random(5, 10));
 				} else {
 					r.push(`In spare moments ${he} teaches ${slave.slaveName} how to take a dick. ${slave.slaveName}'s <span class="green">vanilla sex skills have improved.</span>`);
 				}
 				slaveSkillIncrease('vaginal', slave, Math.ceil(effectiveness / 10));
+			} else if (headGirlsTraining === "penetrative skill") {
+				slave.training = 0;
+				if (S.HeadGirl.energy > 95) {
+					r.push(`In spare moments ${he} teaches ${slave.slaveName} how to properly fuck a ${girl}. Your Head Girl's enthusiasm for sex is infectious. ${slave.slaveName}'s <span class="green">penetrative skills have improved.</span>`);
+					slaveSkillIncrease('penetrative', slave, random(5, 10));
+				} else if (S.HeadGirl.vagina > 0 && canDoVaginal(S.HeadGirl) && S.HeadGirl.fetish === "pregnancy" && S.HeadGirl.fetishStrength > 60) {
+					r.push(`In spare moments ${he} teaches ${slave.slaveName} how to properly fuck a ${girl}. Your Head Girl uses ${his} pussy as an effective teaching tool. ${slave.slaveName}'s <span class="green">penetrative skills have improved.</span>`);
+					slaveSkillIncrease('penetrative', slave, random(5, 10));
+				} else if (S.HeadGirl.anus > 0 && canDoAnal(S.HeadGirl) && S.HeadGirl.fetish === Fetish.BUTTSLUT && S.HeadGirl.fetishStrength > 60) {
+					r.push(`In spare moments ${he} teaches ${slave.slaveName} how to properly fuck a ${girl}. Your Head Girl uses ${his} rear hole as an effective teaching tool. ${slave.slaveName}'s <span class="green">penetrative skills have improved.</span>`);
+					slaveSkillIncrease('penetrative', slave, random(5, 10));
+				} else {
+					r.push(`In spare moments ${he} teaches ${slave.slaveName} how to properly fuck a ${girl}. ${slave.slaveName}'s <span class="green">penetrative skills have improved.</span>`);
+				}
+				slaveSkillIncrease('penetrative', slave, Math.ceil(effectiveness / 10));
 			} else if (headGirlsTraining === "whore skill") {
 				slave.training = 0;
 				r.push(`In spare moments ${he} teaches ${slave.slaveName} how to prostitute ${himself2}. ${slave.slaveName}'s <span class="green">whoring skills have improved.</span>`);
@@ -717,6 +736,8 @@ App.EndWeek.penthouseReport = function() {
 							HGPossibleSlaves[5].push({ID: slave.ID, training: "oral skill"});
 						} else if (slave.skill.vaginal < S.HeadGirl.skill.vaginal && slave.vagina > 0 && canDoVaginal(slave)) {
 							HGPossibleSlaves[5].push({ID: slave.ID, training: "fuck skill"});
+						} else if (slave.skill.penetrative < S.HeadGirl.skill.penetrative && penetrativeSocialUse(slave) >= 40) {
+							HGPossibleSlaves[5].push({ID: slave.ID, training: "penetrative skill"});
 						} else if (slave.skill.anal < S.HeadGirl.skill.anal && slave.anus > 0 && canDoAnal(slave)) {
 							HGPossibleSlaves[5].push({ID: slave.ID, training: "anal skill"});
 						} else if (slave.skill.whoring < S.HeadGirl.skill.whoring) {
diff --git a/src/endWeek/reports/personalAttention.js b/src/endWeek/reports/personalAttention.js
index 75baabd3e431f0766bd5fdd20d0fba0a3668e580..3a18c86c14fb29109a8ac0922735fad38eb3a27f 100644
--- a/src/endWeek/reports/personalAttention.js
+++ b/src/endWeek/reports/personalAttention.js
@@ -102,6 +102,7 @@ App.PersonalAttention.slaveReport = function(slave) {
 	let coloredText;
 	let trainingEfficiency;
 	let vaginalTrainingEfficiency;
+	let dickTrainingEfficiency;
 	let analTrainingEfficiency;
 	let seed;
 	let skillgainS = false;
@@ -1076,11 +1077,13 @@ App.PersonalAttention.slaveReport = function(slave) {
 				trainingEfficiency += 10;
 			}
 			if (pcHorny) {
+				// wip
 			} else if (pcFrigid) {
 				r.push(`Needing to teach sex while having no desire to have any complicates matters. You do your best to put up an effort when it comes to practical lessons, but it is far too little to be effective.`);
 				trainingEfficiency *= .25;
 			}
 			trainingEfficiency *= hindranceModSex;
+			/*
 			if (hindranceModSex <= .3) {
 				r.push(`With how difficult it is for you to get around, you end up only taking a fraction of the jobs you would normally consider. That is also not taking into account just how easily identifiable someone with your physique is to the public.`);
 			} else if (hindranceModSex <= .5) {
@@ -1088,6 +1091,7 @@ App.PersonalAttention.slaveReport = function(slave) {
 			} else if (hindranceModSex <= .7) {
 				r.push(`You keep missing out on opportunities between the difficulties getting places with your reduced mobility and the increased risk of your physical hindrances making you identifiable.`);
 			}
+			*/
 			Math.max(1, trainingEfficiency);
 
 			if (slave.vagina >= 0) {
@@ -1102,6 +1106,11 @@ App.PersonalAttention.slaveReport = function(slave) {
 			} else if (slave.anus === 0 || !canDoAnal(slave)) {
 				analTrainingEfficiency = Math.trunc(trainingEfficiency / 2);
 			}
+			if (slave.dick === 0 || !canAchieveErection(slave)) {
+				dickTrainingEfficiency = Math.trunc(trainingEfficiency / 4);
+			} else {
+				dickTrainingEfficiency = Math.trunc(trainingEfficiency / 2);
+			}
 			if (slave.devotion > 50) {
 				r.push(`${He}'s devoted to you, making sexual training much easier.`);
 			} else if (slave.devotion > 20) {
@@ -1144,6 +1153,10 @@ App.PersonalAttention.slaveReport = function(slave) {
 				r.push(`Since ${he}'s anally unskilled, and not an anal virgin, you start with ${his} ass.`);
 				r.push(App.UI.DOM.makeElement("span", `${His} anal skills have improved.`, "lime"));
 				r.push(slaveSkillIncrease('anal', slave, trainingEfficiency));
+			} else if (slave.skill.penetrative <= 10 && slave.dick > 0 && canPenetrate(slave)) { // WIP
+				r.push(`Since ${he} is unskilled at using ${his} cock, you start with ${his} dick.`);
+				r.push(App.UI.DOM.makeElement("span", `${His} penetrative skills have improved.`, "lime"));
+				r.push(slaveSkillIncrease('penetrative', slave, trainingEfficiency));
 			} else if (slave.skill.oral <= 30) {
 				r.push(`Since ${he}'s sexually experienced, you work with ${him} on the finer points of oral sex.`);
 				r.push(App.UI.DOM.makeElement("span", `${His} oral skills have improved.`, "lime"));
@@ -1178,6 +1191,23 @@ App.PersonalAttention.slaveReport = function(slave) {
 				}
 				r.push(App.UI.DOM.makeElement("span", `${His} anal skills have improved.`, "lime"));
 				r.push(slaveSkillIncrease('anal', slave, trainingEfficiency));
+			} else if (slave.skill.penetrative <= 30 && slave.dick > 0 && canPenetrate(slave)) { // wip
+				r.push(`Since ${he}'s experienced in penetrating others, you work with ${him} on the finer points of pleasing with ${his} dick. ${He} can already can enter any orifice smoothly, but ${his} control over the pace and the depth and strength of the penetration required at every moment could be improved. ${He} works ${his} Kegel muscles to improve ${his} sexual performance and practices with`);
+				let orifices = [];
+				if (V.policies.sexualOpenness === 1 || slave.toyHole === "dick") {
+					if (V.PC.vagina > 0 && canDoVaginal(V.PC)) {
+						orifices.push("vagina");
+					}
+					if (V.PC.anus > 0 && canDoAnal(V.PC)) {
+						orifices.push("anus");
+					}
+					orifices.push("mouth");
+					orifices[0] = "your " + orifices[0];
+				}
+				orifices.push("the holes of the other slaves you indicate.");
+				r.push(toSentence(orifices));
+				r.push(App.UI.DOM.makeElement("span", `${His} penetrative skills have improved.`, "lime"));
+				r.push(slaveSkillIncrease('penetrative', slave, trainingEfficiency));
 			} else if (slave.skill.vaginal <= 10 && slave.vagina >= 0) {
 				r.push(`Since ${he}'s vaginally unskilled,`);
 				if (slave.vagina === 0 && !canDoVaginal(slave)) {
@@ -1202,6 +1232,18 @@ App.PersonalAttention.slaveReport = function(slave) {
 				r.push(`you explain the basics of anal sex to ${him}.`);
 				r.push(App.UI.DOM.makeElement("span", `${His} anal skills have improved.`, "lime"));
 				r.push(slaveSkillIncrease('anal', slave, analTrainingEfficiency));
+			} else if (slave.skill.penetrative <= 10) { // wip
+				r.push(`Since ${he}'s unskilled penetrating others,`);
+				if (slave.chastityPenis) {
+					r.push(`and ${his} penis is caged,`);
+				} else if (!canAchieveErection(slave)) {
+					r.push(`and can't achieve an erection,`);
+				} else {
+					r.push(`and can't penetrate regular holes,`);
+				}
+				r.push(`you explain the basics of penetrative sex to ${him}.`);
+				r.push(App.UI.DOM.makeElement("span", `${His} penetrative skills have improved.`, "lime"));
+				r.push(slaveSkillIncrease('penetrative', slave, dickTrainingEfficiency));
 			} else if (slave.skill.oral < 100) {
 				r.push(`${He} is already a skilled oral whore, but ${his} skills can be polished further. You train ${him} in the basics of`);
 				if (V.seePee === 1) {
@@ -1276,6 +1318,17 @@ App.PersonalAttention.slaveReport = function(slave) {
 				r.push(App.UI.DOM.makeElement("span", `${His} anal skills have improved,`, "lime"));
 				r.push(`but it's a slow process without practical experience.`);
 				r.push(slaveSkillIncrease('anal', slave, analTrainingEfficiency));
+			} else if (slave.skill.penetrative <= 30 && canAchieveErection(slave)) { // wip
+				r.push(`Since ${he} has only rudimentary penetrative skills,`);
+				if (slave.chastityPenis) {
+					r.push(`and ${his} penis is caged,`);
+				} else {
+					r.push(`and can't penetrate regular holes,`);
+				}
+				r.push(`you spend time teaching ${him} sexual positions and how to someday use ${his} cock to its potential. You have ${him} work ${his} Kegel muscles all week to prepare ${him} for the future.`);
+				r.push(App.UI.DOM.makeElement("span", `${His} penetrative skills have improved,`, "lime"));
+				r.push(`but it's a slow process without practical experience.`);
+				r.push(slaveSkillIncrease('penetrative', slave, dickTrainingEfficiency));
 			} else if (slave.skill.vaginal < 100 && slave.vagina >= 0) {
 				r.push(`${He} already a skilled pussy slut,`);
 				if (slave.vagina === 0 && !canDoVaginal(slave)) {
diff --git a/src/endWeek/saGetMilked.js b/src/endWeek/saGetMilked.js
index 288894ec0e9277f04f618928e75885bcd2fd04a4..604f72b56ab950b855b54448c8774832e1e3ea5a 100644
--- a/src/endWeek/saGetMilked.js
+++ b/src/endWeek/saGetMilked.js
@@ -565,7 +565,13 @@
 					if (S.Milkmaid.dick > 4 && canAchieveErection(S.Milkmaid)) {
 						const milkmaidPronouns = getPronouns(S.Milkmaid);
 						r.text += ` ${S.Milkmaid.slaveName} sometimes stands in for the machines, which is a polite way of saying ${milkmaidPronouns.he} sometimes fucks ${slave.slaveName}'s ass to help ${him} cum.`;
-						r.cum *= 1.2;
+						if (S.Milkmaid.skill.penetrative > 90) {
+							r.cum *= 1.3;
+						} else if (S.Milkmaid.skill.penetrative > 10) {
+							r.cum *= 1.2;
+						} else {
+							r.cum *= 1.1;
+						}			
 					}
 				}
 			}
diff --git a/src/endWeek/saLiveWithHG.js b/src/endWeek/saLiveWithHG.js
index bb20968e1b45208d2bc83bf0eef4ae8aa5a85923..f5df4531199700fd852131152f81e34cfec4ea87 100644
--- a/src/endWeek/saLiveWithHG.js
+++ b/src/endWeek/saLiveWithHG.js
@@ -518,6 +518,9 @@ App.SlaveAssignment.liveWithHG = function saliveWithHG(slave) {
 		} else if (slave.vagina > 0 && canDoVaginal(slave) && slave.skill.vaginal <= 30) {
 			r.push(`${HG.slaveName} wants ${his2} personal sex slave to be as skilled with ${his} pussy as possible, so ${he2} trains ${slave.slaveName}'s vaginal skills.`);
 			r.push(slaveSkillIncrease('vaginal', slave, 10));
+		} else if (((HG.vagina > 0 && canDoVaginal(HG)) || (HG.anus > 0 && canDoAnal(HG))) && slave.dick > 0 && canPenetrate(slave) && slave.skill.penetrative <= 30) {
+			r.push(`${HG.slaveName} wants ${his2} personal sex slave to be as skilled with ${his} dick as possible, so ${he2} trains ${slave.slaveName}'s penetrative skills.`);
+			r.push(slaveSkillIncrease('penetrative', slave, 10));
 		} else if (slave.anus > 0 && canDoAnal(slave) && slave.skill.anal <= 30) {
 			r.push(`${HG.slaveName} wants ${his2} personal sex slave to be a skillful backdoor whore, so ${he2} trains ${slave.slaveName}'s anal skills.`);
 			r.push(slaveSkillIncrease('anal', slave, 10));
diff --git a/src/endWeek/saLongTermEffects.js b/src/endWeek/saLongTermEffects.js
index df07c15fa9f6b30ee9330758157d347e4f4f1bb9..e81b0a89d2841501e1f43c3365b52450dad6e54a 100644
--- a/src/endWeek/saLongTermEffects.js
+++ b/src/endWeek/saLongTermEffects.js
@@ -218,6 +218,13 @@ App.SlaveAssignment.longTermEffects = function saLongTermEffects(slave) {
 					r.push(`${He}'s trained to perform thorough mechanical obedience, <span class="flaw break">utterly destroying ${his} sexual deficiencies.</span>`);
 					slave.sexualFlaw = SexualFlaw.NONE;
 				}
+				if (canAchieveErection(slave)) {
+					r.push(`${He} is trained to become erect on command, to endure having ${his} phallus ridden for as long as desired, to ejaculate on demand, or refrain from doing so if ordered.`);
+					if (slave.skill.penetrative > 25) {
+						r.push(`Since ${his} cock is now a simple accessory to the suit, ${he} <span class="stat drop">quickly loses the finer techniques ${he} once had.</span>`);
+						slave.skill.penetrative = 25;
+					}
+				}
 			} else if (slave.fuckdoll <= 75) {
 				r.push(`This week ${he} <span class="fuckdoll">begins to learn more advanced commands</span> from ${his} suit. ${He} is taught a command that instructs ${him} to take a more active role in penetrative sex. When that command is given, ${he} must fuck ${himself} against any`);
 				if (V.PC.dick !== 0) {
diff --git a/src/endWeek/saPleaseYou.js b/src/endWeek/saPleaseYou.js
index fd3cb702e6481ecd28482dac2b1c6cfc67acbb86..264c11e2dcca4fdda5d6797dcc6f6a79238e1b28 100644
--- a/src/endWeek/saPleaseYou.js
+++ b/src/endWeek/saPleaseYou.js
@@ -1148,6 +1148,10 @@ App.SlaveAssignment.pleaseYou = function saPleaseYou(slave) {
 				r.push(`Spending so much intimate time with an attractive woman <span class="green">reconciles ${him} to serving the fairer sex.</span>`);
 				slave.behavioralFlaw = BehavioralFlaw.NONE;
 			}
+			if (slave.skill.penetrative < 100 && (slave.devotion >= -20 || slave.trust > 20)) {
+				r.push(`You find ${his} ability to fuck you unsatisfactory, so you work to <span class="green">improve ${his} penetrative skills.</span>`);
+				r.push(slaveSkillIncrease("penetrative", slave, trainingEfficiency));
+			}
 		}
 		seX(slave, "penetrative", V.PC, canDoVaginal(V.PC) ? "vaginal" : "anal", penetrativeUse);
 		if (canImpreg(V.PC, slave)) {
@@ -1263,6 +1267,10 @@ App.SlaveAssignment.pleaseYou = function saPleaseYou(slave) {
 				r.push(`Spending so much intimate time with an attractive woman <span class="green">reconciles ${him} to serving the fairer sex.</span>`);
 				slave.behavioralFlaw = BehavioralFlaw.NONE;
 			}
+			if (slave.skill.penetrative < 100 && (slave.devotion >= -20 || slave.trust > 20)) {
+				r.push(`You find ${his} technique lacks refinement, so you work to <span class="green">improve ${his} penetrative skills.</span>`);
+				r.push(slaveSkillIncrease("penetrative", slave, trainingEfficiency));
+			}
 		}
 		seX(slave, "penetrative", V.PC, "oral", penetrativeUse);
 		if (V.policies.sexualOpenness === 0) {
diff --git a/src/endWeek/saRecruitGirls.js b/src/endWeek/saRecruitGirls.js
index bae984a353622be934c2d2c5a580a08fac9e1e11..fbf9690206b2461570271a8e8c4e77ddbcf84e98 100644
--- a/src/endWeek/saRecruitGirls.js
+++ b/src/endWeek/saRecruitGirls.js
@@ -1153,7 +1153,7 @@ App.SlaveAssignment.recruitGirls = function recruitGirls(slave) {
 			if (slave.accent <= 1) {
 				if (totalInt > 50) {
 					if (totalInt > 95) {
-						if (slave.skill.entertainment + slave.skill.whoring + slave.skill.oral + slave.skill.anal + slave.skill.vaginal >= 400) {
+						if (slave.skill.entertainment + slave.skill.whoring + slave.skill.oral + slave.skill.anal + slave.skill.vaginal + slave.skill.penetrative >= 400) {
 							pushFS(`Each week ${he} hosts ${his} own seminar demonstrating new and exciting sexual techniques, some even of ${his} own creation.`);
 							seed += 1;
 						} else {
@@ -1162,7 +1162,7 @@ App.SlaveAssignment.recruitGirls = function recruitGirls(slave) {
 						seed += 2;
 						FSdefend++;
 						arcology.FSSlaveProfessionalism += 0.01 * V.FSSingleSlaveRep * FSIntMod;
-					} else if (slave.skill.entertainment + slave.skill.whoring + slave.skill.oral + slave.skill.anal + slave.skill.vaginal >= 400) {
+					} else if (slave.skill.entertainment + slave.skill.whoring + slave.skill.oral + slave.skill.anal + slave.skill.vaginal + slave.skill.penetrative >= 400) {
 						pushFS(`${He} participates in a weekly article showcasing skills every slave needs. However, only being able to recite learned information limits ${him}.`);
 						seed += 1;
 					} else {
diff --git a/src/endWeek/saRelationships.js b/src/endWeek/saRelationships.js
index 03f06324888eace4124a9893ab261acde37b8dd6..58c3399515a74066ebc2096f1cf08f0a01896d58 100644
--- a/src/endWeek/saRelationships.js
+++ b/src/endWeek/saRelationships.js
@@ -1097,7 +1097,7 @@ App.SlaveAssignment.relationships = function saRelationships(slave) {
 				}
 			}
 			if (lover.actualAge - slave.actualAge > 10 && slave.relationship >= 4 && random(1, 300) > (slave.intelligence + slave.intelligenceImplant + lover.intelligence + lover.intelligenceImplant) && lover.devotion > 75 && lover.trust > 50 && (lover.intelligence + lover.intelligenceImplant > 15) && (slave.devotion > 20 || (slave.devotion >= -20 && slave.trust < -20) || slave.trust > -10)) {
-				if ((lover.skill.oral > slave.skill.oral) || (lover.skill.anal > slave.skill.anal) || (lover.skill.vaginal > slave.skill.vaginal && slave.vagina >= 0 && lover.vagina >= 0) || (lover.trust > slave.trust)) {
+				if ((lover.skill.oral > slave.skill.oral) || (lover.skill.anal > slave.skill.anal) || (lover.skill.vaginal > slave.skill.vaginal && slave.vagina >= 0 && lover.vagina >= 0) || (lover.skill.penetrative > slave.skill.penetrative && canPenetrate(slave) && (lover.vagina > 0 || lover.anus > 0)) || (lover.trust > slave.trust)) {
 					r.push(`${slave.slaveName}'s`);
 					if (slave.relationship >= 5) {
 						r.push(`${wife2}`);
@@ -1108,15 +1108,24 @@ App.SlaveAssignment.relationships = function saRelationships(slave) {
 					if (lover.skill.oral > slave.skill.oral) {
 						r.push(`better at blowjobs than ${he} is. They are such good slaves that the senior ${girl2} serves as a mentor to the junior, improving ${his} oral skills.`);
 						r.push(slaveSkillIncrease('oral', slave, 5));
-					} else if (lover.skill.anal > slave.skill.anal) {
-						r.push(`better at`);
-						if (lover.anus > 0) {
-							r.push(`taking a buttfuck`);
+					} else if (lover.skill.penetrative > slave.skill.penetrative && canPenetrate(slave) && (lover.vagina > 0 || lover.anus > 0)) {
+						if (canPenetrate(lover)) {
+							r.push(`a better lover`);
+						} else if (lover.dick > 0) {
+							r.push(`better with ${his2} unusable dick`);
+						} else if (lover.clit >= 3) {
+							r.push(`better with ${his2} clit`);
 						} else {
-							r.push(`using ${his2} rear`);
+							r.push(`better with a strapon`);
 						}
-						r.push(`than ${he} is, and they are such good slaves that the senior ${girl2} serves as a mentor to the junior, improving ${his} anal skills.`);
-						r.push(slaveSkillIncrease('anal', slave, 5));
+						r.push(`than ${he}`);
+						if (canPenetrate(lover)) {
+							r.push(`is,`);
+						} else {
+							r.push(`is with ${his} cock,`);
+						}
+						r.push(`and they are such good slaves that the senior ${girl2} serves as a mentor to the junior, improving ${his} penetrative skills.`);
+						r.push(slaveSkillIncrease('penetrative', slave, 5));
 					} else if (lover.skill.vaginal > slave.skill.vaginal && slave.vagina > 0 && lover.vagina > 0) {
 						if (lover.vagina > 0) {
 							r.push(`a better lover`);
@@ -1131,6 +1140,15 @@ App.SlaveAssignment.relationships = function saRelationships(slave) {
 						}
 						r.push(`and they are such good slaves that the senior ${girl2} serves as a mentor to the junior, improving ${his} vaginal skills.`);
 						r.push(slaveSkillIncrease('vaginal', slave, 5));
+					} else if (lover.skill.anal > slave.skill.anal) {
+						r.push(`better at`);
+						if (lover.anus > 0) {
+							r.push(`taking a buttfuck`);
+						} else {
+							r.push(`using ${his2} rear`);
+						}
+						r.push(`than ${he} is, and they are such good slaves that the senior ${girl2} serves as a mentor to the junior, improving ${his} anal skills.`);
+						r.push(slaveSkillIncrease('anal', slave, 5));
 					} else if (lover.trust > slave.trust) {
 						r.push(`a better slave than ${he} is, and they are such obedient slaves that the senior ${girl2} serves as a mentor to the junior, <span class="trust inc">improving ${his} trust.</span>`);
 						slave.trust += 5;
diff --git a/src/endWeek/saServeThePublic.js b/src/endWeek/saServeThePublic.js
index 5b9bd4a3da7d6fc185a0fc0865694472d8d99d52..36588d64c7a339c5de8102a7dcf520e2d0e17b3b 100644
--- a/src/endWeek/saServeThePublic.js
+++ b/src/endWeek/saServeThePublic.js
@@ -495,7 +495,7 @@ App.SlaveAssignment.serveThePublic = function saServeThePublic(slave) {
 				slave.devotion += 4;
 			}
 		} else {
-			if ((slave.skill.oral + slave.skill.anal >= 200) && ((slave.skill.vaginal >= 100) || !canDoVaginal(slave))) {
+			if ((slave.skill.oral >= 100) && ((slave.skill.anal >= 100) || !canDoAnal(slave)) && ((slave.skill.vaginal >= 100) || !canDoVaginal(slave)) && (slave.skill.penetrative >= 100 && canPenetrate(slave))) {
 				r += ` ${He}'s a <span class="slave skill">sexual master</span> `;
 				if (canDoVaginal(slave)) {
 					r += `whose`;
@@ -509,7 +509,17 @@ App.SlaveAssignment.serveThePublic = function saServeThePublic(slave) {
 					r += ` front hole, ${his}`;
 				}
 				r += ` charms are only for the <span class="green">most prominent citizens.</span> When ${he}'s not `;
-				if (canDoVaginal(slave) && jsRandom(1, 4) === 1) {
+				if (slave.sexAmount > 70 && jsRandom(1, 3) === 1) {
+					r += `getting gangbanged,`;
+				} else if (adjustedPenSkill(slave, true) >= 100 && canPenetrate(slave) && jsRandom(1, 3) === 1) {
+					r += `plunging ${his} `;
+					if (slave.prestige > 1 || slave.porn.prestige > 2) {
+						r += `coveted`;
+					} else {
+						r += `renowned`;
+					}
+					r += ` cock into some lucky hole,`;
+				} else if (canDoVaginal(slave) && jsRandom(1, 2) === 1) {
 					r += `pleasing high society with ${his} `;
 					if (slave.prestige > 1 || slave.porn.prestige > 2) {
 						r += `prestigious`;
@@ -517,17 +527,7 @@ App.SlaveAssignment.serveThePublic = function saServeThePublic(slave) {
 						r += `popular`;
 					}
 					r += ` pussy,`;
-				} else if (slave.sexAmount > 70 && jsRandom(1, 3) === 1) {
-					r += `getting gangbanged,`;
-				} else if (jsRandom(1, 2) === 1) {
-					r += `giving away one of ${his} `;
-					if (slave.prestige > 1 || slave.porn.prestige > 2) {
-						r += `famous`;
-					} else {
-						r += `top-tier`;
-					}
-					r += ` blowjobs,`;
-				} else {
+				} else if (jsRandom(1, 3) === 1 && canDoAnal(slave)) {
 					r += `providing free access to ${his} `;
 					if (slave.prestige > 1 || slave.porn.prestige > 2) {
 						r += `legendary`;
@@ -535,6 +535,14 @@ App.SlaveAssignment.serveThePublic = function saServeThePublic(slave) {
 						r += `notorious`;
 					}
 					r += ` anus,`;
+				} else {
+					r += `giving away one of ${his} `;
+					if (slave.prestige > 1 || slave.porn.prestige > 2) {
+						r += `famous`;
+					} else {
+						r += `top-tier`;
+					}
+					r += ` blowjobs,`;
 				}
 				r += ` ${he} offers personal training and sexual therapy.`;
 			} else {
@@ -553,6 +561,10 @@ App.SlaveAssignment.serveThePublic = function saServeThePublic(slave) {
 					skillIncrease = (5 + Math.floor((slave.intelligence + slave.intelligenceImplant) / 32) + V.analUseWeight);
 					r += ` ${slaveSkillIncrease('anal', slave, skillIncrease)}`;
 				}
+				if (canPenetrate(slave) || random(1, 100) < penetrativeSocialUse(slave)) {
+					skillIncrease = (5 + Math.floor((slave.intelligence + slave.intelligenceImplant) / 32) + V.penetrativeUseWeight);
+					r += ` ${slaveSkillIncrease('penetrative', slave, skillIncrease)}`;
+				}
 			}
 			if (!isAmputee(slave)) {
 				if (slave.skill.entertainment < 100) {
@@ -1298,22 +1310,25 @@ App.SlaveAssignment.serveThePublic = function saServeThePublic(slave) {
 			mammaryUse *= 2;
 		}
 		penetrativeUse = 0;
-		if (canDoVaginal(slave) && slave.clit > 1) {
+		if (canDoVaginal(slave) && slave.clit >= 3) {
 			penetrativeUse += (V.penetrativeUseWeight + (slave.skill.vaginal / 30) + slave.clit);
 		}
 		if (slave.dick && slave.chastityPenis !== 1) {
 			if (canPenetrate(slave)) {
-				penetrativeUse += (V.penetrativeUseWeight + slave.dick + Math.min(slave.balls, 10) / 4);
+				penetrativeUse += (V.penetrativeUseWeight + (slave.skill.penetrative / 30) + slave.dick + Math.min(slave.balls, 10) / 4);
 				if (slave.drugs === Drug.HYPERTESTICLE) {
 					penetrativeUse += Math.min(slave.balls, 5);
 				}
 			} else {
-				penetrativeUse += (V.penetrativeUseWeight + Math.min(slave.balls, 15) + Math.min(slave.balls, 10) / 8);
+				penetrativeUse += (V.penetrativeUseWeight + (slave.skill.penetrative / 30) + Math.min(slave.balls, 15) + Math.min(slave.balls, 10) / 8);
 				if (slave.drugs === Drug.HYPERTESTICLE) {
 					penetrativeUse += Math.min(slave.balls, 5);
 				}
 			}
 		}
+		if (penetrativeSocialUse(slave) >= 20) {
+			penetrativeUse += Math.random(0, V.penetrativeUseWeight + (slave.skill.penetrative / 30));
+		}
 
 		const demand = (oralUse + analUse + vaginalUse + mammaryUse + penetrativeUse);
 
@@ -1395,6 +1410,10 @@ App.SlaveAssignment.serveThePublic = function saServeThePublic(slave) {
 								slave.need -= analUse;
 							}
 						}
+						if (penetrativeUse > 0 && isVirile(slave) && canPenetrate(slave)) {
+							r += ` ${He} got special sexual satisfaction from the times this week that ${he} wasn't required to wear a condom before dumping ${his} load in someone.`;
+							slave.need -= Math.max(1, penetrativeUse * .5);
+						}
 						break;
 					case Fetish.HUMILIATION:
 						r += ` ${He} enjoys the humiliation of being a public slut, and got a bit of sexual satisfaction from every sex act ${he} performed this week.`;
diff --git a/src/endWeek/saServeYourOtherSlaves.js b/src/endWeek/saServeYourOtherSlaves.js
index 07b3b403eef9345d5dc4862264f9a6a941273660..150c8189db7aefd23925e21184c78f027996877b 100644
--- a/src/endWeek/saServeYourOtherSlaves.js
+++ b/src/endWeek/saServeYourOtherSlaves.js
@@ -1225,7 +1225,7 @@ App.SlaveAssignment.serveYourOtherSlaves = function saServeYourOtherSlaves(slave
 					r.push(`Since ${domName} loves hard cocks, ${subName} finds ${himself} being sucked, groped, and toyed with. ${He} spends the week complying with ${domName}'s amusements. <span class="hotpink">${domName} enjoys having a nice dick right at hand,</span> even if it's too big to fit in ${him}.`);
 				} else {
 					r.push(`Since ${domName} loves hard cocks, ${subName} finds ${himself} being sucked, groped, and played with until ${he} comes. ${He} spends the week enjoying with ${domName}'s little games. <span class="hotpink">${domName} enjoys having a nice dick right at hand,</span> even if it's too big to fit in ${him}.`);
-				}			
+				}
 			} else if (slave.dick > 6 && slave.balls > 0) {
 				if (slave.devotion < -20) {
 					r.push(`Since ${domName} loves cocks, even big soft ones, ${subName} finds ${himself} being sucked, groped, and cruelly taunted for ${his} inability to get hard. ${He} spends the week trying to avoid ${domName}'s abuse of ${his} poor oversized penis. <span class="hotpink">${domName} enjoys having a nice dick right at hand,</span> even if it's only good for taunting and torture.`);
@@ -1811,14 +1811,14 @@ App.SlaveAssignment.serveYourOtherSlaves = function saServeYourOtherSlaves(slave
 
 	/**
 	 * @param {App.Entity.SlaveState} slave
-	 * @param {"oral"|"vaginal"|"anal"} skillName
-	 * @param {number} skillValue
+	 * @param {"oral"|"vaginal"|"anal"|"penetrative"} skillName
+	 * @param {number} skillUse
 	 */
-	function increaseSkillFromCumdump(slave, skillName, skillValue) {
-		if (skillValue < 30) {
-			r.push(slaveSkillIncrease(skillName, slave, (Math.floor((oralUse / 2) + Math.floor((slave.intelligence + slave.intelligenceImplant) / 32)))));
-		} else if (skillValue < 100) {
-			r.push(slaveSkillIncrease(skillName, slave, (Math.floor((oralUse / 4) + Math.floor((slave.intelligence + slave.intelligenceImplant) / 32)))));
+	function increaseSkillFromCumdump(slave, skillName, skillUse) {
+		if (slave.skill[skillName] < 30) {
+			r.push(slaveSkillIncrease(skillName, slave, (Math.floor((skillUse / 2) + Math.floor((slave.intelligence + slave.intelligenceImplant) / 32)))));
+		} else if (slave.skill[skillName] < 100) {
+			r.push(slaveSkillIncrease(skillName, slave, (Math.floor((skillUse / 4) + Math.floor((slave.intelligence + slave.intelligenceImplant) / 32)))));
 		}
 	}
 
@@ -1827,16 +1827,23 @@ App.SlaveAssignment.serveYourOtherSlaves = function saServeYourOtherSlaves(slave
 	 */
 	function slaveSkills(slave) {
 		if (jobType === "stud") {
-			// Penetrative skill goes here.
+			if (slave.fuckdoll === 0 && slave.fetish !== Fetish.MINDBROKEN) {
+				if (slave.career === "a breeding bull" || slave.devotion > 20) {
+					r.push(slaveSkillIncrease("penetrative", slave, 2));
+				}
+			}
 		} else if (jobType === "cumdump") {
 			if (oralUse > 0) {
-				increaseSkillFromCumdump(slave, "oral", slave.skill.oral);
+				increaseSkillFromCumdump(slave, "oral", oralUse);
 			}
 			if (vaginalUse > 0) {
-				increaseSkillFromCumdump(slave, "vaginal", slave.skill.vaginal);
+				increaseSkillFromCumdump(slave, "vaginal", vaginalUse);
 			}
 			if (analUse > 0) {
-				increaseSkillFromCumdump(slave, "anal", slave.skill.anal);
+				increaseSkillFromCumdump(slave, "anal", analUse);
+			}
+			if (penetrativeUse > 0) {
+				increaseSkillFromCumdump(slave, "penetrative", penetrativeUse);
 			}
 		} else if (jobType === "sub") {
 			const {his2} = getPronouns(domSlave).appendSuffix('2');
@@ -1865,6 +1872,14 @@ App.SlaveAssignment.serveYourOtherSlaves = function saServeYourOtherSlaves(slave
 						r.push(slaveSkillIncrease('anal', slave, (Math.floor((analUse / 2) + Math.floor((slave.intelligence + slave.intelligenceImplant) / 32)))));
 					}
 				}
+				if (penetrativeUse > 0) {
+					if (slave.skill.penetrative < domSlave.skill.penetrative) {
+						r.push(`${domName} is better at fucking others than ${subName} is, so ${he2} gives ${him} some pointers to improve ${his} skills.`);
+						r.push(slaveSkillIncrease('penetrative', slave, (Math.floor(penetrativeUse + Math.floor(slave.intelligence + slave.intelligenceImplant) / 32))));
+					} else if (slave.skill.penetrative < 30) {
+						r.push(slaveSkillIncrease('penetrative', slave, (Math.floor((penetrativeUse / 2) + Math.floor((slave.intelligence + slave.intelligenceImplant) / 32)))));
+					}
+				}
 			}
 		}
 	}
diff --git a/src/endWeek/saSocialEffects.js b/src/endWeek/saSocialEffects.js
index 1e6005f76133dd36254bfd1e3b6b31f2810cd6bd..e870ab5c6a88a2373539116ac400ff85086c9a91 100644
--- a/src/endWeek/saSocialEffects.js
+++ b/src/endWeek/saSocialEffects.js
@@ -588,7 +588,7 @@ App.SlaveAssignment.saSocialEffects = function(slave) {
 				t.push(new SocialEffect("Slave Professionalism", -2, `Can't speak ${V.language} or be silent`,
 					`Society <span class="red">dislikes</span> ${slave.slaveName}'s inability to properly speak ${V.language} or hold ${his} tongue; allowing such a flaw hinders the notion of professional slavery.`));
 			}
-			if (slave.skill.entertainment + slave.skill.whoring + slave.skill.oral + slave.skill.anal + slave.skill.vaginal >= 400) {
+			if (slave.skill.entertainment + slave.skill.whoring + slave.skill.oral + slave.skill.anal + slave.skill.vaginal + adjustedPenSkill(slave) >= 400) {
 				t.push(new SocialEffect("Slave Professionalism", 1, `Highly skilled`,
 					`Society <span class="green">appreciates</span> a slave with skills of ${slave.slaveName}'s caliber.`));
 			}
@@ -651,7 +651,7 @@ App.SlaveAssignment.saSocialEffects = function(slave) {
 				t.push(new SocialEffect("Body Purist", 1, `Makeup-free beauty`,
 					`Society <span class="green">approves</span> of keeping ${his} naturally beautiful face makeup-free.`));
 			} else if (slave.makeup > 1) {
-				t.push(new SocialEffect("Body Purist", 1, `Heavy makeup`,
+				t.push(new SocialEffect("Body Purist", -1, `Heavy makeup`,
 					`Society <span class="red">disapproves</span> of ${his} heavy makeup, which covers up ${his} natural features.`));
 			}
 		} else if (FutureSocieties.isActive('FSTransformationFetishist')) {
diff --git a/src/endWeek/saTakeClasses.js b/src/endWeek/saTakeClasses.js
index 5503d872f56cadd609c4e90c293b3cda09a69f07..792d5f30567ba266bb8d3aea9457fb5f99e583ea 100644
--- a/src/endWeek/saTakeClasses.js
+++ b/src/endWeek/saTakeClasses.js
@@ -337,6 +337,12 @@ App.SlaveAssignment.takeClasses = function saTakeClasses(slave) {
 			} else if (slave.skill.anal <= 10 && slave.anus >= 0) {
 				set.add(`Since ${he} is a novice at taking it up ${his} butt and not permitted to learn through practice, ${he} is taught relaxation exercises and other simple anal basics.`);
 				set.add(slaveSkillIncrease('anal', slave, skillIncrease));
+			} else if (slave.skill.penetrative <= 10 && penetrativeSocialUse() >= 40 && (canPenetrate(slave) || slave.clit >= 3)) {
+				set.add(`Since ${he} is a novice at using ${his} ${slave.clit < 3 ? "dick" : "phallic clit"}, ${he} is taught the basics of foreplay, insertion and movement.`);
+				set.add(slaveSkillIncrease('penetrative', slave, skillIncrease));
+			} else if (slave.skill.penetrative <= 10 && penetrativeSocialUse() >= 40) {
+				set.add(`Since ${he} is a novice at penetrating others with a phallus, ${he} is taught the basics of foreplay, insertion and movement.`);
+				set.add(slaveSkillIncrease('penetrative', slave, skillIncrease));
 			} else if (slave.skill.whoring <= 10) {
 				set.add(`Since ${he} has little idea what's involved in selling ${his} body, ${he} is taught basic safety practices and other simple prostitution skills.`);
 				set.add(slaveSkillIncrease('whoring', slave, skillIncrease));
@@ -359,6 +365,9 @@ App.SlaveAssignment.takeClasses = function saTakeClasses(slave) {
 				} else if (slave.skill.anal <= 30) {
 					set.add(`Having completed the basic sex slave curriculum, ${he} studies more advanced techniques and exotic positions to make use of ${his} ${(slave.anus === 0) ? `virgin ass for use in ${his} first time` : `ass`}.`);
 					set.add(slaveSkillIncrease('anal', slave, skillIncrease));
+				} else if (slave.skill.penetrative <= 30 && penetrativeSocialUse() >= 40) {
+					set.add(`Having completed the basic sex slave curriculum, ${he} studies more advanced techniques and exotic positions to ${canPenetrate(slave) ? `make use of ${his} penis` : `better penetrate others`}.`);
+					set.add(slaveSkillIncrease('penetrative', slave, skillIncrease));
 				}
 			}
 		}
@@ -769,6 +778,9 @@ App.SlaveAssignment.takeClasses = function saTakeClasses(slave) {
 		if (slave.vagina >= 0 && (slave.skill.vaginal <= 10 || (V.schoolroomUpgradeSkills > 0 && slave.skill.vaginal <= 30))) {
 			return;
 		}
+		if (penetrativeSocialUse() >= 40 && (slave.skill.penetrative <= 10 || (V.schoolroomUpgradeSkills > 0 && slave.skill.penetrative <= 30))) {
+			return;
+		}
 		if (needsTutoring(slave)) {
 			return;
 		}
diff --git a/src/endWeek/saWhore.js b/src/endWeek/saWhore.js
index 5d62b91610c5169362abc9c676601eb77f178334..48066543f149cf2a2dff39df484c01fc4845bc6b 100644
--- a/src/endWeek/saWhore.js
+++ b/src/endWeek/saWhore.js
@@ -397,43 +397,53 @@ App.SlaveAssignment.whore = function(slave) {
 			} else {
 				let canA = canDoAnal(slave) ? 1 : 0;
 				let canV = canDoVaginal(slave) ? 1 : 0;
+				let canP = canPenetrate(slave) && penetrativeSocialUse(slave) >= 40 ? 1 : 0;
 				let skillTarget = 100 +
 					(
-						(slave.skill.anal - 100) * canA * (1.5 - 0.5 * canV) +
-						(slave.skill.vaginal - 100) * canV * (1.5 - 0.5 * canA) +
-						(slave.skill.oral - 100) * (3 - 1.5 * canA - 1.5 * canV + canA * canV)
-					) * 3 / 10;
+						(slave.skill.anal - 100) * canA * [0, 6, 4, 3][canA + canV + canP] + // 100 -> 0, 600, 400, 300
+						(slave.skill.vaginal - 100) * canV * [0, 6, 4, 3][canA + canV + canP] + // 100 -> 0, 600, 400, 300
+						(slave.skill.penetrative - 100) * canP * [0, 6, 4, 3][canA + canV + canP] + // 100 -> 0, 600, 400, 300
+						(slave.skill.oral - 100) * [12, 6, 4, 3][canA + canV + canP] // 100 -> 1200, 600, 400, 300
+					) / 120;
 				// Complicated, I know - but it should automatically account for what acts are possible to scale the injury risk smoothly between 90% when totally unskilled
 				// and 0% when perfectly skilled in the relevant method or methods.
 
 				if (jsRandom(1, 100) > skillTarget) {
-					healthDamage(slave, 10 - 7 * canA * canV);		// Any limitations means an injury inflicts the harsher 10 instead of 3
+					healthDamage(slave, 10 - 7 * canA * (canV | canP));		// Any limitations means an injury inflicts the harsher 10 instead of 3
 					injury = 1;
 				}
 
-				if (slave.vagina < 0) {
-					if (!injury) {
-						r += ` ${He}'s such an expert whore that ${he} copes with the stress of being a ${SlaveTitle(slave)} slut.`;
-					} else {
-						r += ` The stress of being a ${SlaveTitle(slave)} prostitute is <span class="health dec">hard on ${him}.</span>`;
-					}
-				} else if (!canV && canA) {
-					if (!injury) {
-						r += ` ${He}'s such an expert whore that ${he} copes with the stress of being limited to buttsex and oral.`;
-					} else {
-						r += ` The stress of being limited to buttsex and oral is <span class="health dec">hard on ${him}.</span>`;
-					}
-				} else if (!canA && canV) {
-					if (!injury) {
-						r += ` ${He}'s such an expert whore that ${he} copes with the stress of being limited to vaginal and oral.`;
-					} else {
-						r += ` The stress of being limited to vaginal and oral is <span class="health dec">hard on ${him}.</span>`;
-					}
-				} else if (!canA && !canV) {
-					if (!injury) {
-						r += ` ${He}'s such an expert whore that ${he} copes with the stress of being limited to oral.`;
-					} else {
-						r += ` The stress of being limited to oral sex is <span class="health dec">hard on ${him}.</span>`;
+				if (canA + canV + canP < 2){
+					if (slave.vagina < 0) {
+						if (!injury) {
+							r += ` ${He}'s such an expert whore that ${he} copes with the stress of being a ${SlaveTitle(slave)} slut.`;
+						} else {
+							r += ` The stress of being a ${SlaveTitle(slave)} prostitute is <span class="health dec">hard on ${him}.</span>`;
+						}
+					} else if (canA) {
+						if (!injury) {
+							r += ` ${He}'s such an expert whore that ${he} copes with the stress of being limited to buttsex and oral.`;
+						} else {
+							r += ` The stress of being limited to buttsex and oral is <span class="health dec">hard on ${him}.</span>`;
+						}
+					} else if (canV) {
+						if (!injury) {
+							r += ` ${He}'s such an expert whore that ${he} copes with the stress of being limited to vaginal and oral.`;
+						} else {
+							r += ` The stress of being limited to vaginal and oral is <span class="health dec">hard on ${him}.</span>`;
+						}
+					} else if (canP) {
+						if (!injury) {
+							r += ` ${He}'s such an expert whore that ${he} copes with the stress of being limited to penetrative and oral.`;
+						} else {
+							r += ` The stress of being limited to penetrative and oral is <span class="health dec">hard on ${him}.</span>`;
+						}
+					} else if (canA + canV + canP === 0) {
+						if (!injury) {
+							r += ` ${He}'s such an expert whore that ${he} copes with the stress of being limited to oral.`;
+						} else {
+							r += ` The stress of being limited to oral sex is <span class="health dec">hard on ${him}.</span>`;
+						}
 					}
 				}
 			}
@@ -610,6 +620,14 @@ App.SlaveAssignment.whore = function(slave) {
 						r += `popular`;
 					}
 					r += ` pussy,`;
+				} else if (adjustedPenSkill(slave, true) >= 100 && canPenetrate(slave) && jsRandom(1, 3) === 1) {
+					r += `plunging ${his} `;
+					if (slave.prestige > 1 || slave.porn.prestige > 2) {
+						r += `coveted`;
+					} else {
+						r += `renowned`;
+					}
+					r += ` cock into some wealthy hole,`;
 				} else if (beauty > 70 && jsRandom(1, 3) === 1) {
 					r += `getting gangbanged,`;
 				} else if (jsRandom(1, 2) === 1) {
@@ -648,6 +666,10 @@ App.SlaveAssignment.whore = function(slave) {
 					skillIncrease = (5 + Math.floor((slave.intelligence + slave.intelligenceImplant) / 32) + V.analUseWeight);
 					r += ` ${slaveSkillIncrease('anal', slave, skillIncrease)}`;
 				}
+				if (canPenetrate(slave) || random(1, 100) < penetrativeSocialUse(slave)) {
+					skillIncrease = (5 + Math.floor((slave.intelligence + slave.intelligenceImplant) / 32) + V.penetrativeUseWeight);
+					r += ` ${slaveSkillIncrease('penetrative', slave, skillIncrease)}`;
+				}
 			}
 		}
 	}
@@ -1382,22 +1404,25 @@ App.SlaveAssignment.whore = function(slave) {
 			mammaryUse *= 2;
 		}
 		penetrativeUse = 0;
-		if (canDoVaginal(slave) && slave.clit > 1) {
+		if (canDoVaginal(slave) && slave.clit >= 3) {
 			penetrativeUse += (V.penetrativeUseWeight + (slave.skill.vaginal / 30) + slave.clit);
 		}
 		if (slave.dick && slave.chastityPenis !== 1) {
 			if (canPenetrate(slave)) {
-				penetrativeUse += (V.penetrativeUseWeight + slave.dick + Math.min(slave.balls, 10) / 4);
+				penetrativeUse += (V.penetrativeUseWeight + (slave.skill.penetrative / 30) + slave.dick + Math.min(slave.balls, 10) / 4);
 				if (slave.drugs === Drug.HYPERTESTICLE) {
 					penetrativeUse += Math.min(slave.balls, 5);
 				}
 			} else {
-				penetrativeUse += (V.penetrativeUseWeight + Math.min(slave.balls, 15) + Math.min(slave.balls, 10) / 8);
+				penetrativeUse += (V.penetrativeUseWeight + (slave.skill.penetrative / 30) + Math.min(slave.balls, 15) + Math.min(slave.balls, 10) / 8);
 				if (slave.drugs === Drug.HYPERTESTICLE) {
 					penetrativeUse += Math.min(slave.balls, 5);
 				}
 			}
 		}
+		if (penetrativeSocialUse(slave) >= 20) {
+			penetrativeUse += Math.random(0, V.penetrativeUseWeight + (slave.skill.penetrative / 30));
+		}
 
 		const demand = (oralUse + analUse + vaginalUse + mammaryUse + penetrativeUse);
 		oralUse = Math.trunc((oralUse / demand) * beauty);
@@ -1478,6 +1503,10 @@ App.SlaveAssignment.whore = function(slave) {
 								slave.need -= analUse;
 							}
 						}
+						if (penetrativeUse > 0 && isVirile(slave) && canPenetrate(slave)) {
+							r += ` ${He} got special sexual satisfaction from the times this week that ${he} wasn't required to wear a condom before dumping ${his} load in someone.`;
+							slave.need -= Math.max(1, penetrativeUse * .5);
+						}
 						break;
 					case Fetish.HUMILIATION:
 						r += ` ${He} enjoys the humiliation of being a whore, and got a bit of sexual satisfaction from every sex act ${he} performed this week.`;
diff --git a/src/endWeek/slaveAssignmentReport.js b/src/endWeek/slaveAssignmentReport.js
index b8e0ecb48dd66028cd127ceeedae489e4d045954..9b84a1bac7403856b70933823f3ce3843df2778f 100644
--- a/src/endWeek/slaveAssignmentReport.js
+++ b/src/endWeek/slaveAssignmentReport.js
@@ -21,7 +21,8 @@ App.EndWeek.slaveAssignmentReport = function() {
 		entertainment: "entertain",
 		vaginal: "vaginal",
 		anal: "anal",
-		oral: "oral"
+		oral: "oral",
+		penetrative: "penetrative"
 	};
 
 	const res = document.createDocumentFragment();
diff --git a/src/events/JE/jeSlaveDisputeBreedingDeal.js b/src/events/JE/jeSlaveDisputeBreedingDeal.js
index 556b0fe74b15a04b44b952ee8fcfb78f8ff02f1d..d050a8cb1f67a3c1749ab954d012f1b412730af9 100644
--- a/src/events/JE/jeSlaveDisputeBreedingDeal.js
+++ b/src/events/JE/jeSlaveDisputeBreedingDeal.js
@@ -28,6 +28,7 @@ App.Events.JESlaveDisputeBreedingDeal = class JESlaveDisputeBreedingDeal extends
 		slave.skill.oral = 0;
 		slave.skill.whoring = 0;
 		slave.skill.vaginal = 0;
+		slave.skill.penetrative = 0;
 		slave.skill.entertainment = 0;
 		slave.bellySag = 10;
 		slave.bellySagPreg = 10;
diff --git a/src/events/JE/jeSlaveDisputeIndentureDeal.js b/src/events/JE/jeSlaveDisputeIndentureDeal.js
index 76b3adc83f09a4fd0bea912f3ee40b90eb15499c..0171075c2766a898395466e55c2d2309e8642166 100644
--- a/src/events/JE/jeSlaveDisputeIndentureDeal.js
+++ b/src/events/JE/jeSlaveDisputeIndentureDeal.js
@@ -22,6 +22,9 @@ App.Events.JESlaveDisputeIndentureDeal = class JESlaveDisputeIndentureDeal exten
 			slave.vagina = 2;
 		}
 		slave.skill.vaginal = 15;
+		if (slave.dick > 0 || slave.clit >= 3) {
+			slave.skill.penetrative = 15;
+		}
 		slave.skill.oral = 15;
 		slave.skill.anal = 15;
 		slave.skill.whoring = 0;
diff --git a/src/events/JE/jeSlaveDisputeMajorityDeal.js b/src/events/JE/jeSlaveDisputeMajorityDeal.js
index 8e60fd9db44afb0d2e7c0fdcae7e62fc01f80d56..0c3350c85baf9929e3ed72bc2e2644b153591d80 100644
--- a/src/events/JE/jeSlaveDisputeMajorityDeal.js
+++ b/src/events/JE/jeSlaveDisputeMajorityDeal.js
@@ -32,6 +32,7 @@ App.Events.JESlaveDisputeMajorityDeal = class JESlaveDisputeMajorityDeal extends
 		slave.skill.oral = 0;
 		slave.skill.whoring = 0;
 		slave.skill.vaginal = 0;
+		slave.skill.penetrative = 0;
 		slave.skill.entertainment = 0;
 
 		const {
diff --git a/src/events/JE/jeSlaveDisputeSlaveTraining.js b/src/events/JE/jeSlaveDisputeSlaveTraining.js
index d4e025b43be7b5083306e0272c1ee505c06990af..1806fe7943fc3e4660b05289f7875b995189c941 100644
--- a/src/events/JE/jeSlaveDisputeSlaveTraining.js
+++ b/src/events/JE/jeSlaveDisputeSlaveTraining.js
@@ -25,6 +25,7 @@ App.Events.JESlaveDisputeSlaveTraining = class JESlaveDisputeSlaveTraining exten
 		setHealth(slave, jsRandom(60, 80), 0, 0, 0, jsRandom(10, 30));
 		slave.balls = 0;
 		slave.anus = 2;
+		slave.skill.penetrative = 35;
 		slave.skill.anal = 35;
 		slave.skill.oral = 35;
 		slave.skill.whoring = 35;
diff --git a/src/events/PESS/pessMadamStrategy.js b/src/events/PESS/pessMadamStrategy.js
index 1183a763885beb6a6ab0e8793683f3754d4b3622..ad7c7a54144ff644624462a94c0d6e8b255416b0 100644
--- a/src/events/PESS/pessMadamStrategy.js
+++ b/src/events/PESS/pessMadamStrategy.js
@@ -33,10 +33,12 @@ App.Events.pessMadamStrategy = class pessMadamStrategy extends App.Events.BaseEv
 				if (slave.assignment === Job.BROTHEL) {
 					if (slave.skill.oral < 100) {
 						slave.skill.oral += 5;
-					} else if (slave.skill.anal < 100) {
-						slave.skill.anal += 5;
 					} else if (slave.skill.vaginal < 100 && slave.vagina > 0) {
 						slave.skill.vaginal += 5;
+					} else if (slave.skill.anal < 100) {
+						slave.skill.anal += 5;
+					} else if (slave.skill.penetrative < 100 && penetrativeSocialUse(slave) >= 40) {
+						slave.skill.penetrative += 5;
 					}
 				}
 			}
diff --git a/src/events/RE/reCelebrityDebt.js b/src/events/RE/reCelebrityDebt.js
index 3db5ac9cb3306dd086936b9d7e2b5c1181fb30cf..a560523099230ae9772fc8db89f3764b3574ccb4 100644
--- a/src/events/RE/reCelebrityDebt.js
+++ b/src/events/RE/reCelebrityDebt.js
@@ -95,6 +95,9 @@ App.Events.RECelebrityAddictionDebt = class RECelebrityAddictionDebt extends App
 				slave.skill.vaginal = random(31, 70);
 			}
 			slave.skill.oral = random(31, 70);
+			if (slave.dick > 0) {
+				slave.skill.penetrative = jsRandom(31, 70);
+			}
 			if (slave.anus !== 0) {
 				slave.skill.anal = random(31, 70);
 			}
diff --git a/src/events/RE/reMalefactor.js b/src/events/RE/reMalefactor.js
index 99e30bc54c62f782f48e1db3613e3ad34744157d..3224f3b62594ab37f27fcb2391b15652a13c9a48 100644
--- a/src/events/RE/reMalefactor.js
+++ b/src/events/RE/reMalefactor.js
@@ -638,10 +638,12 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent {
 						slave.balls = 0;
 						slave.vagina = 2;
 						slave.skill.vaginal = 15;
+						slave.skill.penetrative = 0;
 					} else {
 						slave.ovaries = 0;
 						slave.clit = 0;
 						slave.skill.vaginal = 0;
+						slave.skill.penetrative = 15;
 					}
 					slave.skill.oral = 15;
 					slave.skill.anal = 35;
@@ -667,12 +669,14 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent {
 						slave.balls = 0;
 						slave.vagina = 2;
 						slave.skill.vaginal = 15;
+						slave.skill.penetrative = 0;
 					} else {
 						slave.dick = random(4, 5);
 						slave.balls = random(0, 2);
 						slave.ovaries = 0;
 						slave.clit = 0;
 						slave.skill.vaginal = 0;
+						slave.skill.penetrative = 15;
 					}
 					slave.skill.oral = 0;
 					slave.skill.anal = 0;
@@ -706,6 +710,7 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent {
 					slave.skill.vaginal = 30;
 					slave.skill.oral = 15;
 					slave.skill.anal = 15;
+					slave.skill.penetrative = 0;
 					slave.sexualFlaw = "crude";
 					slave.behavioralFlaw = "bitchy";
 					break;
@@ -732,6 +737,7 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent {
 						slave.clit = 0;
 					}
 					slave.skill.vaginal = 0;
+					slave.skill.penetrative = 0;
 					slave.skill.oral = 0;
 					slave.skill.anal = 0;
 					slave.skill.whoring = 0;
@@ -779,6 +785,7 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent {
 						slave.vagina = 2;
 						slave.skill.vaginal = 35;
 					}
+					slave.skill.penetrative = 15;
 					slave.skill.oral = 35;
 					slave.skill.anal = 35;
 					slave.skill.whoring = 35;
@@ -810,6 +817,7 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent {
 					setHealth(slave, jsRandom(0, 20), undefined, undefined, 0, 5);
 					slave.anus = 0;
 					slave.balls = random(2, 4);
+					slave.skill.penetrative = 35;
 					slave.skill.oral = 0;
 					slave.skill.anal = 0;
 					slave.behavioralFlaw = "arrogant";
@@ -833,6 +841,7 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent {
 					slave.pubicHStyle = "shaved";
 					slave.bellySag = 2;
 					slave.skill.vaginal = 50;
+					slave.skill.penetrative = 0;
 					slave.anus = 0;
 					slave.hips = 0;
 					slave.weight = -60;
@@ -856,6 +865,7 @@ App.Events.REMalefactor = class REMalefactor extends App.Events.BaseEvent {
 					slave.weight = random(-20, 30);
 					slave.waist = random(-10, 10);
 					slave.skill.vaginal = 0;
+					slave.skill.penetrative = 0;
 					slave.skill.oral = 0;
 					slave.skill.anal = 0;
 					slave.skill.whoring = 0;
diff --git a/src/events/RE/reNickname.js b/src/events/RE/reNickname.js
index 10bc7a2909b76019c833ad377278555d078ae8f2..3a82d7592579c07fe7f4f1e9c3b09154ceffd1f2 100644
--- a/src/events/RE/reNickname.js
+++ b/src/events/RE/reNickname.js
@@ -1196,6 +1196,14 @@ App.Events.RENickname = class RENickname extends App.Events.BaseEvent {
 				notApplyDesc: `understands that what matters is not what ${he} did yesterday, or how much they liked it, but what ${he} does today, and how much they like it.`,
 			});
 		}
+		if (slave.skill.penetrative > 95 && canPenetrate(slave)) {
+			nickMap.set("gigolo", {
+				nicknameArray: ["Casanova", "Gigolo", "Lothario", "Stallion", "Stud"],
+				situationDesc: `knows how to put ${his} dick to good use. Men don't appreciate the competition, and most women would rather not be fucked by a slave, but it is a skill none-the-less.`,
+				applyDesc: `takes pride in ${his} new nickname and is thankful to be allowed to keep using ${his} cock; ${he} knows just how easily you can leave ${him} impotent should ${he} cross you.`,
+				notApplyDesc: `understands that, while ${his} skill may be valuable, they aren't special. With proper training, anyone could take ${his} place.`,
+			});
+		}
 		if (slave.breedingMark === 1 && V.propOutcome === 1 && FutureSocieties.isActive('FSRestart')) {
 			nickMap.set("mark", {
 				nicknameArray: ["Ass Kisser", "Breeder", "Chosen", "Conceited", "Connections", "Elite Breeder", "Elite", "Elitist", "Eugenicist", "Favors", "High and Mighty", "Lucky", "Mark", "Marked", "Nepotist", "Pedigree", "Privileged", "Special"],
diff --git a/src/events/RE/reRelativeRecruiter.js b/src/events/RE/reRelativeRecruiter.js
index 88b3e5b05fd95434cde644e1664e4da84c5c7d02..fdd01e2da1ba5992a6ffc0b886e3b71e677edf85 100644
--- a/src/events/RE/reRelativeRecruiter.js
+++ b/src/events/RE/reRelativeRecruiter.js
@@ -491,6 +491,7 @@ App.Events.RERelativeRecruiter = class RERelativeRecruiter extends App.Events.Ba
 					if (slave.dick.isBetween(0, 5)) {
 						slave.dick = 5;
 						slave.foreskin = slave.dick;
+						slave.skill.penetrative += jsRandom(0, 30);
 					}
 					if (slave.vagina > -1) {
 						slave.vagina = 2;
diff --git a/src/events/REFS/refsNeoImperialistFeast.js b/src/events/REFS/refsNeoImperialistFeast.js
index b1fd7f2bd770b6c884beb1f7510002a649ba1454..32bfcf9acf284bcb57fd99b81e824cc53cb89f80 100644
--- a/src/events/REFS/refsNeoImperialistFeast.js
+++ b/src/events/REFS/refsNeoImperialistFeast.js
@@ -29,6 +29,7 @@ App.Events.refsNeoImperialistFeast = class refsNeoImperialistFeast extends App.E
 		slave.weight = 0;
 		slave.intelligence = random(15, 100);
 		slave.skill.entertainment = 45;
+		slave.skill.penetrative = 0;
 		slave.skill.anal = 0;
 		slave.skill.oral = 0;
 		slave.skill.whoring = 0;
diff --git a/src/events/intro/acquisition.js b/src/events/intro/acquisition.js
index a96a13655b0943cd76b8432245d06ddeb58afef9..6f823db397bc1023be68da620ed1a10dd285a8a0 100644
--- a/src/events/intro/acquisition.js
+++ b/src/events/intro/acquisition.js
@@ -530,6 +530,7 @@ App.Intro.acquisition = function() {
 				slave.attrXY = random(70, 90);
 				slave.attrXX = 0;
 				slave.skill.oral = random(35, 65);
+				slave.skill.penetrative = random(35, 65);
 				slave.skill.anal = random(35, 65);
 				slave.skill.whoring = random(35, 65);
 				SoftenSexualFlaw(slave);
@@ -910,6 +911,9 @@ App.Intro.acquisition = function() {
 					}
 					slave.skill.vaginal = 100;
 				}
+				if (canAchieveErection(slave)) {
+					slave.skill.penetrative = 100;
+				}
 				slave.skill.entertainment = 100;
 				slave.skill.whoring = 100;
 				SoftenBehavioralFlaw(slave);
@@ -1017,6 +1021,9 @@ App.Intro.acquisition = function() {
 					slave.skill.vaginal = random(15, 35);
 					slave.vagina = 3;
 				}
+				if (canAchieveErection(slave)) {
+					slave.skill.penetrative = random(15, 35);
+				}
 				slave.skill.entertainment = 0;
 				slave.energy = random(60, 80);
 				slave.behavioralFlaw = "gluttonous";
@@ -1057,6 +1064,7 @@ App.Intro.acquisition = function() {
 				slave.skill.oral = 100;
 				slave.skill.anal = 100;
 				slave.skill.vaginal = 100;
+				slave.skill.penetrative = 100;
 				slave.skill.entertainment = 100;
 				slave.skill.whoring = 100;
 				slave.intelligence = 100;
diff --git a/src/events/nonRandom/mercs/pSlaveMedic.js b/src/events/nonRandom/mercs/pSlaveMedic.js
index 87ce8dec3cbba3286e89ad47150610600a83706e..4e3cad7ca87fe638dbb15c15cda7afc107665030 100644
--- a/src/events/nonRandom/mercs/pSlaveMedic.js
+++ b/src/events/nonRandom/mercs/pSlaveMedic.js
@@ -17,6 +17,7 @@ App.Events.PSlaveMedic = class PSlaveMedic extends App.Events.BaseEvent {
 			slave.scrotum = 3;
 			slave.butt = 3;
 			slave.attrXY = 70;
+			slave.skill.penetrative = 35;
 		} else {
 			slave = GenerateNewSlave("XX", genParam);
 			slave.vagina = 2;
diff --git a/src/events/nonRandom/mercs/pSnatchAndGrabResult.js b/src/events/nonRandom/mercs/pSnatchAndGrabResult.js
index 0dc2c17389181f5dc85b85db9de7b851307386ab..6ea82caeec07167fb70743c75a1506c3240ed500 100644
--- a/src/events/nonRandom/mercs/pSnatchAndGrabResult.js
+++ b/src/events/nonRandom/mercs/pSnatchAndGrabResult.js
@@ -66,6 +66,7 @@ App.Events.PSnatchAndGrabResult = class PSnatchAndGrabResult extends App.Events.
 		setHealth(snatched, 250, 0, 0, 0, 0);
 		snatched.face = 15;
 		snatched.skill.vaginal = 0;
+		snatched.skill.penetrative = 0;
 		snatched.skill.oral = 0;
 		snatched.skill.anal = 0;
 		snatched.skill.whoring = 0;
diff --git a/src/events/nonRandom/pAidResult.js b/src/events/nonRandom/pAidResult.js
index e8ed4a5fdeda7bcec37ba7af330a99c8fad75d8b..0942fb16dafda73716ff6db656136ff119c5ec27 100644
--- a/src/events/nonRandom/pAidResult.js
+++ b/src/events/nonRandom/pAidResult.js
@@ -58,6 +58,7 @@ App.Events.pAidResult = class pAidResult extends App.Events.BaseEvent {
 			slave.attrXY = random(10, 50);
 			slave.energy = random(60, 80);
 			slave.skill.vaginal = 0;
+			slave.skill.penetrative = 65;
 			slave.skill.oral = 35;
 			slave.skill.anal = 0;
 			slave.skill.whoring = 0;
@@ -84,6 +85,7 @@ App.Events.pAidResult = class pAidResult extends App.Events.BaseEvent {
 				slave.attrXY = random(10, 50);
 				slave.energy = random(5, 20);
 				slave.skill.vaginal = 0;
+				slave.skill.penetrative = 0;
 				slave.skill.oral = 15;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 0;
@@ -110,6 +112,7 @@ App.Events.pAidResult = class pAidResult extends App.Events.BaseEvent {
 			slave.attrXY = random(10, 50);
 			slave.energy = random(60, 80);
 			slave.skill.vaginal = 15;
+			slave.skill.penetrative = 15;
 			slave.skill.oral = 15;
 			slave.skill.anal = 15;
 			slave.skill.whoring = 0;
@@ -136,13 +139,14 @@ App.Events.pAidResult = class pAidResult extends App.Events.BaseEvent {
 				slave.attrXY = random(10, 70);
 				slave.energy = random(50, 70);
 				slave.skill.vaginal = 0;
+				slave.skill.penetrative = 0;
 				slave.skill.oral = 0;
 				slave.skill.anal = 15;
 				slave.skill.whoring = 0;
 				slave.skill.entertainment = 0;
 				slave.fetish = "buttslut";
 				slave.behavioralFlaw = either("anorexic", "arrogant", "bitchy");
-				slave.sexualFlaw = either("hates anal", "idealistic", "shamefast");
+				slave.sexualFlaw = either("hates oral", "idealistic", "shamefast");
 				newSlaves.push(slave);
 			}
 		} else if (V.eventResults.aidTarget === "maternity") {
@@ -213,6 +217,7 @@ App.Events.pAidResult = class pAidResult extends App.Events.BaseEvent {
 			slave.attrXY = 90;
 			slave.energy = random(30, 80);
 			slave.skill.oral = random(50, 100);
+			slave.skill.penetrative = random(50, 100);
 			slave.skill.anal = random(50, 100);
 			slave.skill.whoring = 0;
 			slave.skill.entertainment = random(15, 40);
@@ -235,6 +240,7 @@ App.Events.pAidResult = class pAidResult extends App.Events.BaseEvent {
 				slave.attrXY = random(60, 90);
 				slave.energy = random(30, 70);
 				slave.skill.oral = random(15, 40);
+				slave.skill.penetrative = random(15, 40);
 				slave.skill.anal = random(15, 40);
 				slave.skill.whoring = 0;
 				slave.skill.entertainment = 0;
diff --git a/src/events/nonRandom/rival/pRivalryActions.js b/src/events/nonRandom/rival/pRivalryActions.js
index 03d1efafd092d7f5c8a5d79d20246eb781245141..84f9b985527d4c3e5fc3504c3ff853254d71c615 100644
--- a/src/events/nonRandom/rival/pRivalryActions.js
+++ b/src/events/nonRandom/rival/pRivalryActions.js
@@ -830,6 +830,8 @@ App.Events.pRivalryActions = function() {
 						V.hostage.counter.anal += 10;
 						if (V.seeDicks !== 0) {
 							V.hostage.dick = 1;
+							V.hostage.skill.penetrative = Math.clamp(V.hostage.skill.penetrative + 5, 0, 100);
+							V.hostage.counter.penetrative += 10;
 						}
 						V.hostage.vaginaTat = "lewd crest";
 						V.hostage.behavioralFlaw = "none";
@@ -1086,6 +1088,7 @@ App.Events.pRivalryActions = function() {
 						V.hostage.skill.entertainment = 0;
 						V.hostage.skill.anal = 0;
 						V.hostage.skill.vaginal = 0;
+						V.hostage.skill.penetrative = 0;
 						V.hostage.skill.whoring = 0;
 						V.hostage.skill.combat = 0;
 						V.hostage.makeup = 4;
@@ -1252,6 +1255,8 @@ App.Events.pRivalryActions = function() {
 							V.hostage.dick = 3;
 							V.hostage.balls = 2;
 							V.hostage.scrotum = 1;
+							V.hostage.skill.penetrative = Math.clamp(V.hostage.skill.penetrative + 5, 0, 100);
+							V.hostage.counter.penetrative += 10;
 						}
 						V.hostage.fetishStrength = 100;
 						V.hostage.sexualFlaw = "anal addict";
@@ -1612,6 +1617,8 @@ App.Events.pRivalryActions = function() {
 							V.hostage.dick = 4;
 							V.hostage.balls = 4;
 							V.hostage.scrotum = 2;
+							V.hostage.skill.penetrative = Math.clamp(V.hostage.skill.penetrative + 5, 0, 100);
+							V.hostage.counter.penetrative += 10;
 						}
 						r.push(`giving an interview. ${He} gushes over how great it feels being fucked in the rear and how ${he} never has to worry about pregnancy that way. ${He} carries on about how terrible it is that some people want to deny people this great sensation.`);
 						break;
@@ -2241,6 +2248,8 @@ App.Events.pRivalryActions = function() {
 								hostageAction.push(`enjoying a hard anal pounding, ${his} tiny new penis swinging from the thrusts.`);
 								hostageAction.push(`letting off a moan as a penis slides into ${his} asspussy, ${his} tiny new penis trying to get hard.`);
 								hostageAction.push(`cleaning ${his} rear while fondling ${his} asspussy, ${his} other hand teasing ${his} new tiny penis.`);
+								V.hostage.skill.penetrative = Math.clamp(V.hostage.skill.penetrative + 5, 0, 100);
+								V.hostage.counter.penetrative += 10;
 							} else {
 								hostageAction.push(`enjoying a hard anal pounding.`);
 								hostageAction.push(`letting off a moan as a penis slides into ${his} asspussy.`);
@@ -2254,6 +2263,8 @@ App.Events.pRivalryActions = function() {
 								hostageAction.push(`orgasming immodestly to a hard anal pounding, ${his} erect penis cumming across ${his} belly.`);
 								hostageAction.push(`moaning lewdly as a huge dick slides up ${his} asspussy, ${his} erect penis bumping into ${his} belly.`);
 								hostageAction.push(`seeing how many fingers ${he} can fit into ${his} ass as ${he} showers, while teasing ${his} erect dick with the other hand.`);
+								V.hostage.skill.penetrative = Math.clamp(V.hostage.skill.penetrative + 5, 0, 100);
+								V.hostage.counter.penetrative += 10;
 							} else {
 								hostageAction.push(`orgasming immodestly to a hard anal pounding.`);
 								hostageAction.push(`moaning lewdly as a huge dick slides up ${his} asspussy.`);
@@ -2265,6 +2276,8 @@ App.Events.pRivalryActions = function() {
 								hostageAction.push(`happily taking two dicks at once in ${his} blown out anus, while stroking ${his} rock hard cock.`);
 								hostageAction.push(`getting assfucked, ${his} rock-hard cock dribbling precum everywhere. ${He} gasps with delight as ${he} feels a second hot shaft slide inside ${his} asspussy next to the first.`);
 								hostageAction.push(`fisting ${his} own ass in the shower, and jacking off to the prostrate stimulation. ${He} gasps with delight as an orgasm wracks ${his} body.`);
+								V.hostage.skill.penetrative = Math.clamp(V.hostage.skill.penetrative + 5, 0, 100);
+								V.hostage.counter.penetrative += 10;
 							} else {
 								hostageAction.push(`happily taking two dicks at once in ${his} blown out anus.`);
 								hostageAction.push(`getting assfucked. ${He} gasps with delight as ${he} feels a second hot shaft slide inside ${his} asspussy next to the first.`);
diff --git a/src/events/nonRandom/rival/pRivalryCapture.js b/src/events/nonRandom/rival/pRivalryCapture.js
index 55b6a321ee6c9fbac074e9afbe10cdb95eb0042f..ef7f3317931b68282d4983d907e0b3bc1e3391d9 100644
--- a/src/events/nonRandom/rival/pRivalryCapture.js
+++ b/src/events/nonRandom/rival/pRivalryCapture.js
@@ -123,6 +123,7 @@ globalThis.pRivalryCapture = function(condition) {
 				slave.anus = 3;
 				slave.vagina = -1;
 				slave.weight = 20;
+				slave.skill.penetrative = 100;
 				slave.skill.oral = 100;
 				slave.skill.anal = 100;
 				slave.skill.whoring = 15;
@@ -160,6 +161,7 @@ globalThis.pRivalryCapture = function(condition) {
 				slave.vagina = -1;
 				slave.weight = -35;
 				slave.skill.oral = 0;
+				slave.skill.penetrative = 100;
 				slave.skill.anal = 100;
 				slave.skill.whoring = 15;
 				slave.skill.entertainment = 100;
@@ -192,6 +194,7 @@ globalThis.pRivalryCapture = function(condition) {
 				slave.vagina = -1;
 				slave.weight = -35;
 				slave.skill.oral = 0;
+				slave.skill.penetrative = 100;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 0;
 				slave.skill.entertainment = 100;
@@ -226,6 +229,7 @@ globalThis.pRivalryCapture = function(condition) {
 				slave.vagina = -1;
 				slave.weight = 0;
 				slave.skill.vaginal = 0;
+				slave.skill.penetrative = 100;
 				slave.skill.oral = 15;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 0;
@@ -258,6 +262,7 @@ globalThis.pRivalryCapture = function(condition) {
 				slave.vagina = -1;
 				slave.weight = 100;
 				slave.skill.vaginal = 0;
+				slave.skill.penetrative = 10;
 				slave.skill.oral = 15;
 				slave.skill.anal = 15;
 				slave.skill.whoring = 0;
@@ -293,6 +298,7 @@ globalThis.pRivalryCapture = function(condition) {
 				slave.vagina = 1;
 				slave.preg = -1;
 				slave.skill.vaginal = 15;
+				slave.skill.penetrative = 65;
 				slave.skill.oral = 0;
 				slave.skill.anal = 15;
 				slave.skill.whoring = 0;
@@ -358,6 +364,7 @@ globalThis.pRivalryCapture = function(condition) {
 				slave.pregWeek = slave.preg;
 				SetBellySize(slave);
 				slave.skill.vaginal = 100;
+				slave.skill.penetrative = 0;
 				slave.skill.oral = 15;
 				slave.skill.anal = 15;
 				slave.skill.whoring = 35;
@@ -392,6 +399,7 @@ globalThis.pRivalryCapture = function(condition) {
 				slave.vagina = 0;
 				slave.preg = 0;
 				slave.skill.vaginal = 0;
+				slave.skill.penetrative = 0;
 				slave.skill.oral = 0;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 0;
@@ -424,6 +432,7 @@ globalThis.pRivalryCapture = function(condition) {
 				slave.vagina = 2;
 				slave.preg = 0;
 				slave.skill.vaginal = 15;
+				slave.skill.penetrative = 0;
 				slave.skill.oral = 15;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 0;
@@ -457,6 +466,7 @@ globalThis.pRivalryCapture = function(condition) {
 				slave.vagina = 1;
 				slave.preg = -1;
 				slave.skill.vaginal = 100;
+				slave.skill.penetrative = 35;
 				slave.skill.oral = 100;
 				slave.skill.anal = 35;
 				slave.skill.whoring = 35;
@@ -492,6 +502,7 @@ globalThis.pRivalryCapture = function(condition) {
 					SetBellySize(slave);
 				}
 				slave.skill.vaginal = 100;
+				slave.skill.penetrative = 100;
 				slave.skill.oral = 100;
 				slave.skill.anal = 100;
 				slave.skill.whoring = 100;
diff --git a/src/events/nonRandom/rival/pRivalryHostage.js b/src/events/nonRandom/rival/pRivalryHostage.js
index e8c9e35dcf292695a1c7b35d26201157f005e7e8..b2b5d77a5e2954fc0822b62b313dc7f729f31f4f 100644
--- a/src/events/nonRandom/rival/pRivalryHostage.js
+++ b/src/events/nonRandom/rival/pRivalryHostage.js
@@ -522,6 +522,7 @@ App.Events.pRivalryHostage = function() {
 					slave.skill.entertainment = 100;
 					slave.skill.anal = 100;
 					slave.skill.vaginal = 100;
+					slave.skill.penetrative = 35;
 					slave.skill.whoring = 100;
 					return slave;
 				},
@@ -573,6 +574,7 @@ App.Events.pRivalryHostage = function() {
 						slave.weight = -80;
 					}
 					slave.muscles = 40;
+					slave.skill.penetrative = 35;
 					setHealth(slave, 100, 0, 0, 0, jsRandom(10, 30));
 					return slave;
 				},
@@ -677,6 +679,7 @@ App.Events.pRivalryHostage = function() {
 					slave.fetish = "sadist";
 					slave.fetishStrength = 100;
 					slave.fetishKnown = 1;
+					slave.skill.penetrative = 35;
 					return slave;
 				},
 				celebrity() {
@@ -710,6 +713,7 @@ App.Events.pRivalryHostage = function() {
 					slave.intelligenceImplant = 30;
 					slave.skill.whoring = 100;
 					slave.skill.entertainment = 100;
+					slave.skill.penetrative = 100;
 					return slave;
 				},
 				default() {
diff --git a/src/events/nonRandom/shootResult.js b/src/events/nonRandom/shootResult.js
index d44df9612f788dcbc27e15a1cdffadc4ae2a9288..15ea24cfcd69da76d9f4da8f604ac2dc6bc11797 100644
--- a/src/events/nonRandom/shootResult.js
+++ b/src/events/nonRandom/shootResult.js
@@ -147,6 +147,7 @@ App.Events.PShootResult = class PShootResult extends App.Events.BaseEvent {
 			slave.skill.anal = 0;
 			slave.skill.oral = 0;
 			slave.skill.vaginal = 0;
+			slave.skill.penetrative = 0;
 			slave.fetish = "pregnancy";
 			slave.fetishStrength = 60;
 			slave.behavioralFlaw = "anorexic";
@@ -185,6 +186,7 @@ App.Events.PShootResult = class PShootResult extends App.Events.BaseEvent {
 			slave.preg = -1;
 			slave.anus = 0;
 			slave.skill.anal = 0;
+			slave.skill.penetrative = 0;
 			slave.muscles = 20;
 			slave.weight = 20;
 			setHealth(slave, 30, undefined, undefined, undefined, 0);
@@ -241,6 +243,7 @@ App.Events.PShootResult = class PShootResult extends App.Events.BaseEvent {
 			slave.clit = 0;
 			slave.preg = -2;
 			slave.anus = 2;
+			slave.skill.penetrative = 35;
 			slave.skill.anal = 35;
 			slave.muscles = 0;
 			slave.weight = 0;
diff --git a/src/events/nonRandom/stripClubAftermath.js b/src/events/nonRandom/stripClubAftermath.js
index 92597477fafce199136825d87a8f904e3eef2a87..57c2493195308d1f13a0182a0000a694ffabb6f3 100644
--- a/src/events/nonRandom/stripClubAftermath.js
+++ b/src/events/nonRandom/stripClubAftermath.js
@@ -27,6 +27,7 @@ App.Events.PStripClubAftermath = class PStripClubAftermath extends App.Events.Ba
 				slave.skill.vaginal = 15;
 			}
 			slave.skill.oral = 15;
+			slave.skill.penetrative = 15;
 			slave.skill.anal = 15;
 			slave.skill.whoring = 15;
 			slave.addict = 2;
@@ -41,6 +42,9 @@ App.Events.PStripClubAftermath = class PStripClubAftermath extends App.Events.Ba
 			if (slave.dick === 0) {
 				slave.vagina = 2;
 				slave.skill.vaginal = 35;
+				slave.skill.penetrative = 15;
+			} else {
+				slave.skill.penetrative = 35;
 			}
 			slave.skill.oral = 35;
 			slave.skill.anal = 35;
diff --git a/src/events/reRecruit/DGSE.js b/src/events/reRecruit/DGSE.js
index 1b945976943d5c984f11ab0dcfed01982d0e5d4b..52aafd67875ffd96c9cf79badaba1a19183620a7 100644
--- a/src/events/reRecruit/DGSE.js
+++ b/src/events/reRecruit/DGSE.js
@@ -59,6 +59,7 @@ App.Events.recDGSE = class recDGSE extends App.Events.BaseEvent {
 			slave.faceImplant = 15;
 			slave.skill.vaginal = 0;
 			slave.skill.anal = 0;
+			slave.skill.penetrative = 15;
 			slave.skill.oral = 35;
 			slave.skill.whoring = 0;
 			slave.boobsImplant = random(2, 6) * 100;
diff --git a/src/events/reRecruit/MTFSE.js b/src/events/reRecruit/MTFSE.js
index dd21b5ac2967d10cac44a2603d4bb67cf943c9b0..36a2ca4332affa9c4e21d791cc417daa21388441 100644
--- a/src/events/reRecruit/MTFSE.js
+++ b/src/events/reRecruit/MTFSE.js
@@ -57,6 +57,7 @@ App.Events.recMTFSE = class recMTFSE extends App.Events.BaseEvent {
 			slave.face = random(20, 60);
 			slave.faceImplant = 15;
 			slave.skill.vaginal = 0;
+			slave.skill.penetrative = 15;
 			slave.skill.anal = 0;
 			slave.skill.oral = random(15, 40);
 			slave.skill.whoring = 0;
diff --git a/src/events/reRecruit/dgRunaway.js b/src/events/reRecruit/dgRunaway.js
index d9d3f1002991a2b3a4a7a4305a656c39b1f9ed35..d21404984550b46943296f467d091ef0f62a8778 100644
--- a/src/events/reRecruit/dgRunaway.js
+++ b/src/events/reRecruit/dgRunaway.js
@@ -75,6 +75,7 @@ App.Events.recDgRunaway = class recDgRunaway extends App.Events.BaseEvent {
 			slave.skill.vaginal = 0;
 			slave.skill.anal = 15;
 			slave.skill.oral = 15;
+			slave.skill.penetrative = 15;
 			slave.skill.whoring = 0;
 			slave.boobs = random(2, 6) * 100;
 			slave.vagina = -1;
diff --git a/src/events/reRecruit/farmBull.js b/src/events/reRecruit/farmBull.js
index 079fecfa549664ac60b2f4e6664e4fc664f30aed..1833da7799dcc2a613bd3a9696dbda33aef5cfbc 100644
--- a/src/events/reRecruit/farmBull.js
+++ b/src/events/reRecruit/farmBull.js
@@ -71,6 +71,7 @@ App.Events.recFarmBull = class recFarmBull extends App.Events.BaseEvent {
 			slave.skill.vaginal = 0;
 			slave.skill.anal = 35;
 			slave.skill.oral = 15;
+			slave.skill.penetrative = 65;
 			slave.skill.entertainment = 0;
 			slave.skill.whoring = 0;
 			slave.boobs = 0;
diff --git a/src/events/reRecruit/hermRunaway.js b/src/events/reRecruit/hermRunaway.js
index a085be50cbb62737f8d01b95bc1c9e52938ea4d7..0326792add482130d0e841758e0db3db89dfae73 100644
--- a/src/events/reRecruit/hermRunaway.js
+++ b/src/events/reRecruit/hermRunaway.js
@@ -80,6 +80,7 @@ App.Events.recHermRunaway = class recHermRunaway extends App.Events.BaseEvent {
 			slave.skill.vaginal = 15;
 			slave.skill.anal = 15;
 			slave.skill.oral = 15;
+			slave.skill.penetrative = 15;
 			slave.skill.whoring = 0;
 			slave.boobs = random(3, 7) * 100;
 			slave.vagina = 3;
diff --git a/src/events/reRecruit/maleSD.js b/src/events/reRecruit/maleSD.js
index 66e61256dfd685feb4d2f1acc5d1560a4321e425..4dc435d53755c1517d180f41744fac5862014d1e 100644
--- a/src/events/reRecruit/maleSD.js
+++ b/src/events/reRecruit/maleSD.js
@@ -106,6 +106,7 @@ App.Events.recMaleSD = class recMaleSD extends App.Events.BaseEvent {
 			slave.skill.vaginal = 0;
 			slave.skill.anal = random(0, 40);
 			slave.skill.oral = random(0, 40);
+			slave.skill.penetrative = jsRandom(0, 65);
 			slave.skill.whoring = 0;
 			slave.boobs = 150;
 			slave.vagina = -1;
diff --git a/src/events/reRecruit/orphanFemboy.js b/src/events/reRecruit/orphanFemboy.js
index c7c8ca064a44c8e8aa2217b112a0e338f2b4f764..1284f3aa6c0aae0a3f9f6075d2006906981df4e4 100644
--- a/src/events/reRecruit/orphanFemboy.js
+++ b/src/events/reRecruit/orphanFemboy.js
@@ -66,6 +66,7 @@ App.Events.recOrphanFemboy = class recOrphanFemboy extends App.Events.BaseEvent
 			slave.skill.anal = 15;
 			slave.skill.oral = 35;
 			slave.skill.entertainment = 0;
+			slave.skill.penetrative = 0;
 			slave.skill.whoring = 15;
 			slave.boobs = 200;
 			slave.dick = random(3, 4);
diff --git a/src/events/reRecruit/paternalistSwanSong.js b/src/events/reRecruit/paternalistSwanSong.js
index 8b4ba7254621a66b5048012d64e8f397d754fd7c..988158a326797230ef6bcea471702ba115de4ff4 100644
--- a/src/events/reRecruit/paternalistSwanSong.js
+++ b/src/events/reRecruit/paternalistSwanSong.js
@@ -86,6 +86,7 @@ App.Events.recPaternalistSwanSong = class recPaternalistSwanSong extends App.Eve
 			slave.skill.vaginal = 0;
 			slave.skill.oral = 0;
 			slave.skill.anal = 0;
+			slave.skill.penetrative = 0;
 			slave.piercing.ear.weight = 0;
 			slave.piercing.nose.weight = 0;
 			slave.piercing.eyebrow.weight = 0;
diff --git a/src/events/reRecruit/racerDgChaser.js b/src/events/reRecruit/racerDgChaser.js
index ab40f18f094331484412fb201a8db1d9b8acadb0..a1ff0c45f688a585f89a4368f695d91fe179e5c7 100644
--- a/src/events/reRecruit/racerDgChaser.js
+++ b/src/events/reRecruit/racerDgChaser.js
@@ -65,6 +65,7 @@ App.Events.recRacerDgChaser = class recRacerDgChaser extends App.Events.BaseEven
 			slave.skill.vaginal = 0;
 			slave.skill.anal = random(0, 15);
 			slave.skill.oral = random(0, 15);
+			slave.skill.penetrative = jsRandom(50, 70);
 			slave.skill.whoring = 0;
 			slave.boobs = random(1, 4) * 100;
 			slave.vagina = -1;
diff --git a/src/events/reRecruit/tgAddict.js b/src/events/reRecruit/tgAddict.js
index fc730562f6a73878ec8d890c770ec41448cbb837..ba6575aac57072cee3ca6ccc774be6fbef43e31e 100644
--- a/src/events/reRecruit/tgAddict.js
+++ b/src/events/reRecruit/tgAddict.js
@@ -67,6 +67,7 @@ App.Events.recTgAddict = class recTgAddict extends App.Events.BaseEvent {
 			slave.weight = random(-40, 5);
 			slave.vagina = 0;
 			slave.skill.vaginal = 0;
+			slave.skill.penetrative = 0;
 			slave.dick = 0;
 			slave.foreskin = 0;
 			slave.balls = 0;
diff --git a/src/events/recETS/recetsDesperateBroodmother.js b/src/events/recETS/recetsDesperateBroodmother.js
index cecbecbd885e992933680948bb0aedf23f17ecdd..b8480be58854944bbfc644a1bb1e2b8fe5f88ba8 100644
--- a/src/events/recETS/recetsDesperateBroodmother.js
+++ b/src/events/recETS/recetsDesperateBroodmother.js
@@ -75,6 +75,7 @@ App.Events.recetsDesperateBroodmother = class recetsDesperateBroodmother extends
 			child.pregAdaptation = 10;
 			child.anus = 0;
 			child.skill.vaginal = 0;
+			child.skill.penetrative = 0;
 			child.skill.whoring = 0;
 			child.skill.anal = 0;
 			child.weight = random(-80, -50);
@@ -121,6 +122,7 @@ App.Events.recetsDesperateBroodmother = class recetsDesperateBroodmother extends
 			child.oldTrust = child.trust;
 			child.anus = 0;
 			child.skill.vaginal = 0;
+			child.skill.penetrative = 0;
 			child.skill.whoring = 0;
 			child.skill.anal = 0;
 			child.weight = random(-80, -50);
diff --git a/src/events/recETS/recetsIdenticalHermPair.js b/src/events/recETS/recetsIdenticalHermPair.js
index 840b28ae767a12da472a6514c902cf08c7cabcad..eafc7b4a6ed23f4b960b9bae2fe63ba68c8c14ec 100644
--- a/src/events/recETS/recetsIdenticalHermPair.js
+++ b/src/events/recETS/recetsIdenticalHermPair.js
@@ -37,6 +37,7 @@ App.Events.recetsIdenticalHermPair = class recetsIdenticalHermPair extends App.E
 			thing1.teeth = "normal";
 		}
 		thing1.skill.vaginal = 15;
+		thing1.skill.penetrative = 15;
 		thing1.skill.oral = 15;
 		thing1.skill.anal = 15;
 		if (thing1.physicalAge >= random(13, 17)) {
diff --git a/src/events/recETS/recetsIdenticalPair.js b/src/events/recETS/recetsIdenticalPair.js
index 297e9983d2df97301bb9f98736666986726535ab..7c9db452f4a21e248eb0e7b25e714601d4c2a0c4 100644
--- a/src/events/recETS/recetsIdenticalPair.js
+++ b/src/events/recETS/recetsIdenticalPair.js
@@ -37,6 +37,7 @@ App.Events.recetsIdenticalPair = class recetsIdenticalPair extends App.Events.Ba
 		thing1.skill.vaginal = 15;
 		thing1.skill.oral = 15;
 		thing1.skill.anal = 15;
+		thing1.skill.penetrative = 0;
 		if (thing1.physicalAge >= random(13, 17)) {
 			thing1.boobs = either(500, 600);
 			thing1.natural.boobs = thing1.boobs;
diff --git a/src/events/recETS/recetsIncestFatherDaughter.js b/src/events/recETS/recetsIncestFatherDaughter.js
index 7db9a04bbd6b4ba45fd78a7c216d6c2562fbcf08..6474b8320ea2fb3262174f74417d4e7571a33cb8 100644
--- a/src/events/recETS/recetsIncestFatherDaughter.js
+++ b/src/events/recETS/recetsIncestFatherDaughter.js
@@ -26,6 +26,7 @@ App.Events.recetsIncestFatherDaughter = class recetsIncestFatherDaughter extends
 		father.dick = 4;
 		father.balls = 3;
 		father.scrotum = 3;
+		father.skill.penetrative = 60;
 		father.face = 15;
 		father.faceShape = "masculine";
 		father.clothes = "conservative clothing";
diff --git a/src/events/recETS/recetsIncestMotherSon.js b/src/events/recETS/recetsIncestMotherSon.js
index e5bcd632aaec496fca2b9a992914544a69d10a65..f4e0a8e75c40150c157827c2c419e7a0518da348 100644
--- a/src/events/recETS/recetsIncestMotherSon.js
+++ b/src/events/recETS/recetsIncestMotherSon.js
@@ -53,6 +53,7 @@ App.Events.recetsIncestMotherSon = class recetsIncestMotherSon extends App.Event
 		son.faceShape = "cute";
 		son.boobs = 100;
 		son.anus = 0;
+		son.skill.penetrative = 15;
 		son.energy = Math.max(son.energy, 40);
 		son.attrXX = Math.max(son.attrXX, 70);
 		if (son.behavioralFlaw === "hates women") {
diff --git a/src/events/recETS/recetsIncestTwinsMixed.js b/src/events/recETS/recetsIncestTwinsMixed.js
index 3f75229dc672c6a3019e7985fc4775e9ef3ab785..3dae968672c82d5b270b6063aeca668f36f45a9b 100644
--- a/src/events/recETS/recetsIncestTwinsMixed.js
+++ b/src/events/recETS/recetsIncestTwinsMixed.js
@@ -47,6 +47,7 @@ App.Events.recetsIncestTwinsMixed = class recetsIncestTwinsMixed extends App.Eve
 		bro.balls = 2;
 		bro.scrotum = 2;
 		bro.skill.vaginal = 0;
+		bro.skill.penetrative = 15;
 		bro.faceShape = "masculine";
 		bro.boobs = 100;
 		bro.anus = 0;
diff --git a/src/events/recETS/recetsMatchedPair.js b/src/events/recETS/recetsMatchedPair.js
index 1ee0b9795e04d1a6ccc97e549c641af443a9a718..917bb699aa14c3d0431714a899bcc7665171b6fe 100644
--- a/src/events/recETS/recetsMatchedPair.js
+++ b/src/events/recETS/recetsMatchedPair.js
@@ -37,6 +37,7 @@ App.Events.recetsMatchedPair = class recetsMatchedPair extends App.Events.BaseEv
 		sis1.skill.vaginal = 0;
 		sis1.skill.oral = 15;
 		sis1.skill.anal = 15;
+		sis1.skill.penetrative = 15;
 		sis1.boobs = either(500, 600);
 		sis1.natural.boobs = sis1.boobs; // This is for sis2 to inherit.
 		sis1.boobsImplant = 400;
@@ -67,6 +68,7 @@ App.Events.recetsMatchedPair = class recetsMatchedPair extends App.Events.BaseEv
 		sis2.ovaries = 1;
 		sis2.balls = 0;
 		sis2.skill.vaginal = 15;
+		sis2.skill.penetrative = 0;
 		sis2.boobsImplant = 0;
 		sis2.boobsImplantType = "none";
 		sis2.buttImplant = 0;
diff --git a/src/events/recETS/recetsMismatchedPair.js b/src/events/recETS/recetsMismatchedPair.js
index 71f4e390c4f9183b5de279f0049054a3b8d5cb7a..8292486051f7abe34cb8a315ad3577c267d70828 100644
--- a/src/events/recETS/recetsMismatchedPair.js
+++ b/src/events/recETS/recetsMismatchedPair.js
@@ -41,6 +41,7 @@ App.Events.recetsMismatchedPair = class recetsMismatchedPair extends App.Events.
 		bro.skill.vaginal = 0;
 		bro.skill.oral = 15;
 		bro.skill.anal = 15;
+		bro.skill.penetrative = 15;
 		bro.boobs = 600;
 		bro.boobsImplant = 400;
 		bro.boobsImplantType = "normal";
diff --git a/src/events/recFS/recfsSlaveProfessionalismTwo.js b/src/events/recFS/recfsSlaveProfessionalismTwo.js
index 644ca6c9a876142295210c6feb1b25c72df669cc..0a49053df78a815f9c8ae715adcfd45d193f7c4a 100644
--- a/src/events/recFS/recfsSlaveProfessionalismTwo.js
+++ b/src/events/recFS/recfsSlaveProfessionalismTwo.js
@@ -21,6 +21,8 @@ App.Events.recFSSlaveProfessionalismTwo = class recFSSlaveProfessionalismTwo ext
 		if (slave.vagina >= 0) {
 			slave.vagina = 2;
 			slave.skill.vaginal = 100;
+		} else {
+			slave.skill.penetrative = 100;
 		}
 		slave.weight = random(-10, 10);
 		slave.skill.oral = 100;
diff --git a/src/events/scheduled/seCoursing.js b/src/events/scheduled/seCoursing.js
index bbfa849328ad282b74de77855401b4d567863aa6..69b5ac447e227a0970a9a722b3159e26849c892d 100644
--- a/src/events/scheduled/seCoursing.js
+++ b/src/events/scheduled/seCoursing.js
@@ -149,6 +149,7 @@ App.Events.SECoursing = class SECoursing extends App.Events.BaseEvent {
 				}
 				slave.ovaries = 1;
 				slave.skill.vaginal = 0;
+				slave.skill.penetrative = 0;
 				slave.skill.oral = 0;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 0;
@@ -167,6 +168,7 @@ App.Events.SECoursing = class SECoursing extends App.Events.BaseEvent {
 				SetBellySize(slave);
 				slave.ovaries = 1;
 				slave.skill.vaginal = 0;
+				slave.skill.penetrative = 0;
 				slave.skill.oral = 0;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 0;
@@ -222,6 +224,7 @@ App.Events.SECoursing = class SECoursing extends App.Events.BaseEvent {
 				slave.skill.oral = 0;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 0;
+				slave.skill.penetrative = 15;
 				slave.sexualFlaw = either("hates oral", "hates anal", "hates penetration");
 				slave.behavioralFlaw = either("arrogant", "bitchy", "hates men");
 				slave.attrXY = 0;
@@ -238,6 +241,7 @@ App.Events.SECoursing = class SECoursing extends App.Events.BaseEvent {
 				slave.scrotum = 5;
 				slave.dick = random(3, 5);
 				slave.skill.oral = 0;
+				slave.skill.penetrative = 0;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 0;
 				slave.weight = random(-50, 100);
@@ -256,6 +260,7 @@ App.Events.SECoursing = class SECoursing extends App.Events.BaseEvent {
 				actX(slave, "anal");
 				slave.balls = random(0, 1);
 				slave.dick = random(1, 2);
+				slave.skill.penetrative = 15;
 				slave.skill.oral = 15;
 				slave.skill.anal = 35;
 				slave.skill.whoring = 15;
diff --git a/src/events/scheduled/seCustomSlaveDelivery.js b/src/events/scheduled/seCustomSlaveDelivery.js
index 61cca97d9c29c15a5e6cf325f7d51bc25f69b53d..485157f8cb0e9b309bb4a10f1681985d95aaa629 100644
--- a/src/events/scheduled/seCustomSlaveDelivery.js
+++ b/src/events/scheduled/seCustomSlaveDelivery.js
@@ -170,6 +170,7 @@ App.Events.SEcustomSlaveDelivery = class SEcustomSlaveDelivery extends App.Event
 				delivery.balls = V.customSlave.balls;
 				delivery.scrotum = delivery.balls;
 				delivery.foreskin = delivery.dick;
+				delivery.skill.penetrative = V.customSlave.skills;
 			} else {
 				if (V.customSlave.virgin === 0) {
 					delivery.vagina = V.customSlave.virgin;
@@ -182,6 +183,7 @@ App.Events.SEcustomSlaveDelivery = class SEcustomSlaveDelivery extends App.Event
 					delivery.balls = V.customSlave.balls;
 					delivery.scrotum = delivery.balls;
 					delivery.foreskin = delivery.dick;
+					delivery.skill.penetrative = V.customSlave.skills;
 					if (delivery.dick === 0) {
 						delivery.clit = V.customSlave.clit;
 						delivery.foreskin = delivery.clit;
diff --git a/src/events/scheduled/seRaiding.js b/src/events/scheduled/seRaiding.js
index 29255c816505a4d1f5b098bb69f5d11ef1d42d0c..c15ebbd6ea0d38b4be63fd49e9f7a5014c3b9b44 100644
--- a/src/events/scheduled/seRaiding.js
+++ b/src/events/scheduled/seRaiding.js
@@ -469,6 +469,7 @@ App.Events.SERaiding = class SERaiding extends App.Events.BaseEvent {
 						minAge: 26, maxAge: 45, disableDisability: 1, ageOverridesPedoMode: 1
 					});
 					slave.career = "a military officer";
+					slave.skill.penetrative = 35;
 					slave.skill.anal = 0;
 					slave.skill.oral = 0;
 					slave.skill.whoring = 0;
diff --git a/src/events/scheduled/seRecruiterSuccess.js b/src/events/scheduled/seRecruiterSuccess.js
index ffb123e551433a68230e1a72564a29af150f7a54..81268be07a37677ec880e8a5036c4b5616dcc592 100644
--- a/src/events/scheduled/seRecruiterSuccess.js
+++ b/src/events/scheduled/seRecruiterSuccess.js
@@ -37,6 +37,9 @@ App.Events.SERecruiterSuccess = class SERecruiterSuccess extends App.Events.Base
 				slave.vagina = random(1, 3);
 				slave.skill.vaginal = random(15, 40);
 			}
+			if (slave.dick > 0 && canAchieveErection(slave)) {
+				slave.skill.penetrative = jsRandom(15,40);
+			}
 			slave.skill.anal = 0;
 			slave.piercing.ear.weight = pierceMe();
 		} else if (V.recruiterTarget === "reassignment candidates") {
@@ -49,7 +52,7 @@ App.Events.SERecruiterSuccess = class SERecruiterSuccess extends App.Events.Base
 			if (slave.balls === 0) {
 				slave.balls = random(1, 3);
 			}
-
+			slave.skill.penetrative = jsRandom(0, 35);
 			slave.piercing.tongue.weight = pierceMe();
 			slave.piercing.ear.weight = pierceMe();
 			slave.piercing.nose.weight = pierceMe();
@@ -65,6 +68,7 @@ App.Events.SERecruiterSuccess = class SERecruiterSuccess extends App.Events.Base
 			if (slave.balls === 0) {
 				slave.balls = random(1, 3);
 			}
+			slave.skill.penetrative = jsRandom(15, 40);
 			slave.skill.oral = random(15, 40);
 			slave.skill.anal = random(15, 40);
 			slave.faceImplant = 20*pierceMe();
@@ -110,6 +114,7 @@ App.Events.SERecruiterSuccess = class SERecruiterSuccess extends App.Events.Base
 			if (slave.balls > 0) {
 				slave.vagina = random(1, 3);
 				slave.skill.vaginal = random(15, 40);
+				slave.skill.penetrative = 15;
 			}
 			slave.skill.oral = random(15, 40);
 			slave.skill.anal = random(15, 40);
diff --git a/src/events/scheduled/seTheSirenStrikesBack.js b/src/events/scheduled/seTheSirenStrikesBack.js
index b23bd8de641374c234c5f7f824dd107a3df522c0..51f6991c31efcdb260f77c9d435e2984f55ef46f 100644
--- a/src/events/scheduled/seTheSirenStrikesBack.js
+++ b/src/events/scheduled/seTheSirenStrikesBack.js
@@ -32,6 +32,9 @@ App.Events.SETheSirenStrikesBack = class SETheSirenStrikesBack extends App.Event
 			producer.vagina = 1;
 			producer.preg = -1;
 		}
+		if (producer.dick > 0) {
+			producer.skill.penetrative = 15;
+		}
 		producer.skill.vaginal = 0;
 		producer.skill.oral = 0;
 		producer.skill.anal = 0;
diff --git a/src/events/schools/resFailure.js b/src/events/schools/resFailure.js
index 5d21eaa379ddd134b60d002fcefec12d267b9ce9..ce9614325bbcbb32426e495ce6ea6f660abb2aa4 100644
--- a/src/events/schools/resFailure.js
+++ b/src/events/schools/resFailure.js
@@ -137,6 +137,7 @@ App.Events.RESFailure = class RESFailure extends App.Events.BaseEvent {
 			} else {
 				slave.balls = slave.scrotum = (V.TFS.schoolUpgrade === 1 ? 0 : random(5, 6));
 			}
+			slave.skill.penetrative = 100;
 			slave.lips = random(25, 55);
 			slave.weight = 50;
 			slave.vagina = 3;
diff --git a/src/facilities/nursery/nurseryDatatypeCleanup.js b/src/facilities/nursery/nurseryDatatypeCleanup.js
index e79986ba6ed9a8a58fa545ee9dc0659455b0634a..3ba3f8f46231bb05d63786e3c1103bc643bda0f4 100644
--- a/src/facilities/nursery/nurseryDatatypeCleanup.js
+++ b/src/facilities/nursery/nurseryDatatypeCleanup.js
@@ -409,6 +409,7 @@ App.Facilities.Nursery.ChildDatatypeCleanup = function(child) {
 	function childSkillsDatatypeCleanup(child) {
 		child.skill.oral = Math.clamp(+child.skill.oral, 0, 100) || 0;
 		child.skill.vaginal = Math.clamp(+child.skill.vaginal, 0, 100) || 0;
+		child.skill.penetrative = Math.clamp(+child.skill.penetrative, 0, 100) || 0;
 		child.skill.anal = Math.clamp(+child.skill.anal, 0, 100) || 0;
 		child.skill.whoring = Math.clamp(+child.skill.whoring, 0, 100) || 0;
 		child.skill.entertainment = Math.clamp(+child.skill.entertainment, 0, 100) || 0;
diff --git a/src/facilities/nursery/utils/nurseryUtils.js b/src/facilities/nursery/utils/nurseryUtils.js
index 4680c67fdaabbd360484623963294a50ce46451a..a53ce91fcb2bd66bb810a9f732649d874ec1d74c 100644
--- a/src/facilities/nursery/utils/nurseryUtils.js
+++ b/src/facilities/nursery/utils/nurseryUtils.js
@@ -316,6 +316,7 @@ App.Facilities.Nursery.infantToChild = function infantToChild(child) {
 		stewardess: 0,
 		teacher: 0,
 		vaginal: 0,
+		penetrative: 0,
 		wardeness: 0,
 		whore: 0,
 		whoring: 8
diff --git a/src/facilities/schoolroom/schoolroomFramework.js b/src/facilities/schoolroom/schoolroomFramework.js
index e64d48550f69508ddb67289abf26887e280cbc31..a469bc7f86db7590d8122b02729a6599f2a7c562 100644
--- a/src/facilities/schoolroom/schoolroomFramework.js
+++ b/src/facilities/schoolroom/schoolroomFramework.js
@@ -55,6 +55,7 @@ App.Entity.Facilities.SchoolroomStudentJob = class extends App.Entity.Facilities
 			(slave.voice === 0 || slave.accent + this.facility.upgrade("Language") <= 2) &&
 			(slave.skill.oral > maxSkill) && (slave.skill.whoring > maxSkill) && (slave.skill.entertainment > maxSkill) &&
 			(slave.skill.anal > maxSkill) && ((slave.vagina < 0) || (slave.skill.vaginal > maxSkill)) &&
+			((penetrativeSocialUse() < 40) || (slave.skill.penetrative > maxSkill)) &&
 			(!needsTutoring(slave))) {
 			r.push(`${slave.slaveName} has nothing left to learn.`);
 		}
diff --git a/src/interaction/sellSlave.js b/src/interaction/sellSlave.js
index 819db07bb0de65ba32f0e033f44e44984930260f..8a4e8e9afc5d07332c1162a61d3046aa21eb3718 100644
--- a/src/interaction/sellSlave.js
+++ b/src/interaction/sellSlave.js
@@ -1784,7 +1784,7 @@ App.Interact.sellSlave = function(slave) {
 			["D r9k", {
 				cost: 1.15,
 				offerDesc: `from a prominent citizen who's a notoriously inexperienced lover; it's painfully obvious that he prefers inexperienced slaves as they make him feel less insecure.`,
-				get requirements() { return (slave.skill.vaginal <= 10 && slave.skill.anal <= 10 && slave.skill.oral <= 10 && slave.skill.whoring <= 10 && slave.skill.entertainment <= 10); },
+				get requirements() { return (slave.skill.vaginal <= 10 && slave.skill.penetrative <= 10 && slave.skill.anal <= 10 && slave.skill.oral <= 10 && slave.skill.whoring <= 10 && slave.skill.entertainment <= 10); },
 				percentOdds: 80,
 				get completeSale() {
 					const r = [];
@@ -2918,6 +2918,8 @@ App.Interact.sellSlave = function(slave) {
 			desc = ` from a citizen interested in acquiring a skilled butthole bitch.`;
 		} else if ((slave.skill.vaginal >= 100) && (random(1, 100) > 80)) {
 			desc = ` from a citizen interested in acquiring a slut with real vaginal skill.`;
+		} else if ((slave.skill.penetrative >= 100) && (random(1, 100) > 90)) {
+			desc = ` from a citizen interested in be filled with a skilled stud's dick.`;
 		} else if ((slave.skill.oral >= 100) && (random(1, 100) > 80)) {
 			desc = ` from a citizen interested in acquiring a skilled cocksucker.`;
 		} else if ((slave.health.condition > 80) && (random(1, 100) > 80)) {
diff --git a/src/js/SlaveState.js b/src/js/SlaveState.js
index 1fbff2dd1198bf17bac4de5d1dce9625fe1df2f2..03f3fd0307633714ef395b8b5a7f68185ffb839d 100644
--- a/src/js/SlaveState.js
+++ b/src/js/SlaveState.js
@@ -160,6 +160,15 @@ App.Entity.SlaveSkillsState = class {
 		 * * 100+: master
 		 */
 		this.vaginal = 0;
+		/**
+		 * skill in penetrative sex
+		 * * 0-10: unskilled
+		 * * 11-30: basic
+		 * * 31-60: skilled
+		 * * 61-99: expert
+		 * * 100+: master
+		 */
+		this.penetrative = 0;
 		/**
 		 * skill in oral sex
 		 * * 0-10: unskilled
diff --git a/src/js/economyJS.js b/src/js/economyJS.js
index b08ee41e103bd8bd791b02d7378f2e4478baa136..98dbd06e55391423d7697c60b4d72ea1f94d1d38 100644
--- a/src/js/economyJS.js
+++ b/src/js/economyJS.js
@@ -1828,8 +1828,16 @@ globalThis.slaveJobValues = function(lowerClassSexDemandRef, middleClassSexDeman
 			App.EndWeek.saVars.madamBonus += 0.05 * Math.floor((-0.00008 * madamIntel * madamIntel) + (0.0337 * madamIntel) + 0.5);
 		}
 		if (madam.dick > 2 && canPenetrate(madam)) {
-			// $His turgid dick helps $him manage the bitches.
-			App.EndWeek.saVars.madamBonus += 0.05;
+			if (S.Madam.skill.penetrative > 90) {
+				// $His skilled dick incentivizes the bitches to behave.
+				App.EndWeek.saVars.madamBonus += 0.07;
+			} else if (S.Madam.skill.penetrative > 10) {
+				// $His turgid dick helps $him manage the bitches.
+				App.EndWeek.saVars.madamBonus += 0.05;
+			} else {
+				// `$He tries to use $his turgid cock to keep the bitches in line, but $his lack of skill only leaves them off kilter.
+				App.EndWeek.saVars.madamBonus -= 0.05;
+			}
 		}
 		for (const slave of App.Entity.facilities.brothel.employees()) {
 			if (madam.relationshipTarget === slave.ID) {
@@ -1851,7 +1859,7 @@ globalThis.slaveJobValues = function(lowerClassSexDemandRef, middleClassSexDeman
 				}
 			} else if (slave.prestigeDesc === "$He is remembered for winning best in show as a cockmilker.") {
 				if (FutureSocieties.isActive('FSGenderFundamentalist')) {
-					if (slave.balls === 0 && slave.dick === 0 && slave.vagina > -1) { /* this needs review - doesn't fit right. An XY slave would be expected to be masculine. */
+					if (slave.balls === 0 && slave.dick === 0 && slave.vagina > -1) { /* this needs review - doesn't fit right. An XY slave would be expected to be masculine. 5.0.0 */
 						App.EndWeek.saVars.madamBonus += 0.20;
 					}
 				} else if ((slave.balls > 5 && slave.dick !== 0) || (slave.balls > 4 && slave.dick !== 0 && slave.prostate > 1)) {
@@ -1960,12 +1968,17 @@ globalThis.slaveJobValues = function(lowerClassSexDemandRef, middleClassSexDeman
 				} else {
 					const canA = canDoAnal(s) ? 1 : 0;
 					const canV = canDoVaginal(s) ? 1 : 0;
-					let skilltarget = (100 + ((s.skill.anal - 100) * canA * (1.5 - 0.5 * canV) + (s.skill.vaginal - 100) * canV * (1.5 - 0.5 * canA) + (s.skill.oral - 100) * (3 - 1.5 * canA - 1.5 * canV + canA * canV)) * 3 / 10);
+					let canP = canPenetrate(s) && penetrativeSocialUse(s) >= 40 ? 1 : 0;
+					let skilltarget = (100 + (s.skill.anal - 100) * canA * [0, 6, 4, 3][canA + canV + canP] + // 100 -> 0, 600, 400, 300
+						(s.skill.vaginal - 100) * canV * [0, 6, 4, 3][canA + canV + canP] + // 100 -> 0, 600, 400, 300
+						(s.skill.penetrative - 100) * canP * [0, 6, 4, 3][canA + canV + canP] + // 100 -> 0, 600, 400, 300
+						(s.skill.oral - 100) * [12, 6, 4, 3][canA + canV + canP] // 100 -> 1200, 600, 400, 300
+						) / 120;
 					// Complicated, I know - but it should automatically account for what acts are possible to scale the injury risk smoothly between 90% when totally unskilled
 					// and 0% when perfectly skilled in the relevant method or methods.
 
 					if (jsRandom(1, 100) > skilltarget) {
-						healthDamage(s, 10 - 7 * canA * canV); // Any limitations means an injury inflicts the harsher 10 instead of 3
+						healthDamage(s, 10 - 7 * canA * (canV | canP)); // Any limitations means an injury inflicts the harsher 10 instead of 3
 						s.minorInjury = 1;
 					}
 				}
diff --git a/src/js/slaveCostJS.js b/src/js/slaveCostJS.js
index faf89e7803fbbe26b54a495819301d204f22da2f..bd6c5b936f3ddf249d8968bb54d39842a013fac7 100644
--- a/src/js/slaveCostJS.js
+++ b/src/js/slaveCostJS.js
@@ -439,7 +439,7 @@ globalThis.BeautyArray = function(slave) {
 			}
 		}
 		if (arcologyInfo.fsActive('FSSlaveProfessionalism')) {
-			adjustBeauty("Skilled: Slave Professionalism", ((arcology.FSSlaveProfessionalism / 50) * ((slave.skill.entertainment + slave.skill.whoring + slave.skill.oral + slave.skill.anal + slave.skill.vaginal) / 100))); /* 10 */
+			adjustBeauty("Skilled: Slave Professionalism", ((arcology.FSSlaveProfessionalism / 50) * ((slave.skill.entertainment + slave.skill.whoring + slave.skill.oral + slave.skill.anal + slave.skill.vaginal + adjustedPenSkill(slave)) / 100))); /* 10 */
 		}
 		if (arcologyInfo.fsActive('FSYouthPreferentialist')) {
 			if (slave.visualAge < 30) {
@@ -1882,7 +1882,7 @@ globalThis.FResultArray = (function() {
 			adjustFResult(`Muscles: weak`, -2);
 		}
 
-		const uses = V.oralUseWeight + V.vaginalUseWeight + V.analUseWeight;
+		const uses = V.oralUseWeight + V.vaginalUseWeight + V.analUseWeight + V.penetrativeUseWeight;
 		if (uses <= 0) {
 			return;
 		}
@@ -1906,6 +1906,12 @@ globalThis.FResultArray = (function() {
 				adjustFResult(`Anal potential: Aphrodisiac inflation`, (V.analUseWeight / uses) * (slave.inflation * 3));
 			}
 		}
+		if (canPenetrate(slave)) {
+			adjustFResult(`Dick use potential: skill, and arcology penetrative weight`, (6 + slave.piercing.dick.weight) * (V.penetrativeUseWeight / uses) * (slave.skill.penetrative / 30));
+			adjustFResult(`Dick use potential: Dick size`, (slave.dick < 7 ? Math.floor(slave.dick / 2) : Math.round((slave.dick - 8) / 2)));
+		} else if (penetrativeSocialUse() >= 20) {
+			adjustFResult(`Penetrative potential: skill, and arcology penetrative weight`, (6 + slave.piercing.dick.weight) * (V.penetrativeUseWeight / uses) * (slave.skill.penetrative / 30));
+		}			
 	}
 
 	/**
@@ -2921,6 +2927,9 @@ globalThis.slaveCostBeauty = function(slave, isStartingSlave, followLaws, isSpec
 		if (slave.skill.vaginal) {
 			startingSlaveMultiplier += 0.00001 * slave.skill.vaginal * slave.skill.vaginal;
 		}
+		if (slave.skill.penetrative > 10) {
+			startingSlaveMultiplier += 0.00001 * slave.skill.penetrative * slave.skill.penetrative;
+		}
 		if (slave.skill.anal) {
 			startingSlaveMultiplier += 0.00001 * slave.skill.anal * slave.skill.anal;
 		}
diff --git a/src/js/slaveListing.js b/src/js/slaveListing.js
index c72083e8a51b6d1360406f07ba5dd7441666de26..91eab41f4f87d0da21b8aacec7cfc7da7c395542 100644
--- a/src/js/slaveListing.js
+++ b/src/js/slaveListing.js
@@ -234,6 +234,9 @@ App.UI.SlaveList.render = function(IDs, rejectedSlaves, interactionLink, postNot
 			if (!((slave.skill.vaginal > 30) || ((V.schoolroomUpgradeSkills === 0) && (slave.skill.vaginal > 10)) || (slave.vagina < 0))) {
 				lessons.push("vaginal");
 			}
+			if (!((slave.skill.penetrative > 30) || ((V.schoolroomUpgradeSkills === 0) && (slave.skill.penetrative > 10)) || (penetrativeSocialUse() < 40))) {
+				lessons.push("penetrative");
+			}
 			const role = tutorForSlave(slave);
 			if (role && needsTutoring(slave)) {
 				lessons.push(`being a good ${role}`);
diff --git a/src/js/slaveSummaryHelpers.js b/src/js/slaveSummaryHelpers.js
index ff6decf3ba44f75de203e9a9d7d1a6cfa7848fd7..c535ee8a95f20e4a288f197a1d6d873192d637f3 100644
--- a/src/js/slaveSummaryHelpers.js
+++ b/src/js/slaveSummaryHelpers.js
@@ -988,11 +988,16 @@ App.UI.SlaveSummaryImpl = function() {
 		function short_skills(slave, c) {
 			const sd = data.short.skills;
 			let SSkills = (slave.skill.anal + slave.skill.oral);
-			if (((SSkills + slave.skill.whoring + slave.skill.entertainment) >= 400) && ((slave.vagina < 0) || (slave.skill.vaginal >= 100))) {
+			let PSU = penetrativeSocialUse();
+			if (
+				((SSkills + slave.skill.whoring + slave.skill.entertainment) >= 400) &&
+				((slave.vagina < 0) || (slave.skill.vaginal >= 100)) &&
+				((PSU < 60 && (PSU < 40 || (!canAchieveErection(slave) && slave.clit < 3))) || (slave.skill.penetrative >= 100))
+			) {
 				helpers.makeStyledSpan(c, sd.mss);
 			} else {
-				SSkills += slave.skill.vaginal;
-				helpers.makeStyledSpan(c, App.Ratings.multiNumeric(sd.sex, [SSkills, slave.vagina >= 0 ? 1 : 0]), Math.trunc(SSkills), true);
+				SSkills += slave.skill.vaginal + adjustedPenSkill(slave);
+				helpers.makeStyledSpan(c, App.Ratings.multiNumeric(sd.sex, [SSkills, ((slave.vagina >= 0 ? 1 : 0) + (slave.dick > 0 ? 2 : 0))]), Math.trunc(SSkills), true);
 				helpers.makeRatedStyledSpan(c, sd.whoring, slave.skill.whoring, 0, true);
 				helpers.makeRatedStyledSpan(c, sd.entertainment, slave.skill.entertainment, 0, true);
 			}
@@ -1040,11 +1045,16 @@ App.UI.SlaveSummaryImpl = function() {
 		function long_skills(slave, c) {
 			const sd = data.long.skills;
 			let SSkills = (slave.skill.anal + slave.skill.oral);
-			if (((SSkills + slave.skill.whoring + slave.skill.entertainment) >= 400) && ((slave.vagina < 0) || (slave.skill.vaginal >= 100))) {
+			let PSU = penetrativeSocialUse();
+			if (
+				((SSkills + slave.skill.whoring + slave.skill.entertainment) >= 400) &&
+				((slave.vagina < 0) || (slave.skill.vaginal >= 100)) &&
+				((PSU < 60 && (PSU < 40 || (!canAchieveErection(slave) && slave.clit < 3))) || (slave.skill.penetrative >= 100))
+			) {
 				helpers.makeStyledSpan(c, sd.mss);
 			} else {
-				SSkills += slave.skill.vaginal;
-				helpers.makeStyledSpan(c, App.Ratings.multiNumeric(sd.sex, [SSkills, slave.vagina >= 0 ? 1 : 0]), Math.trunc(SSkills), true);
+				SSkills += slave.skill.vaginal + adjustedPenSkill(slave);
+				helpers.makeStyledSpan(c, App.Ratings.multiNumeric(sd.sex, [SSkills, ((slave.vagina >= 0 ? 1 : 0) + (slave.dick > 0 ? 2 : 0))]), Math.trunc(SSkills), true);
 				helpers.makeRatedStyledSpan(c, sd.whoring, slave.skill.whoring, 0, true);
 				helpers.makeRatedStyledSpan(c, sd.entertainment, slave.skill.entertainment, 0, true);
 			}
diff --git a/src/js/statsChecker/statsChecker.js b/src/js/statsChecker/statsChecker.js
index e25992d84e48d41cad05c2c3865a7722a6cda4b9..903a4581e7eb0bd962be3d9a27555f9e306f7893 100644
--- a/src/js/statsChecker/statsChecker.js
+++ b/src/js/statsChecker/statsChecker.js
@@ -1239,7 +1239,7 @@ globalThis.isHorny = function(actor) {
  * @param {FC.HumanState} actor
  * @returns {boolean}
  */
-globalThis.acceptsUnderage = function(actor) {
+globalThis.acceptsUnderage = function(actor) { // should this consider slaves below an age threshold?
 	return (actor.fetish === Fetish.MINDBROKEN ||
 		(actor.behavioralQuirk === "sinful") ||
 		(actor.devotion > 50) || 
diff --git a/src/js/utilsArcology.js b/src/js/utilsArcology.js
index 90275afbe5048815255cb93783caff0bd3457ce7..cd03f709302b0027fb0ca2021b1294b561bff714 100644
--- a/src/js/utilsArcology.js
+++ b/src/js/utilsArcology.js
@@ -91,6 +91,78 @@ globalThis.menialPopCap = function() {
 	return {text: r, value: popCap};
 };
 
+/**
+ * Returns the percentage (0-100) of the social acceptance of the slaves penetrating citizens in YOUR arcology. Accepts a slave as argument.
+ *
+ * @param {FC.SlaveState} slave
+ * @returns {number}
+ */
+globalThis.penetrativeSocialUse = function(slave = null) {
+	let total = 10;
+	if (V.policies.sexualOpenness) {
+		total += 40 + 20 * (Math.clamp(V.rep - 5000, 0, 12000) / 12000); // penetrative campaign, related to reputation, (40 to 60)
+	}
+	total += V.LDE.schoolPresent * 3 + V.TGA.schoolPresent * 3 + V.TFS.schoolPresent * 10; // slave schools focused on penises
+	total += FutureSocieties.isActive("FSGenderRadicalist") ? 25 : 0;
+	total += [0, 15, 20, 0, 5][V.arcologies[0].FSGenderRadicalistLawFuta]; // 15 futas, 20 big dicks & balls, 5 small dicks
+	total += FutureSocieties.isActive("FSNull") ? 15 : 0;
+	total += FutureSocieties.isActive("FSHedonisticDecadence") ? 15 : 0;
+	total += FutureSocieties.isActive("FSRepopulationFocus") ? 5 : 0;
+	total += V.arcologies[0].FSRepopulationFocusLaw * 10;
+
+	total -= FutureSocieties.isActive("FSGenderFundamentalist") ? 25 : 0;
+	total -= V.arcologies[0].FSGenderFundamentalistSMR ? 30 : 0;
+	total -= FutureSocieties.isActive("FSEdoRevivalist") ? 10 : 0;
+	total -= FutureSocieties.isActive("FSArabianRevivalist") ? 10 : 0;
+	total -= FutureSocieties.isActive("FSChineseRevivalist") ? 10 : 0;
+	total -= V.arcologies[0].FSRestartSMR ? 30 : 0;
+	total -= FutureSocieties.isActive("FSAztecRevivalist") ? 10 : 0;
+	total -= FutureSocieties.isActive("FSNeoImperialist") ? 10 : 0;
+	total -= FutureSocieties.isActive("FSAntebellumRevivalist") ? 10 : 0;
+
+	total = Math.clamp(total, 0, 100);
+
+	if (slave && asSlave(slave)) {
+		total += slave.toyHole === "dick" ? 5 : 0;
+		total += Math.trunc(slave.skill.penetrative / 20); // 10 changed to 20 to avoid unskilled giving 1 at 10. This may be better as a quadratic function to make higher values more impactful.
+		if (FutureSocieties.isActive("FSSupremacist")) {
+			total += V.arcologies[0].FSSupremacistRace === slave.race ? 10 : -20;
+		}
+		if (FutureSocieties.isActive("FSSubjugationist")) {
+			total += V.arcologies[0].FSSubjugationistRace === slave.race ? 20 : 0;
+		}
+		if (FutureSocieties.isActive("FSRestart")) {
+			total -= isVirile(slave) ? 40 : 0;
+		}
+		total += slave.prestige * 5;
+		total += Math.pow(slave.porn.prestige, 3);
+		// in the future, consider some sort of penetrative pornstar bonus here
+	}
+
+	if (V.seeDicks === 0 && total > 0) {
+		total *= .6;
+	} else if (V.seeDicks > 25) {
+		total += V.seeDicks < 75 ? V.seeDicks * .10 : V.seeDicks * .08;
+	}
+
+	if (total >= 40) { // Once dicks are trendy, availability starts to increase interest
+		let haveDick = V.slaves.filter(s => s.dick > 0).length;
+		if (haveDick) {
+			let withDick = (haveDick / V.slaves.length); // percentage of slaves with dicks
+			total += withDick > .2 ? 15 * withDick : 0;
+			let toyHole = V.slaves.filter(s => s.toyHole === "dick").length;
+			total += 10 * (toyHole / haveDick);
+			let penetrativeAverage = 0;
+			V.slaves.filter(s => s.dick > 0).forEach(s1 => {
+				penetrativeAverage += s1.skill.penetrative;
+			});
+			total += (penetrativeAverage / haveDick) * .1;
+		}
+	}
+
+	total = Math.clamp(Math.floor(total), 0, 100);
+	return total;
+};
 
 App.Utils.Arcology = class {
 	/**
diff --git a/src/js/utilsMisc.js b/src/js/utilsMisc.js
index 98c4244ef4c7f0d04120043210c76c26f8dd75f1..168d10115fea383478968f325bbe10c11eed2560 100644
--- a/src/js/utilsMisc.js
+++ b/src/js/utilsMisc.js
@@ -392,76 +392,3 @@ globalThis.weightedRandom = function(values) {
 	// Array was empty or all weights were 0
 	return null;
 };
-
-/**
- * Returns the percentage (0-100) of the social acceptance of the slaves penetrating citizens. Accepts a slave as argument.
- *
- * @param {FC.SlaveState} slave
- * @returns {number}
- */
-globalThis.penetrativeSocialUse = function(slave = null) {
-	let total = 10;
-	if (V.policies.sexualOpenness) {
-		total += 40 + 20 * (Math.clamp(V.rep - 5000, 0, 12000) / 12000); // penetrative campaign, related to reputation, (40 to 60)
-	}
-	total += V.LDE.schoolPresent * 3 + V.TGA.schoolPresent * 3 + V.TFS.schoolPresent * 10; // slave schools focused on penises
-	total += FutureSocieties.isActive("FSGenderRadicalist") ? 25 : 0;
-	total += [0, 15, 20, 0, 5][V.arcologies[0].FSGenderRadicalistLawFuta]; // 15 futas, 20 big dicks & balls, 5 small dicks
-	total += FutureSocieties.isActive("FSNull") ? 15 : 0;
-	total += FutureSocieties.isActive("FSHedonisticDecadence") ? 15 : 0;
-	total += FutureSocieties.isActive("FSRepopulationFocus") ? 5 : 0;
-	total += V.arcologies[0].FSRepopulationFocusLaw * 10;
-
-	total -= FutureSocieties.isActive("FSGenderFundamentalist") ? 25 : 0;
-	total -= V.arcologies[0].FSGenderFundamentalistSMR ? 30 : 0;
-	total -= FutureSocieties.isActive("FSEdoRevivalist") ? 10 : 0;
-	total -= FutureSocieties.isActive("FSArabianRevivalist") ? 10 : 0;
-	total -= FutureSocieties.isActive("FSChineseRevivalist") ? 10 : 0;
-	total -= V.arcologies[0].FSRestartSMR ? 30 : 0;
-	total -= FutureSocieties.isActive("FSAztecRevivalist") ? 10 : 0;
-	total -= FutureSocieties.isActive("FSNeoImperialist") ? 10 : 0;
-	total -= FutureSocieties.isActive("FSAntebellumRevivalist") ? 10 : 0;
-
-	total = Math.clamp(total, 0, 100);
-
-	if (slave && asSlave(slave)) {
-		total += slave.toyHole === "dick" ? 5 : 0;
-		// total += (slave.skill.penetrative / 10);
-		if (FutureSocieties.isActive("FSSupremacist")) {
-			total += V.arcologies[0].FSSupremacistRace === slave.race ? 10 : -20;
-		}
-		if (FutureSocieties.isActive("FSSubjugationist")) {
-			total += V.arcologies[0].FSSubjugationistRace === slave.race ? 20 : 0;
-		}
-		if (FutureSocieties.isActive("FSRestart")) {
-			total -= isVirile(slave) ? 40 : 0;
-		}
-		total += slave.prestige * 5;
-		total += Math.pow(slave.porn.prestige, 3);
-		// in the future, consider some sort of penetrative pornstar bonus here
-	}
-
-	if (V.seeDicks === 0 && total > 0) {
-		total *= .6;
-	} else if (V.seeDicks > 25) {
-		total += V.seeDicks < 75 ? V.seeDicks * .10 : V.seeDicks * .08;
-	}
-
-	if (total >= 40) { // Once dicks are trendy, availability starts to increase interest
-		let haveDick =V.slaves.filter(s => s.dick > 0).length;
-		if (haveDick) {
-			let withDick = (haveDick / V.slaves.length); // percentage of slaves with dicks
-			total += withDick > .2 ? 15 * withDick : 0;
-			let toyHole = V.slaves.filter(s => s.toyHole === "dick").length;
-			total += 10 * (toyHole / haveDick);
-			/* let penetrativeAverage = 0;
-			V.slaves.filter(s => s.dick > 0).forEach(s1 => {
-				penetrativeAverage += s1.skill.penetrative;
-			});
-			total += (penetrativeAverage / haveDick) * .1; */
-		}
-	}
-
-	total = Math.clamp(Math.floor(total), 0, 100);
-	return total;
-};
diff --git a/src/js/utilsSlave.js b/src/js/utilsSlave.js
index f7daea8b6724d96b517516c9abdf2c3717fc21c6..d07db6c78662aedc92cf23be5e13b549349902e8 100644
--- a/src/js/utilsSlave.js
+++ b/src/js/utilsSlave.js
@@ -1045,6 +1045,7 @@ globalThis.resyncSlaveToAge = function(slave) {
 		slave.skill.entertainment = 0;
 		slave.skill.combat = 0;
 		slave.skill.vaginal = 0;
+		slave.skill.penetrative = 0;
 		slave.attrXY = 50;
 		slave.attrXX = 50;
 		slave.boobs = 200;
@@ -2273,6 +2274,15 @@ globalThis.DegradingName = function(slave) {
 	if (slave.skill.anal > 95) {
 		suffixes.push("Asspussy", "Sphincter");
 	}
+	if (slave.skill.penetrative > 95) {
+		names.push("Plowhorse");
+		if (slave.dick > 0) {
+			names.push("Boytoy");
+		}
+		if (!canAchieveErection(slave)) {
+			suffixes.push("Pegger");
+		}
+	}
 	if (slave.intelligence + slave.intelligenceImplant > 50) {
 		names.push("Bright", "Clever", "Smart");
 		if (slave.intelligenceImplant >= 15) {
@@ -3042,6 +3052,7 @@ globalThis.slaveSkillIncrease = function(targetSkill, slave, skillIncrease = 1)
 				case 'oral':
 				case 'vaginal':
 				case 'anal':
+				case 'penetrative':
 					skillDec = `knowledge about ${targetSkill} sex,`;
 					break;
 				case 'whoring':
@@ -3064,6 +3075,9 @@ globalThis.slaveSkillIncrease = function(targetSkill, slave, skillIncrease = 1)
 					case 'vaginal':
 						r += ` and can avoid some of the common pitfalls and turnoffs.`;
 						break;
+					case 'penetrative':
+						r += ` and can smoothly insert ${himself} on the first try.`;
+						break;
 					case 'anal':
 						r += ` and can accept penetration of ${his} anus without danger.`;
 						break;
@@ -3082,6 +3096,7 @@ globalThis.slaveSkillIncrease = function(targetSkill, slave, skillIncrease = 1)
 				case 'oral':
 				case 'vaginal':
 				case 'anal':
+				case 'penetrative':
 					skillDec = `${targetSkill} skills,`;
 					break;
 				case 'whoring':
@@ -3104,6 +3119,9 @@ globalThis.slaveSkillIncrease = function(targetSkill, slave, skillIncrease = 1)
 					case 'vaginal':
 						r += ` and can do more than just lie there and take it.`;
 						break;
+					case 'penetrative':
+						r += ` and is capable of making it pleasurable for ${his} partner.`;
+						break;
 					case 'anal':
 						r += ` and needs less preparation before taking rough penetration.`;
 						break;
@@ -3126,6 +3144,9 @@ globalThis.slaveSkillIncrease = function(targetSkill, slave, skillIncrease = 1)
 				case 'vaginal':
 					skillDec = `a vaginal sex expert,`;
 					break;
+				case 'penetrative':
+					skillDec = `an expert at penetrative sex,`;
+					break;
 				case 'whoring':
 					skillDec = `an expert whore,`;
 					break;
@@ -3145,6 +3166,9 @@ globalThis.slaveSkillIncrease = function(targetSkill, slave, skillIncrease = 1)
 					case 'vaginal':
 						r += ` and has the muscular control to massage anything that's inside ${him}.`;
 						break;
+					case 'penetrative':
+						r += ` and knows how manage ${his} pace, depth and force to maximize ${his} partner's enjoyment.`;
+						break;
 					case 'anal':
 						r += ` and knows how to use ${his} sphincter to please.`;
 						break;
@@ -3164,6 +3188,7 @@ globalThis.slaveSkillIncrease = function(targetSkill, slave, skillIncrease = 1)
 				case 'oral':
 				case 'vaginal':
 				case 'anal':
+				case 'penetrative':
 					skillDec = `has mastered ${targetSkill} sex,`;
 					break;
 				case 'whoring':
@@ -3185,6 +3210,9 @@ globalThis.slaveSkillIncrease = function(targetSkill, slave, skillIncrease = 1)
 					case 'vaginal':
 						r += ` and can learn nothing more about tribbing or taking dick.`;
 						break;
+					case 'penetrative':
+						r += ` and can learn nothing more about fucking pussies, anuses or mouths.`;
+						break;
 					case 'anal':
 						r += ` and can learn nothing more about taking it up the ass.`;
 						break;
@@ -3205,6 +3233,27 @@ globalThis.slaveSkillIncrease = function(targetSkill, slave, skillIncrease = 1)
 	return r;
 };
 
+/**
+ * Considers societal standards and returns slave penetration skill if expected
+ * @returns {number} adjusted penetration skill
+ */
+globalThis.adjustedPenSkill = function(slave, specific = false) {
+	let skill = 0;
+	if (!slave || !slave.skill) {
+		return skill;
+	}
+	let tastes = penetrativeSocialUse(specific ? slave : null);
+
+	if (tastes >= 60) {
+		skill = slave.skill.penetrative;
+	} else if (tastes >= 40) {
+		if (canAchieveErection(slave) || slave.clit >= 3) {
+			skill = slave.skill.penetrative;
+		}
+	}
+	return Math.clamp(skill, 0, 100);
+}
+
 /**
  * Generates a new slave ID that is guaranteed to be unused
  * @returns {number} slave ID
@@ -3349,6 +3398,7 @@ globalThis.applyMindbroken = function(slave, oldIntelligence = -200) {
 	slave.devotion = 40;
 	slave.trust = -40;
 	slave.skill.vaginal = Math.clamp(slave.skill.vaginal, 0, 15);
+	slave.skill.penetrative = Math.clamp(slave.skill.penetrative, 0, 15);
 	slave.skill.oral = Math.clamp(slave.skill.oral, 0, 15);
 	slave.skill.anal = Math.clamp(slave.skill.anal, 0, 15);
 	slave.skill.combat = 0;
diff --git a/src/js/vignettes.js b/src/js/vignettes.js
index 283bdd252cd202f6022567543f84b0c224560c92..dada19d5f877dd591664aec7cfd57a6de7611846 100644
--- a/src/js/vignettes.js
+++ b/src/js/vignettes.js
@@ -1396,6 +1396,13 @@ globalThis.GetVignette = function(slave) {
 				effect: 0,
 			});
 		}
+		if (slave.skill.penetrative >= 100) {
+			vignettes.push({
+				text: `${he} was hired by a group of girls to painlessly deflower one of them,`,
+				type: "rep",
+				effect: 0,
+			});
+		}
 		if (canDoAnal(slave) && slave.skill.anal < 100 && slave.anus < 2) {
 			vignettes.push({
 				text: `a guy with a huge cock paid for the right to fuck ${him} in ${his} tight ass all night,`,
@@ -3422,6 +3429,13 @@ globalThis.GetVignette = function(slave) {
 				effect: 0,
 			});
 		}
+		if (slave.skill.penetrative >= 100) {
+			vignettes.push({
+				text: `${he} was brought by a group of girls to make their friend's first time special,`,
+				type: "devotion",
+				effect: 0,
+			});
+		}
 		if (canDoAnal(slave) && slave.skill.anal < 100 && slave.anus < 2) {
 			vignettes.push({
 				text: `a guy with a huge cock insisted on fucking ${him} in ${his} tight ass all night,`,
diff --git a/src/markets/specificMarkets/eliteSlave.js b/src/markets/specificMarkets/eliteSlave.js
index 8f7d04147b04235878353807f46d16d6ce9a9075..d8b65632269efb73c32b76f24c47938a48073879 100644
--- a/src/markets/specificMarkets/eliteSlave.js
+++ b/src/markets/specificMarkets/eliteSlave.js
@@ -239,6 +239,9 @@ App.Markets["Elite Slave"] = function() {
 			if (slave.vagina >= 0) {
 				slave.skill.vaginal = 100;
 			}
+			if (penetrativeSocialUse(slave) >= 40) {
+				slave.skill.penetrative = 100;
+			}
 			slave.skill.anal = 100;
 			slave.skill.oral = 100;
 			slave.skill.entertainment = 100;
diff --git a/src/markets/specificMarkets/prestigiousSlave.js b/src/markets/specificMarkets/prestigiousSlave.js
index e717f65dff47571111b0f7085d5147fb64d785c2..4d4343887ab80f1e357abedcc5f4fc7be1eeab1d 100644
--- a/src/markets/specificMarkets/prestigiousSlave.js
+++ b/src/markets/specificMarkets/prestigiousSlave.js
@@ -120,6 +120,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.piercing.nose.weight = 1;
 				slave.piercing.ear.weight = 1;
 				slave.skill.vaginal = 100;
+				slave.skill.penetrative = 65;
 				slave.skill.oral = 100;
 				slave.skill.anal = 100;
 				slave.skill.whoring = 15;
@@ -158,6 +159,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.piercing.nipple.weight = 1;
 				slave.piercing.ear.weight = 1;
 				slave.skill.vaginal = 35;
+				slave.skill.penetrative = 0;
 				slave.skill.oral = 35;
 				slave.skill.anal = 15;
 				slave.skill.whoring = 35;
@@ -220,6 +222,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.piercing.ear.weight = 1;
 				slave.skill.vaginal = 15;
 				slave.skill.oral = 15;
+				slave.skill.penetrative = 0;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 15;
 				slave.skill.entertainment = 35;
@@ -287,6 +290,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.piercing.eyebrow.weight = 2;
 				slave.piercing.ear.weight = 2;
 				slave.skill.vaginal = 100;
+				slave.skill.penetrative = 100;
 				slave.skill.oral = 100;
 				slave.skill.anal = 100;
 				slave.skill.whoring = 100;
@@ -327,6 +331,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.weight = 0;
 				slave.piercing.ear.weight = 1;
 				slave.skill.vaginal = 15;
+				slave.skill.penetrative = 0;
 				slave.skill.oral = 15;
 				slave.skill.anal = 15;
 				slave.skill.whoring = 0;
@@ -385,6 +390,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.vagina = 0;
 				slave.weight = 0;
 				slave.skill.vaginal = 0;
+				slave.skill.penetrative = 0;
 				slave.skill.oral = 100;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 15;
@@ -447,6 +453,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.legsTat = "rude words";
 				slave.stampTat = "rude words";
 				slave.skill.vaginal = 15;
+				slave.skill.penetrative = 100;
 				slave.skill.oral = 15;
 				slave.skill.anal = 15;
 				slave.skill.whoring = 0;
@@ -478,6 +485,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.weight = 20;
 				slave.piercing.ear.weight = 1;
 				slave.skill.vaginal = 15;
+				slave.skill.penetrative = 0;
 				slave.skill.oral = 15;
 				slave.skill.anal = 1;
 				slave.skill.whoring = 5;
@@ -516,6 +524,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.attrXY = random(30, 50);
 				slave.energy = random(5, 20);
 				slave.skill.vaginal = 0;
+				slave.skill.penetrative = 0;
 				slave.skill.oral = 15;
 				slave.skill.anal = 15;
 				slave.skill.whoring = 0;
@@ -551,6 +560,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.attrXY = random(80, 100);
 				slave.energy = random(60, 90);
 				slave.skill.vaginal = 0;
+				slave.skill.penetrative = 0;
 				slave.skill.oral = 0;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 0;
@@ -605,6 +615,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.piercing.nipple.weight = 1;
 				slave.piercing.nose.weight = 1;
 				slave.piercing.ear.weight = 1;
+				slave.skill.penetrative = 100;
 				slave.skill.oral = 100;
 				slave.skill.anal = 100;
 				slave.skill.whoring = 15;
@@ -631,6 +642,7 @@ App.Markets["Prestigious Slave"] = function() {
 				setHealth(slave, jsRandom(60, 80), 0, 0, 0, jsRandom(10, 30));
 				slave.weight = 0;
 				slave.piercing.genitals.weight = 1;
+				slave.skill.penetrative = 65;
 				slave.skill.oral = 15;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 15;
@@ -665,6 +677,7 @@ App.Markets["Prestigious Slave"] = function() {
 					slave.scrotum = slave.balls;
 				}
 				slave.weight = 0;
+				slave.skill.penetrative = 35;
 				slave.skill.oral = 15;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 0;
@@ -695,6 +708,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.anus = 2;
 				slave.weight = 0;
 				slave.piercing.ear.weight = 1;
+				slave.skill.penetrative = 35;
 				slave.skill.oral = 100;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 15;
@@ -770,6 +784,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.piercing.navel.weight = 2;
 				slave.piercing.eyebrow.weight = 2;
 				slave.piercing.ear.weight = 2;
+				slave.skill.penetrative = 100;
 				slave.skill.oral = 100;
 				slave.skill.anal = 100;
 				slave.skill.whoring = 100;
@@ -808,6 +823,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.anus = 1;
 				slave.weight = 0;
 				slave.piercing.ear.weight = 1;
+				slave.skill.penetrative = 15;
 				slave.skill.oral = 15;
 				slave.skill.anal = 15;
 				slave.skill.whoring = 0;
@@ -836,6 +852,7 @@ App.Markets["Prestigious Slave"] = function() {
 				setHealth(slave, jsRandom(60, 80), 0, 0, 0, jsRandom(30, 70));
 				slave.anus = 0;
 				slave.weight = 0;
+				slave.skill.penetrative = 35;
 				slave.skill.oral = 0;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 0;
@@ -869,6 +886,7 @@ App.Markets["Prestigious Slave"] = function() {
 				}
 				slave.weight = 0;
 				slave.skill.vaginal = 0;
+				slave.skill.penetrative = 0;
 				slave.skill.oral = 100;
 				slave.skill.anal = 0;
 				slave.skill.whoring = 15;
@@ -914,6 +932,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.armsTat = "rude words";
 				slave.legsTat = "rude words";
 				slave.stampTat = "rude words";
+				slave.skill.penetrative = 100;
 				slave.skill.oral = 15;
 				slave.skill.anal = 15;
 				slave.skill.whoring = 0;
@@ -944,6 +963,7 @@ App.Markets["Prestigious Slave"] = function() {
 				slave.anus = 2;
 				slave.weight = 20;
 				slave.piercing.ear.weight = 1;
+				slave.skill.penetrative = 10;
 				slave.skill.oral = 30;
 				slave.skill.anal = 1;
 				slave.skill.whoring = 5;
diff --git a/src/markets/specificMarkets/slaveShelter.js b/src/markets/specificMarkets/slaveShelter.js
index c3afdfa993ee2243c6c9e99cf3c9fdca12624fd3..3b2dd590331899545c90b6e5b18218578da5a2e6 100644
--- a/src/markets/specificMarkets/slaveShelter.js
+++ b/src/markets/specificMarkets/slaveShelter.js
@@ -118,6 +118,7 @@ App.Markets["Slave Shelter"] = function() {
 					V.shelterSlave.foreskin = 0;
 					V.shelterSlave.balls = 0;
 					V.shelterSlave.scrotum = 0;
+					V.shelterSlave.skill.penetrative = 0;
 					V.shelterSlave.behavioralFlaw = either("anorexic", "anorexic", "anorexic", "odd");
 					V.shelterSlave.sexualFlaw = either("apathetic", "neglectful", "self hating");
 					V.shelterSlave.fetish = either("masochist", "none", "none");
@@ -202,6 +203,7 @@ App.Markets["Slave Shelter"] = function() {
 					V.shelterSlave.balls = 0;
 					V.shelterSlave.anus = 4;
 					V.shelterSlave.skill.oral = 0;
+					V.shelterSlave.skill.penetrative = 0;
 					V.shelterSlave.skill.anal = 15;
 					V.shelterSlave.skill.whoring = 0;
 					V.shelterSlave.skill.entertainment = 0;
@@ -222,6 +224,7 @@ App.Markets["Slave Shelter"] = function() {
 					V.shelterSlave.balls = jsRandom(4, 5);
 					V.shelterSlave.anus = 0;
 					V.shelterSlave.skill.oral = 0;
+					V.shelterSlave.skill.penetrative = 0;
 					V.shelterSlave.skill.anal = 0;
 					V.shelterSlave.skill.whoring = 0;
 					V.shelterSlave.skill.entertainment = 0;
@@ -296,6 +299,7 @@ App.Markets["Slave Shelter"] = function() {
 					V.shelterSlave.skill.oral = 35;
 					V.shelterSlave.skill.anal = 35;
 					V.shelterSlave.skill.vaginal = 35;
+					V.shelterSlave.skill.penetrative = 15;
 					V.shelterSlave.skill.whoring = 35;
 					V.shelterSlave.skill.entertainment = 15;
 					V.shelterSlave.skill.combat = 0;
diff --git a/src/npc/children/childSummary.js b/src/npc/children/childSummary.js
index 4deb59b8be95feb2eeccf2f5abcd5db0e38f0727..6fa4b63c7e0f98c64faacfef49397da3ca9b1d6b 100644
--- a/src/npc/children/childSummary.js
+++ b/src/npc/children/childSummary.js
@@ -2675,7 +2675,7 @@ App.Facilities.Nursery.ChildSummary = function(child) {
 	/**
 	 * @param {App.Entity.SlaveState} child
 	 */
-	function shortSexSkills(child) {
+	function shortSexSkills(child) { // Resync this with slaveSummary
 		let SSkills = child.skill.anal + child.skill.oral;
 		r += `<span class="skill">`;
 		if (((SSkills + child.skill.whoring + child.skill.entertainment) >= 400) && ((child.vagina < 0) || (child.skill.vaginal >= 100))) {
@@ -2830,7 +2830,7 @@ App.Facilities.Nursery.ChildSummary = function(child) {
 	/**
 	 * @param {App.Entity.SlaveState} child
 	 */
-	function longSexSkills(child) {
+	function longSexSkills(child) { // Resync this with slaveSummary
 		let SSkills = (child.skill.anal + child.skill.oral);
 		r += `<span class="skill">`;
 		if (((SSkills + child.skill.whoring + child.skill.entertainment) >= 400) && ((child.vagina < 0) || (child.skill.vaginal >= 100))) {
diff --git a/src/npc/children/longChildDescription.js b/src/npc/children/longChildDescription.js
index fa9a99a18590fa97610a9be631eadbc097c17b83..44876ec91b9c3885160c7d8442133cb226c7bcca 100644
--- a/src/npc/children/longChildDescription.js
+++ b/src/npc/children/longChildDescription.js
@@ -1678,6 +1678,19 @@ App.Facilities.Nursery.LongChildDescription = function(child, {market = 0, event
 			} else if (child.dick < 1 && child.balls > 3) {
 				r += `${His} cock is so small that it barely protrudes from ${his} ample ballsack. `;
 			}
+			if (!canAchieveErection(child)) {
+				r.push(`Since ${he} can't achieve an erection, ${his} penetrative skill is irrelevant.`);
+			} else if (child.skill.penetrative >= 100) {
+				r.push(`${He} is a <span class="skill">master in penetrative sex.</span>`);
+			} else if (child.skill.penetrative > 60) {
+				r.push(`${He} is an <span class="skill">expert in penetrative sex.</span>`);
+			} else if (child.skill.penetrative > 30) {
+				r.push(`${He} is <span class="skill">skilled penetrating others.</span>`);
+			} else if (child.skill.penetrative > 10) {
+				r.push(`${He} has <span class="skill">basic knowledge about penetrating others.</span>`);
+			} else {
+				r.push(`${He} has no penetrative skill.`);
+			}
 		} else if (child.vagina === -1) {
 			if (!child.scrotum) {
 				r += `${He} has ${V.seeDicks > 0 ? `no penis and ` : ``}no vagina, nothing but a tiny hole in the smooth ${child.skin} skin ${hasBothLegs(child) ? `between ${his} legs` : `at the base of ${his} hips`}. `;
diff --git a/src/npc/databases/cheatmodeDatabase.js b/src/npc/databases/cheatmodeDatabase.js
index 61d13f0aaf4d81ade06cfd2c2126d095fba69bc0..1a7987432ff873c66a092d0aeac13cd5e2a9001f 100644
--- a/src/npc/databases/cheatmodeDatabase.js
+++ b/src/npc/databases/cheatmodeDatabase.js
@@ -47,6 +47,7 @@ App.Intro.cheatModeSlaves = function() {
 	cheatSlave.nails = 1;
 	cheatSlave.piercing.ear.weight = 1;
 	cheatSlave.skill.oral = 100;
+	cheatSlave.skill.penetrative = 100;
 	cheatSlave.skill.anal = 100;
 	cheatSlave.skill.whoring = 100;
 	cheatSlave.skill.entertainment = 100;
@@ -122,6 +123,7 @@ App.Intro.cheatModeSlaves = function() {
 	cheatSlave.piercing.ear.weight = 1;
 	cheatSlave.skill.oral = 100;
 	cheatSlave.skill.anal = 100;
+	cheatSlave.skill.penetrative = 100;
 	cheatSlave.skill.whoring = 100;
 	cheatSlave.skill.entertainment = 100;
 	cheatSlave.clothes = "a slave gown";
@@ -190,6 +192,7 @@ App.Intro.cheatModeSlaves = function() {
 	cheatSlave.nails = 1;
 	cheatSlave.piercing.ear.weight = 1;
 	cheatSlave.skill.oral = 35;
+	cheatSlave.skill.penetrative = 35;
 	cheatSlave.skill.anal = 35;
 	cheatSlave.skill.whoring = 35;
 	cheatSlave.skill.entertainment = 35;
@@ -345,6 +348,7 @@ App.Intro.cheatModeSlaves = function() {
 		cheatSlave.foreskin = 4;
 		cheatSlave.prostate = 1;
 		cheatSlave.pubertyXY = 1;
+		cheatSlave.skill.penetrative = 15;
 	}
 	newSlave(cheatSlave);
 	V.BodyguardID = cheatSlave.ID;
@@ -423,6 +427,7 @@ App.Intro.cheatModeSlaves = function() {
 		cheatSlave.prostate = 1;
 		cheatSlave.dickTat = "bovine patterns";
 		cheatSlave.pubertyXY = 1;
+		cheatSlave.skill.penetrative = 15;
 	}
 	newSlave(cheatSlave);
 	slaveNames.push(cheatSlave.slaveName);
diff --git a/src/npc/databases/dSlavesDatabase.js b/src/npc/databases/dSlavesDatabase.js
index 058fdcf9cf3189f54a76c58b27cc1e653cd3416e..369fb4baa455680a51fe1eded081e7fee1cf10d2 100644
--- a/src/npc/databases/dSlavesDatabase.js
+++ b/src/npc/databases/dSlavesDatabase.js
@@ -128,6 +128,7 @@ App.Data.HeroSlaves.D = [
 			vaginal: 35,
 			oral: 35,
 			anal: 35,
+			penetrative: 15,
 			combat: 65
 		},
 		intelligence: -20,
@@ -265,6 +266,7 @@ App.Data.HeroSlaves.D = [
 			vaginal: 15,
 			oral: 15,
 			anal: 15,
+			penetrative: 15,
 			combat: 15,
 		},
 		attrXX: 80,
@@ -315,6 +317,7 @@ App.Data.HeroSlaves.D = [
 			vaginal: 100,
 			oral: 100,
 			anal: 100,
+			penetrative: 35,
 			combat: 65,
 		},
 		clothes: "restrictive latex",
@@ -357,6 +360,7 @@ App.Data.HeroSlaves.D = [
 			vaginal: 100,
 			oral: 100,
 			anal: 100,
+			penetrative: 35,
 			entertainment: 100
 		},
 		intelligence: 25,
@@ -1034,6 +1038,7 @@ App.Data.HeroSlaves.D = [
 		ovaries: 1,
 		skill: {
 			vaginal: 35,
+			penetrative: 35,
 			oral: 35,
 			anal: 35
 		},
@@ -1702,6 +1707,7 @@ App.Data.HeroSlaves.D = [
 		skill: {
 			vaginal: 100,
 			oral: 100,
+			penetrative: 35,
 			anal: 100
 		},
 		clothes: "slutty jewelry",
@@ -2780,6 +2786,7 @@ App.Data.HeroSlaves.D = [
 		ovaries: 1,
 		skill: {
 			vaginal: 15,
+			penetrative: 15,
 			oral: 35
 		},
 		clothes: "a slave gown",
@@ -3266,6 +3273,7 @@ App.Data.HeroSlaves.D = [
 			vaginal: 100,
 			oral: 100,
 			anal: 100,
+			penetrative: 100,
 			whoring: 100,
 			entertainment: 100,
 			combat: 100
diff --git a/src/npc/databases/ddSlavesDatabase.js b/src/npc/databases/ddSlavesDatabase.js
index 8aaa94edc5e3081bf9adee6ec3b86cca45d652e1..e22491063e6dc73ed434f21f81ec9735a593be62 100644
--- a/src/npc/databases/ddSlavesDatabase.js
+++ b/src/npc/databases/ddSlavesDatabase.js
@@ -33,7 +33,7 @@ App.Data.HeroSlaves.DD = [
 		prostate: 1,
 		balls: 1,
 		scrotum: 1,
-		skill: {oral: 35, anal: 100},
+		skill: {oral: 35, anal: 100, penetrative: 35},
 		intelligenceImplant: 30,
 		attrXX: 40,
 		attrXY: 40,
@@ -97,7 +97,7 @@ App.Data.HeroSlaves.DD = [
 		prostate: 1,
 		balls: 1,
 		scrotum: 1,
-		skill: {oral: 15, anal: 15},
+		skill: {oral: 15, anal: 15, penetrative: 15},
 		attrXX: 40,
 		attrXY: 40,
 		fetish: "buttslut",
@@ -206,7 +206,7 @@ App.Data.HeroSlaves.DD = [
 		prostate: 1,
 		balls: 2,
 		scrotum: 2,
-		skill: {oral: 100, anal: 100},
+		skill: {oral: 100, anal: 100, penetrative: 65},
 		intelligence: 100,
 		intelligenceImplant: 30,
 		attrXX: 40,
@@ -316,7 +316,7 @@ App.Data.HeroSlaves.DD = [
 		prostate: 1,
 		balls: 2,
 		scrotum: 2,
-		skill: {oral: 35, anal: 35},
+		skill: {oral: 35, anal: 35, penetrative: 15},
 		clothes: "a slave gown",
 		intelligence: -20,
 		attrXX: 40,
@@ -439,7 +439,7 @@ App.Data.HeroSlaves.DD = [
 		prostate: 1,
 		balls: 1,
 		scrotum: 1,
-		skill: {oral: 15, anal: 15},
+		skill: {oral: 15, anal: 15, penetrative: 15},
 		clothes: "attractive lingerie",
 		intelligence: -20,
 		attrXX: 40,
@@ -521,7 +521,7 @@ App.Data.HeroSlaves.DD = [
 		prostate: 1,
 		balls: 2,
 		scrotum: 2,
-		skill: {oral: 35, anal: 15},
+		skill: {oral: 35, anal: 15, penetrative: 15},
 		clothes: "restrictive latex",
 		intelligence: 25,
 		intelligenceImplant: 30,
@@ -565,7 +565,7 @@ App.Data.HeroSlaves.DD = [
 		prostate: 1,
 		balls: 2,
 		scrotum: 2,
-		skill: {oral: 15, anal: 15},
+		skill: {oral: 15, anal: 15, penetrative: 15},
 		intelligence: 98,
 		intelligenceImplant: 30,
 		attrXX: 40,
@@ -640,7 +640,7 @@ App.Data.HeroSlaves.DD = [
 		balls: 3,
 		scrotum: 3,
 		anusTat: "bleached",
-		skill: {oral: 100, anal: 100},
+		skill: {oral: 100, anal: 100, penetrative: 100},
 		attrXX: 40,
 		attrXY: 40,
 		fetishKnown: 1,
@@ -674,7 +674,7 @@ App.Data.HeroSlaves.DD = [
 		prostate: 1,
 		balls: 1,
 		anusTat: "bleached",
-		skill: {oral: 15, combat: 15},
+		skill: {oral: 15, penetrative: 15, combat: 15},
 		intelligence: 30,
 		attrXX: 40,
 		attrXY: 40,
@@ -715,7 +715,7 @@ App.Data.HeroSlaves.DD = [
 		balls: 3,
 		scrotum: 3,
 		anusTat: "bleached",
-		skill: {combat: 65},
+		skill: {combat: 65, penetrative: 35},
 		intelligence: 30,
 		intelligenceImplant: 30,
 		attrXX: 40,
@@ -755,7 +755,7 @@ App.Data.HeroSlaves.DD = [
 		balls: 3,
 		scrotum: 3,
 		anusTat: "bleached",
-		skill: {oral: 15},
+		skill: {oral: 15, penetrative: 15},
 		attrXX: 40,
 		attrXY: 40,
 		fetishKnown: 1,
@@ -797,7 +797,7 @@ App.Data.HeroSlaves.DD = [
 		balls: 2,
 		scrotum: 2,
 		anusTat: "bleached",
-		skill: {anal: 100, combat: 65},
+		skill: {anal: 100, combat: 65, penetrative: 35},
 		addict: 50,
 		intelligence: 20,
 		intelligenceImplant: 30,
@@ -843,7 +843,7 @@ App.Data.HeroSlaves.DD = [
 		shouldersTat: "tribal patterns",
 		armsTat: "rude words",
 		stampTat: "rude words",
-		skill: {oral: 100, entertainment: 15},
+		skill: {oral: 100, penetrative: 15, entertainment: 15},
 		clothes: "a slutty outfit",
 		collar: "pretty jewelry",
 		shoes: "heels",
@@ -908,6 +908,7 @@ App.Data.HeroSlaves.DD = [
 			vaginal: 35,
 			oral: 100,
 			anal: 100,
+			penetrative: 15,
 			whoring: 100,
 			entertainment: 35
 		},
@@ -960,7 +961,7 @@ App.Data.HeroSlaves.DD = [
 		scrotum: 4,
 		makeup: 1,
 		nails: 1,
-		skill: {entertainment: 35},
+		skill: {penetrative: 15, entertainment: 35},
 		clothes: "cutoffs and a t-shirt",
 		collar: "pretty jewelry",
 		shoes: "heels",
@@ -1017,7 +1018,7 @@ App.Data.HeroSlaves.DD = [
 		scrotum: 2,
 		anusTat: "flowers",
 		brand: {"back": "your initials"},
-		skill: {oral: 15, anal: 15, entertainment: 15},
+		skill: {oral: 15, anal: 15, penetrative: 15, entertainment: 15},
 		clothes: "a comfortable bodysuit",
 		collar: "pretty jewelry",
 		shoes: "heels",
@@ -1064,7 +1065,7 @@ App.Data.HeroSlaves.DD = [
 		scrotum: 2,
 		makeup: 1,
 		nails: 1,
-		skill: {oral: 15},
+		skill: {oral: 15, penetrative: 35},
 		collar: "pretty jewelry",
 		shoes: "heels",
 		intelligence: 100,
@@ -1121,7 +1122,7 @@ App.Data.HeroSlaves.DD = [
 		nails: 3,
 		legsTat: "flowers",
 		stampTat: "flowers",
-		skill: {oral: 100, anal: 100, whoring: 100},
+		skill: {oral: 100, anal: 100, penetrative: 65, whoring: 100},
 		clothes: "a slave gown",
 		collar: "pretty jewelry",
 		shoes: "heels",
@@ -1223,6 +1224,7 @@ App.Data.HeroSlaves.DD = [
 			vaginal: 35,
 			oral: 35,
 			anal: 15,
+			penetrative: 35,
 			whoring: 35,
 			entertainment: 35,
 			combat: 15
@@ -1288,6 +1290,7 @@ App.Data.HeroSlaves.DD = [
 			vaginal: 15,
 			oral: 100,
 			anal: 15,
+			penetrative: 100,
 			whoring: 15,
 			entertainment: 15,
 			combat: 35
@@ -1419,6 +1422,7 @@ App.Data.HeroSlaves.DD = [
 			vaginal: 100,
 			oral: 100,
 			anal: 100,
+			penetrative: 35,
 			whoring: 15,
 			entertainment: 35
 		},
@@ -1525,6 +1529,7 @@ App.Data.HeroSlaves.DDextreme = [
 		hStyle: "neat",
 		boobs: 400,
 		preg: -2,
+		skill: {penetrative: 15},
 		attrXX: 40,
 		attrXY: 40,
 		sexualFlaw: "hates penetration",
@@ -1562,7 +1567,7 @@ App.Data.HeroSlaves.DDextreme = [
 		preg: -2,
 		dick: 1,
 		anusTat: "bleached",
-		skill: {oral: 100},
+		skill: {oral: 100, penetrative: 35},
 		clothes: "a penitent nuns habit",
 		collar: "tight steel",
 		shoes: "heels",
@@ -1609,7 +1614,7 @@ App.Data.HeroSlaves.DDextreme = [
 		balls: 3,
 		scrotum: 3,
 		anusTat: "bleached",
-		skill: {combat: 65},
+		skill: {combat: 65, penetrative: 15},
 		intelligence: -40,
 		intelligenceImplant: 30,
 		attrXX: 40,
@@ -1713,7 +1718,7 @@ App.Data.HeroSlaves.DDextreme = [
 		intelligenceImplant: 30,
 		attrXX: 100,
 		attrXY: 0,
-		skill: {oral: 95},
+		skill: {oral: 95, penetrative: 95},
 		fetish: "submissive",
 		fetishKnown: 1,
 		behavioralQuirk: "advocate"
diff --git a/src/npc/databases/dfSlavesDatabase.js b/src/npc/databases/dfSlavesDatabase.js
index 67324f2ea859a833827baef4b12ec8b0dad44775..87b299ec904635c902a033a8a95241a677fde7b6 100644
--- a/src/npc/databases/dfSlavesDatabase.js
+++ b/src/npc/databases/dfSlavesDatabase.js
@@ -190,7 +190,7 @@ App.Data.HeroSlaves.DF = [
 		preg: -2,
 		anus: 2,
 		ovaries: 1,
-		skill: {vaginal: 35, oral: 100, anal: 35},
+		skill: {vaginal: 35, oral: 100, anal: 35, penetrative: 15},
 		attrXY: 40,
 		fetish: "submissive",
 		fetishKnown: 1,
diff --git a/src/npc/descriptions/crotch/dick.js b/src/npc/descriptions/crotch/dick.js
index 67a5bc21a8d9f076700535a11c24b7f00742de7a..8aa4977f94780ac64ebfaf916b57e32f6b9dd471 100644
--- a/src/npc/descriptions/crotch/dick.js
+++ b/src/npc/descriptions/crotch/dick.js
@@ -1631,6 +1631,7 @@ App.Desc.dick = function(slave, descType = DescType.NORMAL) {
 	}
 
 	r.push(App.Desc.mods(slave, "dick"));
+	penetrativeSkillDesc();
 
 	return r.join(" ");
 
@@ -1930,4 +1931,40 @@ App.Desc.dick = function(slave, descType = DescType.NORMAL) {
 				break;
 		}
 	}
+
+	function penetrativeSkillDesc() {
+		if (slave.fuckdoll > 0) {
+			if (canPenetrate(slave) && (V.policies.sexualOpenness || slave.toyHole === "dick")) {
+				if (V.PC.vagina > 0 || V.PC.anus > 0) {
+					r.push(`Riding`);
+				} else {
+					r.push(`Playing with`);
+				}
+				r.push(`${his} dick`);
+				if (slave.fuckdoll <= 65) { /// 55?
+					r.push(`mostly results in you doing all the work, assuming ${he} even stays hard.`);
+				} else {
+					r.push(`offers its user a wide selection of speeds and positions that last and last.`);
+				}
+			}
+		} else if (slave.dick > 0 || slave.balls > 0 || slave.vagina === -1) {
+			if (slave.skill.penetrative >= 100) {
+				r.push(`${He} is a <span class="skill">penetrative sex master.</span>`);
+			} else if (slave.skill.penetrative > 60) {
+				r.push(`${He} is an <span class="skill">expert at penetrative sex.</span>`);
+			} else if (slave.skill.penetrative > 30) {
+				r.push(`${He} is <span class="skill">skilled at penetrating others.</span>`);
+			} else if (slave.skill.penetrative > 10) {
+				if (canPenetrate(slave) || slave.clit >= 3 || penetrativeSocialUse(slave) >= 40) {
+					r.push(`${He} is <span class="skill">capable of basic penetrative sex.</span>`);
+				}
+			} else {
+				if (canPenetrate(slave) || slave.clit >= 3) {
+					r.push(`${He} is unskilled at using ${his} ${slave.clit >= 3 ? "clit" : "dick"} for penetration.`);
+				} else if (penetrativeSocialUse(slave) >= 40) {
+					r.push(`${He} is clueless at how to have penetrative sex.`);
+				}
+			}
+		}
+	}
 };
diff --git a/src/npc/descriptions/crotch/vagina.js b/src/npc/descriptions/crotch/vagina.js
index a185acd3899fa042b202daf6784bc248c6a3c536..8f36c31b0d519d138520962045e65893a154998c 100644
--- a/src/npc/descriptions/crotch/vagina.js
+++ b/src/npc/descriptions/crotch/vagina.js
@@ -646,6 +646,23 @@ App.Desc.vagina = function(slave) {
 		} else {
 			r.push(`${He} is unskilled at vaginal sex.`);
 		}
+		if (slave.vagina >= 0) {
+			if (slave.skill.penetrative >= 100) {
+				r.push(`${He} is a <span class="skill">penetrative sex master.</span>`);
+			} else if (slave.skill.penetrative > 60) {
+				r.push(`${He} is an <span class="skill">expert at penetrative sex.</span>`);
+			} else if (slave.skill.penetrative > 30) {
+				r.push(`${He} is <span class="skill">skilled at penetrating others.</span>`);
+			} else if (slave.skill.penetrative > 10) {
+				if (penetrativeSocialUse(slave) >= 40) {
+					r.push(`${He} is <span class="skill">capable of basic penetrative sex.</span>`);
+				}
+			} else {
+				if (penetrativeSocialUse(slave) >= 40) {
+					r.push(`${He} is clueless at how to penetrate others.`);
+				}
+			}
+		}
 	}
 
 	r.push(App.Desc.mods(slave, "pubic mound"));
diff --git a/src/npc/descriptions/skills.js b/src/npc/descriptions/skills.js
index bd41b2a34419168802512a6964c677354cca585f..9c044024c4bc92a24461b8ef55af1b3393891802 100644
--- a/src/npc/descriptions/skills.js
+++ b/src/npc/descriptions/skills.js
@@ -74,4 +74,3 @@ App.Desc.skills = function(slave) {
 	}
 	return r.join(" ");
 };
-
diff --git a/src/npc/generate/generateGenetics.js b/src/npc/generate/generateGenetics.js
index 7ce11163d4acf295dd2900b3a47dd2d270b437bd..53f643a11b35337348759633be2d1a1dd5062ba9 100644
--- a/src/npc/generate/generateGenetics.js
+++ b/src/npc/generate/generateGenetics.js
@@ -1369,6 +1369,7 @@ globalThis.generateChild = function(mother, ovum, incubator = false) {
 		child.skill.oral = 0;
 		child.skill.anal = 0;
 		child.skill.vaginal = 0;
+		child.skill.penetrative = 0;
 		child.accent = 4;
 		child.canRecruit = 0;
 		child.hStyle = "messy";
diff --git a/src/npc/generate/generateLeadershipSlave.js b/src/npc/generate/generateLeadershipSlave.js
index 0f395edb91ab4d2af8cba9d71e6bea106e2b267f..2168178add0dca058ed08ffdbb417b911af0cb05 100644
--- a/src/npc/generate/generateLeadershipSlave.js
+++ b/src/npc/generate/generateLeadershipSlave.js
@@ -4,6 +4,7 @@ globalThis.generateLeadershipSlave = function(input, location) {
 			slave.dick = dick;
 			slave.scrotum = slave.balls = balls;
 			slave.prostate = prostate;
+			slave.skill.penetrative = 100;
 		}
 	};
 
diff --git a/src/npc/generate/generateMarketSlave.js b/src/npc/generate/generateMarketSlave.js
index 6149f06a9e3d0e3a14ce9efd5a1e32d245ce2f01..5673c3b2a6dfa2d45c080f6e51c33a59a61f2213 100644
--- a/src/npc/generate/generateMarketSlave.js
+++ b/src/npc/generate/generateMarketSlave.js
@@ -187,6 +187,9 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1
 				} else if (slave.vagina === 0) {
 					slave.skill.vaginal = Math.clamp(slave.skill.vaginal, 15, 100);
 				}
+				if (canAchieveErection(slave)) {
+					slave.skill.penetrative = Math.clamp(slave.skill.penetrative, 15 * V.corp.SpecSexEd, 100);
+				}
 				if (V.corp.SpecSexEd === 1) {
 					r += `Trainees spend many hours learning sexual competence. `;
 				} else if (V.corp.SpecSexEd === 2) {
@@ -254,6 +257,7 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1
 				r += `The corporation removes dicks where possible. `;
 				slave.dick = 0;
 				slave.prostate = 0;
+				slave.skill.penetrative = Math.clamp(slave.skill.penetrative - 15, 0, 100);
 			}
 			if (V.corp.SpecBalls === 1 && slave.dick > 0) {
 				r += `The corporation adds balls where needed. `;
@@ -657,6 +661,7 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1
 						slave.muscles += jsRandom(0, 20);
 					}
 				}
+				slave.skill.penetrative += Math.clamp(neighbor.prosperity / 2, 15, 100);
 			} else if (neighbor.FSGenderFundamentalist > 50) {
 				r += `Fertile slaves from there almost never appear without swollen bellies and sensitive nipples. `;
 				if (slave.preg < 0) {
@@ -779,6 +784,8 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1
 					slave.skill.vaginal += Math.clamp(neighbor.prosperity / 2, 20, 100);
 					slave.skill.vaginal = Math.clamp(slave.skill.vaginal, 50, 100);
 				}
+				slave.skill.penetrative += Math.clamp(neighbor.prosperity / 2, 20, 100);
+				slave.skill.penetrative = Math.clamp(slave.skill.penetrative, 25, 100);
 				if (slave.anus > 0) {
 					slave.skill.anal += Math.clamp(neighbor.prosperity / 2, 20, 100);
 					slave.skill.anal = Math.clamp(slave.skill.anal, 50, 100);
@@ -1270,12 +1277,13 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1
 				slave.counter.mammary += jsRandom(0, 300);
 			}
 			slave.skill.vaginal = jsRandom(80, 100);
+			slave.skill.penetrative = jsRandom(80, 100);
 			slave.skill.oral = jsRandom(80, 100);
 			slave.skill.anal = jsRandom(80, 100);
 			slave.skill.whoring = jsRandom(80, 100);
 			slave.skill.entertainment = jsRandom(80, 100);
 			slave.slaveName = `WCPU-${model}`;
-			slave.slaveSurname = `#${slave.skill.vaginal}${slave.skill.oral}${slave.skill.anal}${slave.skill.whoring}${slave.skill.entertainment}-${slave.intelligence} `;
+			slave.slaveSurname = `#${slave.skill.vaginal}${slave.skill.penetrative}${slave.skill.oral}${slave.skill.anal}${slave.skill.whoring}${slave.skill.entertainment}-${slave.intelligence} `;
 			slave.birthName = "";
 			slave.birthSurname = "";
 			if (model === "BG") {
@@ -1423,6 +1431,7 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1
 				slave.preg = 0;
 				SetBellySize(slave);
 			}
+			slave.skill.penetrative = 0;
 			slave.skill.anal = 0;
 			slave.anus = 0;
 			slave.skill.oral = 0;
@@ -1449,6 +1458,7 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1
 					SetBellySize(slave);
 				}
 			}
+			slave.skill.penetrative = 0;
 			if (jsRandom(1, 2) === 1) {
 				slave.skill.anal = 0;
 				slave.anus = 0;
@@ -1834,6 +1844,7 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1
 			slave.weight = 0;
 			slave.waist = jsRandom(-10, 30);
 			slave.skill.vaginal = 0;
+			slave.skill.penetrative = 0;
 			slave.skill.oral = 0;
 			slave.skill.anal = 0;
 			slave.skill.whoring = 0;
@@ -1917,6 +1928,7 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1
 				slave.balls = jsRandom(19, 30);
 				slave.scrotum = 10;
 				slave.prostate = 2;
+				slave.skill.penetration = 15;
 				slave.weight = jsRandom(10, 30);
 				slave.waist = jsRandom(0, 100);
 				slave.muscles = jsRandom(80, 100);
@@ -2209,6 +2221,7 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1
 				slave.shoulders = 1;
 			}
 			slave.skill.vaginal = 100;
+			slave.skill.penetrative = 100;
 			slave.skill.oral = 100;
 			slave.skill.anal = 100;
 			slave.skill.whoring = 15;
@@ -3357,6 +3370,7 @@ globalThis.generateMarketSlave = function(market = "kidnappers", numArcology = 1
 					slave.skill.whoring = jsRandom(15, 30);
 					slave.skill.anal = jsRandom(15, 30);
 					slave.skill.oral = jsRandom(15, 30);
+					slave.skill.penetrative = jsRandom(15, 30);
 					if (slave.vagina > 0) {
 						slave.skill.vaginal = jsRandom(15, 30);
 						if (slave.vaginaLube === 0) {
diff --git a/src/npc/generate/generateNewSlaveJS.js b/src/npc/generate/generateNewSlaveJS.js
index 5c4612357e97ab166ee2303b9b626587059f2782..2921544c7fee615fbb5e4264cde3cb88e8a92fdf 100644
--- a/src/npc/generate/generateNewSlaveJS.js
+++ b/src/npc/generate/generateNewSlaveJS.js
@@ -1697,6 +1697,11 @@ globalThis.GenerateNewSlave = (function() {
 	function generateSkills() {
 		slave.skill.vaginal = (slave.vagina <= 0 ? 0 : jsRandom(0, 15));
 		slave.skill.anal = (slave.anus === 0 ? 0 : jsRandom(0, 15));
+		if (slave.pubertyXY === 1 || slave.attrXX > 70) {
+			slave.skill.penetrative = jsRandom(10, 35);
+		} else {
+			slave.skill.penetrative = (canAchieveErection(slave) || slave.clit >= 3 ? jsRandom(0, 15) : 0);
+		}
 		slave.skill.oral = jsRandom(0, 15);
 		slave.skill.entertainment = jsRandom(0, 15);
 		slave.skill.whoring = jsRandom(0, 15);
diff --git a/src/npc/generate/generateRelatedSlave.js b/src/npc/generate/generateRelatedSlave.js
index 39367d2c834f71cefc5250609e4109874dfd2ad0..e725971a589c21b7eb6114f862621cf796738ff3 100644
--- a/src/npc/generate/generateRelatedSlave.js
+++ b/src/npc/generate/generateRelatedSlave.js
@@ -534,6 +534,10 @@ globalThis.generateRelatedSlave = (function() {
 		slave.ovaries = 1;
 		slave.preg = -1; // might get pregnant from repop check later on anyway
 
+		// swap penetrative skill for vaginal
+		slave.skill.vaginal = slave.skill.penetrative;
+		slave.skill.penetrative = 0;
+
 		// swap attraction
 		[slave.attrXX, slave.attrXY] = [slave.attrXY, slave.attrXX];
 
@@ -594,6 +598,10 @@ globalThis.generateRelatedSlave = (function() {
 		slave.scrotum = slave.balls;
 		slave.prostate = 1;
 
+		// swap vaginal skill for penetrative
+		slave.skill.penetrative = slave.skill.vaginal;
+		slave.skill.vaginal = 0;
+
 		// swap attraction
 		[slave.attrXX, slave.attrXY] = [slave.attrXY, slave.attrXX];
 
diff --git a/src/npc/generate/lawCompliance.js b/src/npc/generate/lawCompliance.js
index 9e2aa25609226157fe957f6d77115ee349c497a8..1701edb3182a6d17a3cb1d8e2e4b89b3f790b0f4 100644
--- a/src/npc/generate/lawCompliance.js
+++ b/src/npc/generate/lawCompliance.js
@@ -347,6 +347,9 @@ App.Desc.lawCompliance = function(slave, market = 0) {
 		if (slave.vagina >= 0) {
 			slave.skill.vaginal = Math.clamp(slave.skill.vaginal + 50, 50, 100);
 		}
+		if ((canAchieveErection(slave) || slave.clit >= 3) && penetrativeSocialUse(slave) >= 40) {
+			slave.skill.penetrative = Math.clamp(slave.skill.penetrative + 50, 50, 100);
+		}
 		slave.skill.anal = Math.clamp(slave.skill.anal + 50, 50, 100);
 		slave.skill.oral = Math.clamp(slave.skill.oral + 50, 50, 100);
 		slave.skill.entertainment = Math.clamp(slave.skill.entertainment + 50, 50, 100);
diff --git a/src/npc/generate/newSlaveIntro.js b/src/npc/generate/newSlaveIntro.js
index 8242e742319335e179038b69c50d8940b783d5ac..905bc3e215e07893fb8b5b89df144959cb49b339 100644
--- a/src/npc/generate/newSlaveIntro.js
+++ b/src/npc/generate/newSlaveIntro.js
@@ -1492,7 +1492,7 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest =
 							r.push(`You gesture towards ${slave2.slaveName}. ${He2} is`);
 							if (slave2.intelligence + slave2.intelligenceImplant > 15) {
 								r.push(`bright enough`);
-							} else if ((slave2.skill.vaginal + slave2.skill.anal + slave2.skill.oral) > 100) {
+							} else if ((adjustedPenSkill(slave2) + slave2.skill.vaginal + slave2.skill.anal + slave2.skill.oral) > 100) {
 								r.push(`skilled enough`);
 							} else {
 								r.push(`obedient enough`);
@@ -1561,7 +1561,7 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest =
 							r.push(`You gesture towards ${slave2.slaveName}. ${He2} is`);
 							if (slave2.intelligence + slave2.intelligenceImplant > 15) {
 								r.push(`bright enough`);
-							} else if (((slave2.skill.vaginal + slave2.skill.anal + slave2.skill.oral) > 100)) {
+							} else if (((adjustedPenSkill(slave2) + slave2.skill.vaginal + slave2.skill.anal + slave2.skill.oral) > 100)) {
 								r.push(`skilled enough`);
 							} else {
 								r.push(`obedient enough`);
@@ -1630,7 +1630,7 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest =
 							r.push(`You gesture towards ${slave2.slaveName}. ${He2} is`);
 							if (slave2.intelligence + slave2.intelligenceImplant > 15) {
 								r.push(`bright enough`);
-							} else if (((slave2.skill.vaginal + slave2.skill.anal + slave2.skill.oral) > 100)) {
+							} else if (((adjustedPenSkill(slave2) + slave2.skill.vaginal + slave2.skill.anal + slave2.skill.oral) > 100)) {
 								r.push(`skilled enough`);
 							} else {
 								r.push(`obedient enough`);
@@ -1690,7 +1690,7 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest =
 							r.push(`You gesture towards ${slave2.slaveName}. ${He2} is`);
 							if (slave2.intelligence + slave2.intelligenceImplant > 15) {
 								r.push(`bright enough`);
-							} else if ((slave2.skill.vaginal + slave2.skill.anal + slave2.skill.oral) > 100) {
+							} else if ((adjustedPenSkill(slave2) + slave2.skill.vaginal + slave2.skill.anal + slave2.skill.oral) > 100) {
 								r.push(`skilled enough`);
 							} else {
 								r.push(`obedient enough`);
@@ -1759,7 +1759,7 @@ App.UI.newSlaveIntro = function(slave, slave2, {tankBorn = false, momInterest =
 							r.push(`You gesture towards ${slave2.slaveName}. ${He2} is`);
 							if (slave2.intelligence + slave2.intelligenceImplant > 15) {
 								r.push(`bright enough`);
-							} else if (((slave2.skill.vaginal + slave2.skill.anal + slave2.skill.oral) > 100)) {
+							} else if (((adjustedPenSkill(slave2) + slave2.skill.vaginal + slave2.skill.anal + slave2.skill.oral) > 100)) {
 								r.push(`skilled enough`);
 							} else {
 								r.push(`obedient enough`);
diff --git a/src/npc/interaction/fFeelings.js b/src/npc/interaction/fFeelings.js
index 5f0d9bbbc8ac8a9451a1d5b6e9831e99fdfc18e5..3f0b86f4e1a888779ef0ba24822499e497a72e6a 100644
--- a/src/npc/interaction/fFeelings.js
+++ b/src/npc/interaction/fFeelings.js
@@ -1808,7 +1808,9 @@ App.Interact.fFeelings = function(slave) {
 		function skills() {
 			const text = [];
 
-			if ((slave.skill.oral + slave.skill.anal) >= 120 && slave.vagina === -1) {
+			if ((adjustedPenSkill(slave, true)) >= 100 && canPenetrate(slave)) {
+				text.push(`${Spoken(slave, `I'm really proud of how good I am putting my dick to use; it's a little surprising how many people want it.`)}`);
+			} else if ((slave.skill.oral + slave.skill.anal) >= 120 && slave.vagina === -1) {
 				text.push(`${Spoken(slave, `I'm really proud of my sex skills; it's nice to be good at what you do. Without a cunt my poor`)}`);
 				if (slave.anus > 2) {
 					text.push(`${Spoken(slave, `asspussy`)}`);
@@ -1818,7 +1820,7 @@ App.Interact.fFeelings = function(slave) {
 					text.push(`${Spoken(slave, `little anus`)}`);
 				}
 				text.push(`${Spoken(slave, `does double duty, but I can take it.`)}`);
-			} else if ((slave.skill.oral + slave.skill.vaginal + slave.skill.anal) >= 180) {
+			} else if ((slave.skill.oral + slave.skill.vaginal + slave.skill.anal + adjustedPenSkill(slave, true)) >= 180) {
 				text.push(`${Spoken(slave, `I'm really proud of my sex skills; it's nice to be good at what you do.`)}`);
 			} else if (slave.skill.whoring >= 100) {
 				text.push(`${Spoken(slave, `I'm really proud of my whoring skills; prostitution is a job I know I can do well.`)}`);
@@ -1834,6 +1836,8 @@ App.Interact.fFeelings = function(slave) {
 				text.push(`${Spoken(slave, `I wish I were better at anal; if I could learn to relax getting buttfucked wouldn't hurt so much.`)}`);
 			} else if (slave.skill.vaginal <= 30 && slave.vagina > 0) {
 				text.push(`${Spoken(slave, `I wish I were better at sex; sometimes all I can think to do is just lie there.`)}`);
+			} else if (slave.skill.penetrative <= 10 && canPenetrate(slave) && slave.counter.penetrative > 0) {
+				text.push(`${Spoken(slave, `I wish I were better at sex; I got made fun of last time over how awkward I was getting it in.`)}`);
 			} else if (slave.skill.oral <= 30) {
 				if (slave.counter.oral > 0) {
 					text.push(`${Spoken(slave, `I wish I were better at blowjobs; it would be nice not to gag so much.`)}`);
diff --git a/src/npc/startingGirls/startingGirls.js b/src/npc/startingGirls/startingGirls.js
index 930b0f8f3fc1167703ac59db7095952ef6cc7469..82db30eb3d581ac85531a558716029838d9d8fb4 100644
--- a/src/npc/startingGirls/startingGirls.js
+++ b/src/npc/startingGirls/startingGirls.js
@@ -45,6 +45,7 @@ App.StartingGirls.generate = function(params) {
 	slave.skill.oral = mapValue(slave.skill.oral, App.Data.StartingGirls.skill);
 	slave.skill.anal = mapValue(slave.skill.anal, App.Data.StartingGirls.skill);
 	slave.skill.vaginal = mapValue(slave.skill.vaginal, App.Data.StartingGirls.skill);
+	slave.skill.penetrative = mapValue(slave.skill.penetrative, App.Data.StartingGirls.skill);
 	slave.skill.whoring = mapValue(slave.skill.whoring, App.Data.StartingGirls.skill);
 	slave.skill.entertainment = mapValue(slave.skill.entertainment, App.Data.StartingGirls.skill);
 
@@ -121,6 +122,9 @@ App.StartingGirls.cleanup = function(slave) {
 	} else if ((slave.vagina > 2 && slave.skill.vaginal <= 10) || (slave.vagina === 0 && slave.skill.vaginal > 30)) {
 		slave.skill.vaginal = 15;
 	}
+	if (slave.physicalAge >= slave.pubertyAgeXY + 2 && slave.skill.penetrative <= 10) {
+		slave.skill.penetrative = 15;
+	}
 };
 
 /** Apply starting girl PC career bonus
@@ -139,6 +143,10 @@ App.StartingGirls.applyCareerBonus = function(slave) {
 		}
 		if ((seed > 0) && (slave.skill.vaginal < 60) && (slave.vagina > -1) && ((slave.vagina > 0) || (slave.skill.vaginal <= 10))) {
 			slave.skill.vaginal += 20;
+			seed--;
+		}
+		if ((seed > 0) && (slave.skill.penetrative < 60) && ((canPenetrate(slave) || slave.skill.penetrative <= 10))) {
+			slave.skill.penetrative +=20;
 		}
 	}
 
@@ -1533,6 +1541,7 @@ App.StartingGirls.lower = function(slave, cheat = false) {
 				slave.balls = 0;
 				slave.pubertyXY = 0;
 				slave.pubertyAgeXY = V.potencyAge;
+				slave.skill.penetrative = 0;
 			})
 			.addValue("Tiny", 1, () => slave.clit = 0)
 			.addValue("Small", 2, () => slave.clit = 0)
@@ -2013,6 +2022,13 @@ App.StartingGirls.skills = function(slave, cheat = false) {
 		App.StartingGirls.addSet(option, App.Data.StartingGirls.skill);
 	}
 
+	App.StartingGirls.addSet(
+		options.addOption("Penetrative sex", "penetrative", slave.skill),
+		App.Data.StartingGirls.skill);
+		if (penetrativeSocialUse() < 20) {
+			options.addComment("Penetrative skills are usually not considered valuable.");
+		}
+
 	App.StartingGirls.addSet(
 		options.addOption("Prostitution", "whoring", slave.skill),
 		App.Data.StartingGirls.skill);
@@ -2026,7 +2042,7 @@ App.StartingGirls.skills = function(slave, cheat = false) {
 
 	// skill warning
 	const totalSkill = slave.skill.whoring + slave.skill.entertainment + slave.skill.vaginal
-		+ slave.skill.anal + slave.skill.oral + slave.skill.combat;
+		+ slave.skill.penetrative + slave.skill.anal + slave.skill.oral + slave.skill.combat;
 
 	if (totalSkill > 200 && !cheat) {
 		let comment = ["Starting slaves incur"];
diff --git a/src/npc/startingGirls/startingGirlsPassage.js b/src/npc/startingGirls/startingGirlsPassage.js
index dbdacc91f568f7bc8a957fb3f03962f3c7838cf6..0a9908a0df9e037fb908c5e43a8af03c9ee86348 100644
--- a/src/npc/startingGirls/startingGirlsPassage.js
+++ b/src/npc/startingGirls/startingGirlsPassage.js
@@ -135,6 +135,7 @@ App.StartingGirls.passage = function() {
 						V.activeSlave.skill.anal = 0;
 						V.activeSlave.skill.oral = 0;
 						V.activeSlave.skill.vaginal = 0;
+						V.activeSlave.skill.penetrative = 0;
 						V.activeSlave.skill.whoring = 0;
 						V.activeSlave.skill.entertainment = 0;
 						V.activeSlave.skill.combat = 0;
@@ -167,6 +168,7 @@ App.StartingGirls.passage = function() {
 							V.activeSlave.skill.anal = 0;
 							V.activeSlave.skill.oral = 0;
 							V.activeSlave.skill.vaginal = 0;
+							V.activeSlave.skill.penetrative = 0;
 							V.activeSlave.skill.whoring = 0;
 							V.activeSlave.skill.entertainment = 0;
 							V.activeSlave.skill.combat = 0;
diff --git a/src/npc/surgery/surgery.js b/src/npc/surgery/surgery.js
index 6b23d69b6311e59fd3ea818f6e96507545f59c38..62969500cee4622e729da384eb0c14e3b4e533ae 100644
--- a/src/npc/surgery/surgery.js
+++ b/src/npc/surgery/surgery.js
@@ -525,7 +525,7 @@ globalThis.surgeryAmp = function(slave, part, cheat = false) {
 		case "dick":
 			slave.dick = 0;
 			slave.foreskin = 0;
-			slave.skill.vaginal = 0;
+			slave.skill.penetrative = Math.clamp(slave.skill.penetrative -= 30, 0, 100);
 			slave.dickTat = 0;
 			slave.dickAccessory = "none";
 			slave.chastityPenis = 0;
diff --git a/src/player/js/enslavePlayer.js b/src/player/js/enslavePlayer.js
index aa1d2becfbbbfc5e21620ae2577781eb2b8fd846..19ab61ab9ea983321f1b6f97a30f4400c13ed33d 100644
--- a/src/player/js/enslavePlayer.js
+++ b/src/player/js/enslavePlayer.js
@@ -5,7 +5,8 @@ globalThis.convertPlayerToSlave = function(player, badEnd = "boring") {
 	deepAssign(slave, player);
 
 	/* initialize slave variables */
-	slave.skill.vaginal = 100;
+	slave.skill.vaginal = slave.vagina > 0 ? 100 : 0;
+	slave.skill.penetrative = 100;
 	slave.skill.oral = 100;
 	slave.skill.anal = 100;
 	slave.skill.whoring = 0;
diff --git a/src/player/personalAttentionSelect.js b/src/player/personalAttentionSelect.js
index 5d9b7b957f57e735fe5031452495809c33305003..d50f875b48e998dd5f60df1f3b01f36ef5213bd1 100644
--- a/src/player/personalAttentionSelect.js
+++ b/src/player/personalAttentionSelect.js
@@ -633,6 +633,7 @@ App.UI.Player.personalAttention = function() {
 					]));
 				} else if (slave.skill.anal >= 100 &&
 					slave.skill.oral >= 100 &&
+					slave.skill.penetrative >= 30 &&
 					slave.skill.whoring >= whoreSkillCap &&
 					slave.skill.entertainment >= whoreSkillCap) {
 					if (slave.skill.vaginal >= 100) {
diff --git a/src/pregmod/FCTV/FCTVshows.js b/src/pregmod/FCTV/FCTVshows.js
index 5b966375b5826a8089ad3f86a4458db9a260c372..3b5bd7345ae2230c1e75054b3b37f3fb27e17a2c 100644
--- a/src/pregmod/FCTV/FCTVshows.js
+++ b/src/pregmod/FCTV/FCTVshows.js
@@ -326,6 +326,7 @@ App.Data.FCTV.actors = {
 		slave.trust = jsRandom(50, 80);
 		slave.scrotum = slave.balls;
 		slave.skill.oral = jsRandom(30, 60);
+		slave.skill.penetrative = jsRandom(0, 50);
 		slave.skill.anal = jsRandom(20, 50);
 		slave.skill.whoring = jsRandom(0, 25);
 		slave = FCTV.FinalTouches(slave);
@@ -357,6 +358,7 @@ App.Data.FCTV.actors = {
 		slave.devotion = jsRandom(60, 90);
 		slave.trust = jsRandom(50, 80);
 		slave.skill.oral = jsRandom(40, 80);
+		slave.skill.penetrative = jsRandom(0, 20);
 		slave.skill.anal = jsRandom(40, 80);
 		slave.skill.whoring = jsRandom(40, 70);
 		slave = FCTV.FinalTouches(slave);
diff --git a/src/pregmod/eliteBreedingExam.js b/src/pregmod/eliteBreedingExam.js
index 6c00773e2f19d75303e7bef8d9c04d9a52283c75..a9fe9ac7085e1655dde5b59b4cb693c45acd8e42 100644
--- a/src/pregmod/eliteBreedingExam.js
+++ b/src/pregmod/eliteBreedingExam.js
@@ -72,7 +72,7 @@ App.Interact.eliteBreedingExam = function(slave = null) {
 	} else if (V.arcologies[0].FSSlaveProfessionalism > 20) {
 		checks.push(
 			[
-				slave => slave.skill.vaginal + slave.skill.anal + slave.skill.oral + slave.skill.entertainment + slave.skill.whoring >= (eliteAngered ? 500 : 400),
+				slave => slave.skill.vaginal + adjustedPenSkill(slave) + slave.skill.anal + slave.skill.oral + slave.skill.entertainment + slave.skill.whoring >= (eliteAngered ? 500 : 400),
 				`Must be capable of mastering skills`
 			],
 			[