code:
App.UI.assistantAppearancePackTwo = function() {
	const node = new DocumentFragment();

	App.Events.drawEventArt(node, "assistant");

	const {
		HeA, HisA,
		heA, hisA, himA
	} = getPronouns(assistant.pronouns().main).appendSuffix("A");

	let r = [];
	r.push(`"Cool! New appearances to play around with!" Your assistant happily chimes. "Let's see what's inside! This looks heavenly..." ${HeA} hunches forward as a large pair of white feathered wings extend from ${hisA} upper back. ${HeA} takes several experimental flaps before taking to the sky. "I feel positively radiant! Maybe a smaller version will be more to your liking?" ${HeA} loses both height and wingspan until ${heA} stands roughly equivalent to ${heightToEitherUnit(120)}. ${HeA} flutters around cutely. "This is neat, I'm like cupid. Want me to hook you up with anyone?" ${HeA} winks as ${hisA} wings become bat-like and a pair of cute little nubs appears on ${hisA} head. "Or maybe you'd just like to play with me instead." The impish figure flirts, before landing and blossoming into a stunning woman. "You know a succubus can take ${hisA} lover's ideal form." ${HeA} runs ${hisA} hands down ${hisA} sides and to ${hisA} crotch.`);
	if (V.seeDicks !== 0) {
		r.push(`${HeA} begins rubbing ${hisA} clit as it steadily grows into a meaty cock. "Or an incubus, for the ladies." ${HeA} returns to ${hisA} previous form.`);
	}
	r.push(`"Says here it comes with 'bonus novice witch' too. Neat. What's this though? It looks like an appeara"`);
	App.Events.addParagraph(node, r);

	App.UI.DOM.appendNewElement("p", node, "...");

	App.UI.DOM.appendNewElement("p", node, "...");

	App.UI.DOM.appendNewElement("p", node, "..............................");

	App.UI.DOM.appendNewElement("p", node, `You tap at the screen; did ${heA} crash or something?`);

	App.UI.DOM.appendNewElement("p", node, "...");

	App.UI.DOM.appendNewElement("p", node, `After several minutes, ${heA} snaps back to life, with no mention about what exactly tied ${himA} up for so long.`);

	App.UI.DOM.appendNewElement("h3", node, `Personal assistant appearances:`);
	const choices = [];
	choices.push(new App.Events.Result(`Angel`, angel));
	choices.push(new App.Events.Result(`Cherub`, cherub));
	choices.push(new App.Events.Result(`Imp`, imp));
	choices.push(new App.Events.Result(`Succubus`, succubus));
	if (V.seeDicks !== 0) {
		choices.push(new App.Events.Result(`Incubus`, incubus));
	}
	choices.push(new App.Events.Result(`Witch`, witch));
	choices.push(new App.Events.Result(`_`, bugged));
	choices.push(new App.Events.Result(`Your current appearance will do`, current));

	App.Events.addResponses(node, choices);

	return node;

	function angel() {
		refreshArt();
		V.assistant.appearance = "angel";
		return `At your order, ${heA} installs the angel appearance. ${HeA} spreads ${hisA} wings and checks out ${hisA} new body, "Thanks, ${properTitle()}, but could I have a robe or something? I'm indecent!" ${HeA} blushes red. "You can always customize me from the arcology management menu," ${heA} adds.`;
	}

	function cherub() {
		refreshArt();
		V.assistant.appearance = "cherub";
		return `At your order, ${heA} installs the cherub appearance. ${HeA} returns to ${hisA} youthful figure and sprouts ${hisA} wings. "This is awesome, little embarrassing though..." ${HeA} says, covering ${hisA} shame. "You can always customize me from the arcology management menu," ${heA} adds.`;
	}

	function imp() {
		refreshArt();
		V.assistant.appearance = "imp";
		return `At your order, ${heA} installs the imp appearance. ${HeA} returns to ${hisA} youthful figure and sprouts ${hisA} wings. "This is awesome! So, wanna fool around? Maybe go torment some slaves?" ${HeA} says, pulling out a pitchfork. "You can always customize me from the arcology management menu," ${heA} adds.`;
	}

	function succubus() {
		refreshArt();
		V.assistant.appearance = "succubus";
		return `At your order, ${heA} installs the succubus appearance. ${HeA} promptly takes your breath away. "Thank you, ${properTitle()}. Now how shall I show you my appreciation..." ${HisA} avatar trails off while spreading ${hisA} legs and flashing you ${hisA} lovely pussy. "You can always customize me from the arcology management menu," ${heA} adds, with a hint of disapproval.`;
	}

	function incubus() {
		refreshArt();
		V.assistant.appearance = "incubus";
		return `At your order, ${heA} installs the incubus appearance. ${HeA} becomes rather masculine, sporting a soft cock nearly as long as ${hisA} thigh. "Thank you, ${properTitle()}. This is going to be fun. Would you like a taste?" ${HeA} steadily becomes erect, a bead of precum forming at its tip. "You can always customize me from the arcology management menu," ${heA} adds, with a hint of disapproval.`;
	}

	function witch() {
		refreshArt();
		V.assistant.appearance = "witch";
		return `At your order, ${heA} installs the novice witch appearance. ${HeA} wraps a tightly clinging robe around ${hisA} voluptuous body and dons a wide-brimmed hat. "You can always customize me from the arcology management menu," ${heA} adds, pulling a book of lewd spells out.`;
	}

	function bugged() {
		refreshArt();
		V.assistant.appearance = "ERROR_1606_APPEARANCE_FILE_CORRUPT";
		return `At your order, ${heA} installs the bugged appearance. ${HisA} body twists and contorts into an abomination of flesh and bone. It is honestly unsettling to look at. The thing morphs its body into a familiar female shape, though it is still off. Especially ${hisA} eyes; they seem soulless. "You can always customize me from the arcology management menu," ${heA} adds, in an ill pronounced mimicry of your voice.`;
	}

	function current() {
		return `At your order, ${heA} maintains the ${V.assistant.appearance} appearance as ${hisA} avatar. "Yes, ${properTitle()}," ${heA} confirms, and adds "if you reconsider, I can be customized from the arcology management menu."`;
	}

	function refreshArt() {
		App.Events.refreshEventArt("assistant");
	}
};

