From 726fa2f31e640f15566d77b71e59eb5aa349df5c Mon Sep 17 00:00:00 2001
From: lowercasedonkey <lowercasedonkey@gmail.com>
Date: Mon, 30 Nov 2020 13:18:29 -0500
Subject: [PATCH] tats including custom

---
 .../bodyModification/bodyModification.js      | 220 ++++++++++++++++++
 src/npc/descriptions/describeTattoos.js       |   2 +-
 2 files changed, 221 insertions(+), 1 deletion(-)

diff --git a/src/facilities/bodyModification/bodyModification.js b/src/facilities/bodyModification/bodyModification.js
index 8589c0eac16..0a5bf22625c 100644
--- a/src/facilities/bodyModification/bodyModification.js
+++ b/src/facilities/bodyModification/bodyModification.js
@@ -15,6 +15,7 @@ App.UI.bodyModification = function(slave, cheat = false) {
 	let modReaction;
 	let scarApplied;
 	let brandApplied;
+	let tattooChoice;
 
 	container.append(createPage());
 	return container;
@@ -29,6 +30,7 @@ App.UI.bodyModification = function(slave, cheat = false) {
 			el.append(reaction());
 		}
 		el.append(piercings());
+		el.append(tattoos());
 		return el;
 	}
 
@@ -334,6 +336,224 @@ App.UI.bodyModification = function(slave, cheat = false) {
 		return el;
 	}
 
