From 0a86b1812e2ac6bce1124b173d308ac6ff7a624e Mon Sep 17 00:00:00 2001
From: lowercasedonkey <lowercasedonkey@gmail.com>
Date: Tue, 29 Dec 2020 23:00:56 -0500
Subject: [PATCH] Custom vag toys

---
 .../backwardsCompatibility.js                 |   1 +
 src/facilities/toyShop/toyShop.js             | 222 +++++++++++++++++-
 src/interaction/siWardrobe.js                 |  15 +-
 .../descriptions/crotch/vaginalAccessory.js   |  16 +-
 4 files changed, 241 insertions(+), 13 deletions(-)

diff --git a/src/data/backwardsCompatibility/backwardsCompatibility.js b/src/data/backwardsCompatibility/backwardsCompatibility.js
index 19182f0e0c9..1cdba489fbc 100644
--- a/src/data/backwardsCompatibility/backwardsCompatibility.js
+++ b/src/data/backwardsCompatibility/backwardsCompatibility.js
@@ -1054,6 +1054,7 @@ App.Update.globalVariables = function(node) {
 					break;
 				case "construction":
 					V.trinkets.push("the blueprints of a proto-arcology you helped construct");
+					break;
 				case "worksite helper":
 					V.trinkets.push("the hardhat you used to wear around worksites");
 					break;
diff --git a/src/facilities/toyShop/toyShop.js b/src/facilities/toyShop/toyShop.js
index 9cc2b7269ad..2a947a65554 100644
--- a/src/facilities/toyShop/toyShop.js
+++ b/src/facilities/toyShop/toyShop.js
@@ -6,7 +6,12 @@ App.UI.toyShop = function() {
 	let buttPlugName;
 	let buttPlugData;
 	let selectedPlug;
-	init();
+
+	let vaginalAccName;
+	let vaginalAccData;
+	let selectedVaginalAcc;
+	initPlug();
+	initVaginalAcc();
 
 	container.append(createPage());
 	return container;
@@ -14,11 +19,12 @@ App.UI.toyShop = function() {
 	function createPage() {
 		const el = new DocumentFragment();
 		el.append(intro());
+		el.append(vaginalAccessory());
 		el.append(buttPlugs());
 		return el;
 	}
 
-	function init() {
+	function initPlug() {
 		buttPlugName = "";
 		buttPlugData = {
 			name: "",
@@ -27,6 +33,15 @@ App.UI.toyShop = function() {
 		};
 	}
 
+	function initVaginalAcc() {
+		vaginalAccName = "";
+		vaginalAccData = {
+			name: "",
+			width: 1,
+			length: 1
+		};
+	}
+
 	function intro() {
 		const el = new DocumentFragment();
 		App.UI.DOM.appendNewElement("h1", el, "Toy Shop");
@@ -34,13 +49,212 @@ App.UI.toyShop = function() {
 		return el;
 	}
 
+	function vaginalAccessory() {
+		const el = new DocumentFragment();
+		let linkArray;
+		App.UI.DOM.appendNewElement("h2", el, "Vaginal Accessories");
+		const select = App.UI.DOM.appendNewElement("div", el, App.UI.DOM.link("Start a new design", () => {
+			initVaginalAcc();
+			refresh();
+		}));
+		if (V.customItem.vaginalAccessory.size > 0) {
+			select.append(selectDesign());
+		}
+		el.append(create());
+		return el;
+
+		function create() {
+			const el = new DocumentFragment();
+			const existingDesign = V.customItem.vaginalAccessory.get(vaginalAccName);
+			if (existingDesign) {
+				el.append(descLocked());
+			} else {
+				el.append(desc());
+			}
+			if (vaginalAccData.name) {
+				el.append(title());
+			}
+			el.append(
+				width(),
+				length(),
+			);
+
+			if (existingDesign) {
+				const build = App.UI.DOM.appendNewElement("div", el, `Send updated design to production and make sure all appropriate slaves are updated `);
+				const linkArray = [];
+				linkArray.push(
+					App.UI.DOM.link(
+						"Update the mold",
+						() => { buildVA(); }
+					)
+				);
+
+				linkArray.push(
+					App.UI.DOM.link(
+						`Recall "${vaginalAccName}"`,
+						() => { deleteVA(); }
+					)
+				);
+				build.append(App.UI.DOM.generateLinksStrip(linkArray));
+			} else if (vaginalAccName && vaginalAccData.name){
+				el.append(apply());
+			}
+
+			return el;
+
+			function descLocked() {
+				return App.UI.DOM.makeElement("div", `Description has already been selected for this model: "${vaginalAccName}"`);
+			}
+		}
+		function selectDesign() {
+			const el = new DocumentFragment();
+			const choice = App.UI.DOM.appendNewElement("span", el, ` or choose an existing design to edit `);
+			const select = App.UI.DOM.appendNewElement("select", choice);
+			let matchFound = false;
+			for (const [key, values] of V.customItem.buttplug) {
+				const option = App.UI.DOM.appendNewElement("option", select, values.name);
+				option.value = key;
+				if (option.value === vaginalAccName) {
+					option.selected = true;
+					matchFound = true;
+				}
+			}
+			if (!matchFound) {
+				select.selectedIndex = -1;
+			}
+			select.onchange = () => {
+				const O = select.options[select.selectedIndex];
+				selectedVaginalAcc = O.value;
+				vaginalAccName = selectedVaginalAcc;
+				selectedPlug = V.customItem.buttplug.get(selectedVaginalAcc);
+				refresh();
+			};
+			return el;
+		}
+
+		function desc() {
+			const value = App.UI.DOM.makeElement("div", `Enter shape here as it will appear in descriptions `);
+			value.append(App.UI.DOM.makeTextBox(
+				vaginalAccName,
+				v => {
+					vaginalAccName = v;
+					vaginalAccData.name = capFirstChar(v);
+					refresh();
+				}
+			));
+			App.UI.DOM.appendNewElement("span", value, ` Your slave has a standard ${vaginalAccName ? vaginalAccName : `pink dildo`} wedged firmly in their asshole.`, "note");
+			return value;
+		}
+
+		function title() {
+			const title = App.UI.DOM.makeElement("div", `Enter title as it will appear in lists of choices `);
+			title.append(App.UI.DOM.makeTextBox(
+				vaginalAccData.name,
+				v => {
+					vaginalAccData.name = capFirstChar(v);
+					refresh();
+				}
+			));
+			return title;
+		}
+
+		function width() {
+			const widthOptions = new Map([
+				["standard", 1],
+				["large", 2],
+				["huge", 3],
+			]);
+			const width = App.UI.DOM.makeElement("div", `Select width `);
+			linkArray = [];
+			for (const [key, value] of widthOptions) {
+				if (vaginalAccData.width === value) {
+					linkArray.push(
+						App.UI.DOM.disabledLink(
+							key,
+							["Currently selected"]
+						)
+					);
+				} else {
+					linkArray.push(
+						App.UI.DOM.link(
+							key,
+							() => {
+								vaginalAccData.width = value;
+								refresh();
+							}
+						)
+					);
+				}
+			}
+			width.append(App.UI.DOM.generateLinksStrip(linkArray));
+			return width;
+		}
+
+		function length() {
+			const lengthOptions = new Map([
+				["standard", 1],
+				["long", 2],
+			]);
+			const length = App.UI.DOM.makeElement("div", `Select length `);
+			linkArray = [];
+			for (const [key, value] of lengthOptions) {
+				if (vaginalAccData.length === value) {
+					linkArray.push(
+						App.UI.DOM.disabledLink(
+							key,
+							["Currently selected"]
+						)
+					);
+				} else {
+					linkArray.push(
+						App.UI.DOM.link(
+							key,
+							() => {
+								vaginalAccData.length = value;
+								refresh();
+							}
+						)
+					);
+				}
+			}
+			length.append(App.UI.DOM.generateLinksStrip(linkArray));
+			return length;
+		}
+
+		function buildVA() {
+			V.customItem.vaginalAccessory.set(vaginalAccName, vaginalAccData);
+			initVaginalAcc();
+			refresh();
+		}
+
+		function apply() {
+			const build = App.UI.DOM.appendNewElement("div", el, `Send design to production and make available for all slaves `);
+			build.append(
+				App.UI.DOM.link(
+					"Start the mold",
+					() => { buildVA(); }
+				)
+			);
+			return build;
+		}
+
+		function deleteVA() {
+			V.customItem.vaginalAccessory.delete(vaginalAccName);
+			for (const slave of V.slaves) {
+				if (slave.vaginalAccessory === vaginalAccName) {
+					slave.vaginalAccessory = "none";
+				}
+			}
+			refresh();
+		}
+	}
 
 	function buttPlugs() {
 		const el = new DocumentFragment();
 		let linkArray;
 		App.UI.DOM.appendNewElement("h2", el, "Buttplugs");
 		const select = App.UI.DOM.appendNewElement("div", el, App.UI.DOM.link("Start a new design", () => {
-			init();
+			initPlug();
 			refresh();
 		}));
 		if (V.customItem.buttplug.size > 0) {
@@ -209,7 +423,7 @@ App.UI.toyShop = function() {
 
 		function buildPlug() {
 			V.customItem.buttplug.set(buttPlugName, buttPlugData);
-			init();
+			initPlug();
 			refresh();
 		}
 
diff --git a/src/interaction/siWardrobe.js b/src/interaction/siWardrobe.js
index 17ab18418f7..0082491c1a4 100644
--- a/src/interaction/siWardrobe.js
+++ b/src/interaction/siWardrobe.js
@@ -678,7 +678,20 @@ App.UI.SlaveInteract.wardrobe = function(slave) {
 		App.UI.DOM.appendNewElement("div", el, generateRows(bulletArray, "vaginalAccessory", true), "choices");
 		App.UI.DOM.appendNewElement("div", el, generateRows(normalArray, "vaginalAccessory", true), "choices");
 		App.UI.DOM.appendNewElement("div", el, generateRows(longArray, "vaginalAccessory", true), "choices");
-
+		if (V.customItem.vaginalAccessory.size > 0) {
+			let customArray = [];
+			for (const [key, object] of V.customItem.vaginalAccessory) {
+				const reshapedItem = {
+					text: object.name,
+					updateSlave: {vaginalAccessory: key},
+				};
+				if (object.fs) {
+					reshapedItem.FS = object.fs.unlocks;
+				}
+				customArray.push(reshapedItem);
+			}
+			App.UI.DOM.appendNewElement("div", el, generateRows(customArray, "vaginalAccessory", false), "choices");
+		}
 		return el;
 	}
 
diff --git a/src/npc/descriptions/crotch/vaginalAccessory.js b/src/npc/descriptions/crotch/vaginalAccessory.js
index 74d9d8c5f6f..cc054a389f1 100644
--- a/src/npc/descriptions/crotch/vaginalAccessory.js
+++ b/src/npc/descriptions/crotch/vaginalAccessory.js
@@ -26,9 +26,9 @@ App.Desc.vaginalAccessory = function(slave) {
 		case 1:
 			if (dildo.length === 1) {
 				/* TODO: these may need to be updated for slaves with gaping+ vaginas */
-				r.push(`${His} pussy is filled by a dildo ${held}.`);
+				r.push(`${His} pussy is filled by a ${slave.vaginalAccessory} ${held}.`);
 			} else {
-				r.push(`${His} pussy is filled by a very long dildo ${held}. It noticeably bulges ${his} stomach.`);
+				r.push(`${His} pussy is filled by a very long ${slave.vaginalAccessory} ${held}. It noticeably bulges ${his} stomach.`);
 			}
 			break;
 		case 2:
@@ -41,33 +41,33 @@ App.Desc.vaginalAccessory = function(slave) {
 				r.push(`comfortably filled`);
 			}
 			if (dildo.length === 1) {
-				r.push(`by a large dildo ${held}.`);
+				r.push(`by a large ${slave.vaginalAccessory} ${held}.`);
 			} else {
-				r.push(`by a very long and large dildo ${held}. It noticeably bulges ${his} stomach.`);
+				r.push(`by a very long and large ${slave.vaginalAccessory} ${held}. It noticeably bulges ${his} stomach.`);
 			}
 			break;
 		case 3:
 			if (dildo.length === 1) {
 				if (slave.vagina < 4) {
-					r.push(`${His} pussy is filled to the breaking point by an enormous dildo.`);
+					r.push(`${His} pussy is filled to the breaking point by an enormous ${slave.vaginalAccessory}.`);
 					if (slave.fetish === "masochist" && slave.fetishKnown === 1 && slave.fetishStrength > 60) {
 						r.push(`${He} can barely move with the discomfort, but ${he} frequently climaxes with agony.`);
 					} else {
 						r.push(`${He} can barely move with the discomfort, and ${he} sometimes breaks down in tears at having ${his} cunt permanently stretched.`);
 					}
 				} else {
-					r.push(`${His} cavernous pussy is comfortably filled by a huge dildo.`);
+					r.push(`${His} cavernous pussy is comfortably filled by a huge ${slave.vaginalAccessory}.`);
 				}
 			} else {
 				if (slave.vagina < 4) {
-					r.push(`${His} pussy is filled to the breaking point by an enormously wide and long dildo. It noticeably bulges ${his} stomach.`);
+					r.push(`${His} pussy is filled to the breaking point by an enormously wide and long ${slave.vaginalAccessory}. It noticeably bulges ${his} stomach.`);
 					if (slave.fetish === "masochist" && slave.fetishKnown === 1 && slave.fetishStrength > 60) {
 						r.push(`${He} can barely move with the discomfort, but ${he} frequently climaxes with agony.`);
 					} else {
 						r.push(`${He} can barely move with the discomfort, and ${he} sometimes breaks down in tears at having ${his} cunt permanently stretched.`);
 					}
 				} else {
-					r.push(`${His} cavernous pussy is comfortably filled by an enormously wide and long dildo. It noticeably bulges ${his} stomach.`);
+					r.push(`${His} cavernous pussy is comfortably filled by an enormously wide and long ${slave.vaginalAccessory}. It noticeably bulges ${his} stomach.`);
 				}
 			}
 			if (slave.chastityVagina) {
-- 
GitLab