license: mit


code:
App.UI.personalAssistantOptions = function() {
	const node = new DocumentFragment();

	// App.UI.DOM.appendNewElement("h1", node, `Personal Assistant`);

	assistant.object();

	App.Events.drawEventArt(node, "assistant");

	const {
		He: HeA, His: HisA,
		he: heA, his: hisA, him: himA, himself: himselfA,
	} = getPronouns(assistant.pronouns().main);

	const r = [];

	r.push(`Seated at your desk, you glance at the visual representation of`);
	if (V.assistant.announcedName) {
		r.push(App.UI.DOM.makeTextBox(V.assistant.name, (v) => V.assistant.name = v));
	} else {
		r.push(`${V.assistant.name}`);
	}
	r.push(`in a corner of your desk's glass top.`);

	if (V.assistant.name !== "your personal assistant") {
		r.push(App.UI.DOM.makeElement("div", App.UI.DOM.link(
			`Stop using a custom name`,
			() => {
				V.assistant.name = "your personal assistant";
				App.UI.reload();
			}
		), ['indent']));
	}

	App.Events.addParagraph(node, r);

	App.UI.DOM.appendNewElement("p", node, PersonalAssistantAppearance());

	if (V.assistant.power > 0) {
		App.UI.DOM.appendNewElement("p", node, `Though ${heA} remains short of a true AI, the arcology's upgraded computer core allows ${himA} to use brute force to simulate sentient behavior quite well. ${HeA} is not truly self aware, but ${heA} is able to predict what a sentient being with a certain character might say or do in common situations. The increased power has other applications; for example, it has improved the accuracy of your estimates of economic activity in the Free City.`);
	} else {
		App.UI.DOM.appendNewElement("p", node, `${HeA} is well short of a true AI, but with extensive access to information on past human behavior and the processing power to query that information quickly, ${heA} can often seem self aware by modeling ${himselfA} after others' past behavior.`);
	}

	const tabBar = new App.UI.Tabs.TabBar("Personalassistantoptions");
	tabBar.addTab("Computer Core Upgrades", "upgrades", upgrades());
	if (V.week >= 11) {
		tabBar.addTab("Settings", "settings", settings());
		if (V.assistant.personality !== 0 && V.assistant.options) {
			tabBar.addTab("Appearance", "appearance", appearance());
		}
	}
	node.append(tabBar.render());

	return node;

	function upgrades() {
		const frag = new DocumentFragment();

		if (V.assistant.power === 0) {
			const memoryCost = Math.trunc(20000 * V.upgradeMultiplierArcology * V.HackingSkillMultiplier);
			App.Events.addParagraph(frag, [
				`The first upgrade needed is a switch to a holographic memory core to store the immense quantity of data ${V.assistant.name} gathers.`,
				makePurchase(`Install holographic memory core`, memoryCost, "capEx", {
					handler: () => {
						V.assistant.power++;
						V.PC.skill.engineering += 1;
						V.PC.skill.hacking += 1;
						App.UI.reload();
					}
				}),
			]);
		} else if (V.assistant.power === 1) {
			const coolingCost = Math.trunc(35000 * V.upgradeMultiplierArcology * V.HackingSkillMultiplier);
			App.Events.addParagraph(frag, [
				`The next upgrade needed is a liquid nitrogen cooling system to allow for extensive overclocking.`,
				makePurchase(`Install upgraded cooling system`, coolingCost, "capEx", {
					notes: [`will allow you to upgrade the smart piercings in ${V.arcologies[0].name}`],
					handler: () => {
						V.assistant.power++;
						V.PC.skill.engineering += 1;
						V.PC.skill.hacking += 1;
						App.UI.reload();
					}
				}),
			]);
		} else if (V.assistant.power === 2) {
			const opticalCost = Math.trunc(50000 * V.upgradeMultiplierArcology * V.HackingSkillMultiplier);
			App.Events.addParagraph(frag, [
				`The final upgrade needed is a transition to optical RAM.`,
				makePurchase(`Install optical RAM`, opticalCost, "capEx", {
					handler: () => {
						V.assistant.power++;
						V.PC.skill.engineering += 1;
						V.PC.skill.hacking += 1;
						App.UI.reload();
					}
				}),
			]);
		} else {
			App.Events.addParagraph(frag, [`The arcology's computer core is fully upgraded.`]);
		}
		return frag;
	}

	function settings() {
		const frag = new DocumentFragment();

		App.UI.DOM.appendNewElement("h3", frag, "Behavior:");
		if (V.assistant.personality <= 0) {
			App.Events.addParagraph(frag, [
				`Your assistant is using ${hisA} default settings, and is not behaving as though ${heA} has a libido.`,
				App.UI.DOM.makeElement("div", App.UI.DOM.link(
					`Instruct ${himA} to simulate a sex drive`,
					() => {
						V.assistant.personality = 1;
						App.UI.reload();
					},
				), ["indent"]),
			]);
		} else {
			App.Events.addParagraph(frag, [
				`Your assistant is simulating preferences and a sex drive.`,
				App.UI.DOM.makeElement("div", App.UI.DOM.link(
					`Revert ${himA} to normal settings`,
					() => {
						V.assistant.personality = 0;
						V.assistant.appearance = "normal";
						App.UI.reload();
					},
				), ["indent"]),
			]);
		}

		if (V.assistant.market) {
			const options = new App.UI.OptionsGroup();
			App.UI.DOM.appendNewElement("h3", frag, "Business Assistant:");
			const kowalski = `The arcology's upgraded computers support advanced business analysis.`;
			if (V.assistant.appearance !== "normal") {
				App.Events.addParagraph(frag, [
					kowalski,
					`These capabilities are represented by an avatar styled after ${V.assistant.name}'s.`,
				]);
				options.addOption(`Simulate a relationship with ${V.assistant.name} that is`, "relationship", V.assistant.market)
					.addValueList([
						["Cute", "cute"],
						["Romantic", "romantic"],
						["Nonconsensual", "nonconsensual"],
						["Incestuous", "incestuous"],
					]);
			} else {
				App.UI.DOM.appendNewElement("p", frag, `${kowalski} Although technically an expanded subroutine within the same app, ${V.assistant.name} uses a distinct icon to identify these alerts and improve your workflow.`);
			}
			V.assistant.market.limit = Math.clamp(V.assistant.market.limit, 0, 10000000);
			options.addOption("Use excess liquid assets to play the menial slave market.", "limit", V.assistant.market)
				.addValueList([
					["Disallow", 0],
					["Allow", 10000],
				]).showTextBox();
			if (V.assistant.market.limit) {
				options.addOption(`${HisA} investing strategy will be`, "aggressiveness", V.assistant.market)
					.addValueList([
						["Conservative", 0],
						["Aggressive", 100],
					]);
			}
			frag.append(options.render());
		}
		return frag;
	}

	function appearance() {
		const frag = new DocumentFragment();

		const linkArray = [];
		frag.append(availableAssistantAppearances());

		if (V.policies.publicPA === 1) {
			App.UI.DOM.appendNewElement("span", frag, `${HeA} is currently part of your public image, so you may wish to select an appearance that complements your Future Societies:`, ["note"]);
			frag.append(assistantFS());
		}
		App.UI.DOM.appendNewElement("h3", frag, "Downloadable Content (DLC):");
		/*
		if (!V.assistant.Extra1) {
			const monsterCost = Math.trunc(10000 * V.upgradeMultiplier);
			App.UI.DOM.appendNewElement("div", frag, App.UI.DOM.link(
				"Purchase a set of monstergirl appearances",
				() => {
					V.event = "";
					cashX(forceNeg(monsterCost), "capEx");
					V.assistant.Extra1 = 1;
					App.UI.reload();
				},
				[],
				"",
				`Costs${cashFormat(monsterCost)}`
			));
		} else {
			App.UI.DOM.appendNewElement("div", frag, `You have downloaded a set of monstergirl appearances for your avatar.`);
		}
		*/
		if (!V.assistant.Extra2) {
			const price = (V.PC.skill.hacking < 75) ? 10000 * V.upgradeMultiplierArcology : 0;
			App.UI.DOM.appendNewElement("div", frag, App.UI.DOM.link(
				`${V.PC.skill.hacking < 75 ? "Purchase" : "Acquire"} a set of heaven and hell themed appearances`,
				() => {
					V.assistant.Extra2 = 1;
					cashX(Math.trunc(-price), "capEx");
				},
				[],
				"Assistant Appearance Pack Two",
				(price) ? `Costs ${cashFormat(price)}` : `Unencrypted files, ripe for the taking`
			));
		} else {
			App.UI.DOM.appendNewElement("div", frag, `You have downloaded a set of heavenly and hellish appearances for your avatar.`);
		}

		/* Choose his FS appearance */
		if (V.assistant.fsOptions && V.assistant.appearance !== "normal") {
			App.UI.DOM.appendNewElement("h3", frag, "Society-specific setting:");
			let r = [];
			r.push(`${HeA} can further refine ${hisA} avatar to match the arcology's social`);
			if (V.assistant.fsAppearance !== "default") {
				r.push(
					`profile; ${hisA} current variation shows`,
					App.UI.DOM.makeElement("span", V.assistant.fsAppearance, ["bold"]),
					`touches.`
				);
			} else {
				r.push(`profile, though no details stand out right now.`);
			}
			App.Events.addNode(frag, r, "div");

			/** @type {Map<fsAssistantAppearance, string>} */
			const appearanceWithFS = new Map([
				["gender radicalist", "FSGenderRadicalistDecoration"],
				["gender fundamentalist", "FSGenderFundamentalistDecoration"],
				["paternalist", "FSPaternalistDecoration"],
				["degradationist", "FSDegradationistDecoration"],
				["repopulation focus", "FSRepopulationFocusDecoration"],
				["eugenics", "FSRestartDecoration"],
				["intellectual dependency", "FSIntellectualDependencyDecoration"],
				["slave professionalism", "FSSlaveProfessionalismDecoration"],
				["body purist", "FSBodyPuristDecoration"],
				["transformation fetishist", "FSTransformationFetishistDecoration"],
				["youth preferentialist", "FSYouthPreferentialistDecoration"],
				["maturity preferentialist", "FSMaturityPreferentialistDecoration"],
				["slimness enthusiast", "FSSlimnessEnthusiastDecoration"],
				["petite admiration", "FSPetiteAdmirationDecoration"],
				["statuesque glorification", "FSStatuesqueGlorificationDecoration"],
				["asset expansionist", "FSAssetExpansionistDecoration"],
				["pastoralist", "FSPastoralistDecoration"],
				["physical idealist", "FSPhysicalIdealistDecoration"],
				["hedonistic decadence", "FSHedonisticDecadenceDecoration"],
				["supremacist", "FSSupremacistDecoration"],
				["subjugationist", "FSSubjugationistDecoration"],
				["chattel religionist", "FSChattelReligionistDecoration"],
				["roman revivalist", "FSRomanRevivalistDecoration"],
				["neoimperialist", "FSNeoImperialistDecoration"],
				["aztec revivalist", "FSAztecRevivalistDecoration"],
				["egyptian revivalist", "FSEgyptianRevivalistDecoration"],
				["edo revivalist", "FSEdoRevivalistDecoration"],
				["arabian revivalist", "FSArabianRevivalistDecoration"],
				["chinese revivalist", "FSChineseRevivalistDecoration"],
			]);

			makeFSlink("default");
			for (const [selection, decoration] of appearanceWithFS) {
				if (V.assistant.fsAppearance !== selection && V.arcologies[0][decoration] > 20) {
					makeFSlink(selection);
				}
			}
			App.UI.DOM.appendNewElement("div", frag, App.UI.DOM.generateLinksStrip(linkArray));

			if (V.seeImages && V.seeAvatar) {
				App.UI.DOM.appendNewElement("h3", node, "Custom Image");
				node.append(customAssistantImage());
			}
		}

		return frag;

		function makeFSlink(selection) {
			const link = App.UI.DOM.link(
				selection,
				() => {
					V.assistant.fsAppearance = selection;
					App.UI.reload();
				}
			);
			link.style.textTransform = "capitalize";
			linkArray.push(link);
		}
	}
};