+	function tattoos() {
+		const el = new DocumentFragment();
+		let r = [];
+		let noTats;
+		const tattooLocations = new Map([
+			["shoulder", "shoulders"],
+			["lips", "lips"],
+			["breast", "boobs"],
+			["upper arm", "arms"],
+			["back", "back"],
+			["lower back", "stamp"],
+			["buttock", "butt"],
+			["vagina", "vagina"],
+			["dick", "dick"],
+			["anus", "anus"],
+			["thigh", "legs"]
+		]);
+		// DESCRIPTIONS
+		App.UI.DOM.appendNewElement("h2", el, "Tattoos");
+
+		for (const [name, place] of tattooLocations) {
+			r.push(App.UI.DOM.makeElement("div", App.Desc.tattoo(slave, name)));
+		}
+		if (r.length === 0) {
+			r.push(App.UI.DOM.makeElement("div", `${His} smooth ${slave.skin} skin is completely unmarked.`));
+			noTats = true;
+		}
+		App.Events.addNode(el, r);
+		r = [];
+
+		// Apply tattoos
+		r.push(`Choose a tattoo style:`);
+		const tattooChoiceNames = new Set([
+			"tribal patterns",
+			"flowers",
+			"counting",
+			"advertisements",
+			"rude words",
+			"degradation",
+			"Asian art",
+			"scenes",
+			"bovine patterns",
+			"permanent makeup",
+			"sacrilege",
+			"sacrament",
+			"possessive",
+			"paternalist",
+		]);
+		if (slave.anusTat !== 0) {
+			tattooChoiceNames.add("bleached");
+		}
+		let linkArray = [];
+		for (const style of tattooChoiceNames) {
+			if (tattooChoice === style) {
+				linkArray.push(App.UI.DOM.disabledLink(capFirstChar(style), ["Currently selected"]));
+			} else {
+				linkArray.push(
+					App.UI.DOM.link(
+						capFirstChar(style),
+						() => {
+							tattooChoice = style;
+							refresh();
+						}
+					)
+				);
+			}
+		}
+		if (!noTats) {
+			linkArray.push(
+				App.UI.DOM.link(
+					"Remove a tattoo",
+					() => {
+						tattooChoice = 0;
+						refresh();
+					}
+				)
+			);
+		}
+		r.push(App.UI.DOM.generateLinksStrip(linkArray));
+		App.Events.addNode(el, r, "div");
+		r = [];
+
+		// Determine parts that cannot be pierced
+		let validTattooLocations;
+		if (tattooChoice === "bleached") {
+			validTattooLocations = ["anus"];
+		} else {
+			validTattooLocations = Array.from(tattooLocations.keys());
+			if (!hasAnyNaturalArms(slave)) {
+				removeTattooLocation("upper arm");
+			}
+
+			if (!hasAnyNaturalArms(slave)) {
+				removeTattooLocation("thigh");
+			} else {
+				// There is a disagreement between description and application if we are talking about the leg or thigh.  Switch to leg now for application.
+				const index = validTattooLocations.indexOf("thigh");
+				validTattooLocations.splice(index, 1, "leg");
+			}
+
+			if (slave.dick === 0 || tattooChoice === "scenes") {
+				removeTattooLocation("dick");
+			}
+			if ((tattooChoice === "Asian art" || tattooChoice === "scenes") && slave.anusTat === "bleached") { // leave existing bleached anus alone
+				removeTattooLocation("anus");
+			}
+		}
+
+		function removeTattooLocation(location) {
+			const index = validTattooLocations.indexOf(location);
+			validTattooLocations.splice(index, 1);
+		}
+
+		if (tattooChoice === 0) {
+			r.push(`Clean the ink off of ${him}:`);
+		} else if (tattooChoice === "counting") {
+			r.push(`Add tallies of ${his} sexual exploits to ${him}:`);
+		} else if (tattooChoice === "bleached") {
+			r.push(`Bleach ${his}:`);
+		} else if (tattooChoice) {
+			r.push(`Add ${tattooChoice} to ${his}:`);
+		}
+		// Entire body
+		linkArray = [];
+		if (tattooChoice !== "bleached") {
+			linkArray.push(
+				App.UI.DOM.link(
+					"Entire body",
+					() => {
+						modReaction = "";
+						for (const location of validTattooLocations) {
+							if (slave[`${location}tattoo`] !== tattooChoice) {
+								applyTat(location);
+							}
+						}
+						refresh();
+					}
+				)
+			);
+		}
+		// Each individual tattoo
+		for (const location of validTattooLocations) {
+			if (slave[`${location}tattoo`] !== tattooChoice) {
+				linkArray.push(
+					App.UI.DOM.link(
+						capFirstChar(location),
+						() => {
+							modReaction = "";
+							applyTat(location);
+							refresh();
+						}
+					)
+				);
+			}
+		}
+		r.push(App.UI.DOM.generateLinksStrip(linkArray));
+		App.Events.addNode(el, r, "div");
+
+		// Custom
+		App.UI.DOM.appendNewElement("h3", el, "Custom Tattoos");
+		r = [];
+		for (const location of validTattooLocations) {
+			const varName = tattooLocations.get(location);
+			if (varName) {
+				r.push(App.UI.DOM.makeElement("div", `${capFirstChar(location)}: `));
+				r.push(
+					App.UI.DOM.makeElement(
+						"div",
+						App.UI.DOM.makeTextBox(
+							slave[`${varName}Tat`],
+							(v) => {
+								modReaction += App.Medicine.Modification.setTattoo(slave, varName, v);
+								refresh();
+							}
+						)
+					)
+				);
+			}
+		}
+
+		// Custom
+		r.push(App.UI.DOM.makeElement("div", `Custom: `));
+		r.push(
+			App.UI.DOM.makeElement(
+				"div",
+				App.UI.DOM.makeTextBox(
+					slave.custom.tattoo,
+					(v) => {
+						slave.custom.tattoo = v;
+						cashX(forceNeg(V.surgeryCost), "slaveMod", slave);
+						refresh();
+					}
+				)
+			)
+		);
+		App.Events.addNode(el, r, "div", "grid-2columns-auto");
+		if (slave.custom.tattoo !== "") {
+			el.append(
+				App.UI.DOM.link(
+					"Remove custom Tattoo",
+					() => {
+						slave.custom.tattoo = "";
+						cashX(forceNeg(V.surgeryCost), "slaveMod", slave);
+					}
+				)
+			);
+		}
+		return el;
+
+		function applyTat(location) {
+			tattooChoice = (location === "lips" && tattooChoice === "scenes") ? "permanent makeup" : tattooChoice;
+			modReaction += App.Medicine.Modification.setTattoo(slave, tattooLocations.get(location), tattooChoice);
+			if (!["flowers", "paternalist", "tribal patterns", 0].includes(tattooChoice)) {
+				V.degradation += 1;
+			}
+		}
+	}
+
 	function refresh() {
 		jQuery("#body-modification").empty().append(createPage());
 	}
diff --git a/src/npc/descriptions/describeTattoos.js b/src/npc/descriptions/describeTattoos.js
index 31be28fb299..52e9e03badd 100644
--- a/src/npc/descriptions/describeTattoos.js
+++ b/src/npc/descriptions/describeTattoos.js
@@ -804,7 +804,7 @@ App.Desc.tattoo = function(slave, surface) {
 						r.push(`${His} anus is bleached.`);
 						break;
 					case "tribal patterns":
-						r.push(`${His} anus is bleached. It is tattooed with a tribal pattern that changes interestingly when ${he} relaxes or tightens ${his} sphincter.`);
+						r.push(`${His} anus is tattooed with a tribal pattern that changes interestingly when ${he} relaxes or tightens ${his} sphincter.`);
 						break;
 					case "flowers":
 						r.push(`${He} has a huge blooming flower tattooed right over ${his} anus.`);
-- 
GitLab