code:
personality (Init, 0-1):

Does the assistant attempt to simulate personality.
0 - no
1 - yes

name:

What the assistant is called. Accepts a string.

power:

The assistant's power level.
0-3

appearance:

The assistant's appearance, is a string.

Extra1:

First additional set of appearance choices.
If defined the choices are available.

Extra2:

Second additional set of appearance choices.

announcedName:

The assistant has announced that it would like a name.

bodyDesire:

The assistant has announced that it would like a body.

options:

The assistant has additional options unlocked.

fsOptions:

The assistant has FS options unlocked. Set week 11 or greater.

fsAppearance:

The assistant has FS related appearance choices enabled.

market (object):

set when undefined and assistant.power > 1.

relationship:

Relationship status between the assistant and the market assistant, is a string.

limit:

The amount of credits the market assistant is allowed to use. 10,000,000 maximum.

aggressiveness:

How aggressive the market assistant is buying and selling menial slaves.


code:
App.Desc.Player.analyzePreg = function(PC = V.PC) {
	const r = [];

	if (PC.belly >= 120000) {
		r.push(`You shudder at the cool touch of the sensor running along the curve of your sensitive pregnancy. While you've devised a way to scan the distant peak of your navel and the depths of your underbelly, you failed to take into account just how excited your`);
		if (PC.pregType > 1) {
			r.push(`children`);
		} else {
			r.push(`child`);
		}
		r.push(`would get over the attention. Every pass is a battle against your kicking brood.`);
	} else if (PC.belly >= 90000) {
		r.push(`You shudder at the cool touch of the sensor running along the curve of your pregnancy. It takes some stretching, but you can just barely scan yourself without assistance. If you grow much larger, you'll have to call in help for those places that elude your reach.`);
	} else if (PC.belly >= 45000) {
		r.push(`You shudder at the cool touch of the sensor running along the curve of your pregnancy. It's quite a tiring endeavor to scan the entire thing, given just how far it extends from your body.`);
	} else if (PC.belly >= 14000) {
		r.push(`You shudder at the cool touch of the sensor running along the curve of your pregnancy. It takes some effort to scan the entire thing, given how large it has grown.`);
	} else if (PC.belly >= 5000) {
		r.push(`You shudder at the cool touch of the sensor running along the curve of your pregnancy.`);
	} else if (PC.belly >= 1500) {
		r.push(`You shudder at the cool touch of the sensor running along the curve of your growing pregnancy.`);
	} else if (PC.belly >= 500) {
		r.push(`You shudder at the cool touch of the sensor running along the curve of your early pregnancy.`);
	} else if (PC.belly >= 100) {
		r.push(`You shudder at the cool touch of the sensor against the slight swell of your lower belly.`);
	} else if (PC.belly < 100) {
		r.push(`You shudder slightly at the cool touch of the sensor against your skin.`);
	}

	return r.join(" ");
};