From 0270081733964e6b7d25b4b3273b55a16523e5ac Mon Sep 17 00:00:00 2001
From: DCoded <dicoded@email.com>
Date: Tue, 20 Apr 2021 23:46:46 -0400
Subject: [PATCH] Added animals to seX()

---
 devTools/types/FC/human.d.ts        |  5 +++--
 js/003-data/gameVariableData.js     |  3 ++-
 js/medicine/2-reproductiveOrgans.js | 14 +++++++-------
 src/js/SlaveState.js                | 20 +++++++++-----------
 src/js/sexActsJS.js                 |  5 ++++-
 src/js/storyJS.js                   |  6 ++++--
 src/js/utilsSlave.js                |  5 +++--
 src/npc/children/ChildState.js      | 18 ++++++++----------
 src/npc/interaction/fAnimal.js      |  2 ++
 src/player/js/PlayerState.js        | 19 +++++++++----------
 10 files changed, 51 insertions(+), 46 deletions(-)

diff --git a/devTools/types/FC/human.d.ts b/devTools/types/FC/human.d.ts
index 4b2295a1ae8..09aea9c961d 100644
--- a/devTools/types/FC/human.d.ts
+++ b/devTools/types/FC/human.d.ts
@@ -3,6 +3,7 @@ declare global {
 	export namespace FC {
 		export type SlaveState = InstanceType<typeof App.Entity.SlaveState>;
 		export type PlayerState = InstanceType<typeof App.Entity.PlayerState>;
+		export type AnimalState = InstanceType<typeof App.Entity.Animal>;
 
 		export type DeepPartialSlaveState = DeepPartial<SlaveState>;
 
@@ -318,8 +319,8 @@ declare global {
 		type HeightImplant = -1 | 0 | 1;
 		type Hearing = -2 | -1 | 0;
 
-		type AnimalKind = "human" | "dog" | "pig" | "horse" | "cow";
-		type SpermType = AnimalKind | "sterile";
+		type AnimalType = | "canine" | "hooved" | "feline";
+		type DNAType = AnimalType | "human" | "sterile";
 
 		type GeneticQuirk = 0 | 1 | 2;
 		interface GeneticQuirks {
diff --git a/js/003-data/gameVariableData.js b/js/003-data/gameVariableData.js
index ae39a285bce..ba461a18e19 100644
--- a/js/003-data/gameVariableData.js
+++ b/js/003-data/gameVariableData.js
@@ -573,7 +573,7 @@ App.Data.resetOnNGPlus = {
 	spaUpgrade: 0,
 	spaFix: 0,
 	spaName: "the Spa",
-	
+
 	incubator: {capacity: 0, tanks: []},
 
 	/** @type {FC.FutureSocietyDeco} */
@@ -939,6 +939,7 @@ App.Data.resetOnNGPlus = {
 	birthsTotal: 0,
 	abortionsTotal: 0,
 	miscarriagesTotal: 0,
+	bestialityTotal: 0,
 	pitKillsTotal: 0,
 	pitFightsTotal: 0,
 
diff --git a/js/medicine/2-reproductiveOrgans.js b/js/medicine/2-reproductiveOrgans.js
index 27c13db5de8..369e5ee642f 100644
--- a/js/medicine/2-reproductiveOrgans.js
+++ b/js/medicine/2-reproductiveOrgans.js
@@ -38,7 +38,7 @@ App.Medicine.OrganFarm.Testicles = class extends App.Medicine.OrganFarm.Organ {
 	/**
 	 * @param {Object} params
 	 * @param {string} params.name
-	 * @param {FC.AnimalKind} params.ballType
+	 * @param {FC.DNAType} params.ballType
 	 */
 	constructor({name, ballType}) {
 		super({
@@ -158,7 +158,7 @@ App.Medicine.OrganFarm.Ovaries = class extends App.Medicine.OrganFarm.Organ {
 	/**
 	 * @param {object} params
 	 * @param {string} params.name
-	 * @param {FC.AnimalKind} params.eggType
+	 * @param {FC.DNAType} params.eggType
 	 * @param {string} params.pregData
 	 */
 	constructor({name, eggType, pregData}) {
@@ -182,7 +182,7 @@ App.Medicine.OrganFarm.Ovaries = class extends App.Medicine.OrganFarm.Organ {
 						/**
 						 * @type {FC.PregnancyData}
 						 */
-							// @ts-ignore
+						// @ts-ignore
 						const data = {};
 						deepAssign(data, App.Data.misc.pregData[this.pregData]);
 						s.pregData = data;
@@ -208,7 +208,7 @@ App.Medicine.OrganFarm.Ovaries = class extends App.Medicine.OrganFarm.Organ {
 						/**
 						 * @type {FC.PregnancyData}
 						 */
-							// @ts-ignore
+						// @ts-ignore
 						const data = {};
 						deepAssign(data, App.Data.misc.pregData[this.pregData]);
 						s.pregData = data;
@@ -231,7 +231,7 @@ App.Medicine.OrganFarm.Ovaries = class extends App.Medicine.OrganFarm.Organ {
 App.Medicine.OrganFarm.AnalWombImplantAction = class extends App.Medicine.OrganFarm.OrganImplantAction {
 	/**
 	 * @param {object} params
-	 * @param {FC.AnimalKind} params.eggType
+	 * @param {FC.DNAType} params.eggType
 	 * @param {string} params.pregData
 	 */
 	constructor({eggType, pregData}) {
@@ -251,7 +251,7 @@ App.Medicine.OrganFarm.AnalWombImplantAction = class extends App.Medicine.OrganF
 				/**
 				 * @type {FC.PregnancyData}
 				 */
-					// @ts-ignore
+				// @ts-ignore
 				const data = {};
 				deepAssign(data, App.Data.misc.pregData[this.pregData]);
 				s.pregData = data;
@@ -273,7 +273,7 @@ App.Medicine.OrganFarm.AnalWomb = class extends App.Medicine.OrganFarm.Organ {
 	/**
 	 * @param {object} params
 	 * @param {string} params.name
-	 * @param {FC.AnimalKind} params.eggType
+	 * @param {FC.DNAType} params.eggType
 	 * @param {string} params.pregData
 	 */
 	constructor({name, eggType, pregData}) {
diff --git a/src/js/SlaveState.js b/src/js/SlaveState.js
index 01b6d3ef11e..851170dcb05 100644
--- a/src/js/SlaveState.js
+++ b/src/js/SlaveState.js
@@ -2454,21 +2454,19 @@ App.Entity.SlaveState = class SlaveState {
 		 * What species of sperm she produces.
 		 * * "human"
 		 * * "sterile"
-		 * * "dog"
-		 * * "pig"
-		 * * "horse"
-		 * * "cow"
-		 * @type {FC.SpermType}
+		 * * "canine"
+		 * * "hooved"
+		 * * "feline"
+		 * @type {FC.DNAType}
 		 */
 		this.ballType = "human";
 		/**
-		 * What species of ovum she produces.
+		 * What type of ovum she produces.
 		 * * "human"
-		 * * "dog"
-		 * * "pig"
-		 * * "horse"
-		 * * "cow"
-		 * @type {FC.AnimalKind}
+		 * * "canine"
+		 * * "hooved"
+		 * * "feline"
+		 * @type {FC.DNAType}
 		 */
 		this.eggType = "human";
 		/** Eugenics variable. Is the slave allowed to choose to wear chastity.
diff --git a/src/js/sexActsJS.js b/src/js/sexActsJS.js
index be7405df4c5..6665def27d9 100644
--- a/src/js/sexActsJS.js
+++ b/src/js/sexActsJS.js
@@ -487,7 +487,7 @@ globalThis.actX = function(slave, act, count = 1) {
  * Sex is between two. This is a handy wrapper for actX that emphasizes that.
  * @param {FC.HumanState} slave1 slave or PC
  * @param {FC.SlaveActs} act1 oral, anal, etc
- * @param {FC.HumanState | "public" | "slaves"} slave2 slave or PC or "public"
+ * @param {FC.HumanState | FC.AnimalState | "public" | "slaves"} slave2 slave or PC or "public"
  * @param {FC.SlaveActs} act2 oral, anal, etc
  * @param {number} [count=1]
  */
@@ -501,6 +501,9 @@ globalThis.seX = function(slave1, act1, slave2, act2, count = 1) {
 		addPartner(slave1, -2);
 	} else if (typeof slave2 === 'string') {
 		// someday we may track "slaves" and "assistant"
+	} else if (slave2 instanceof App.Entity.Animal) {
+		V.bestialityTotal++;
+		addPartner(slave1, -8);
 	} else {
 		actX(slave2, act2, count);
 		addPartner(slave1, slave2);
diff --git a/src/js/storyJS.js b/src/js/storyJS.js
index b8ce71c9f43..7cf2bc77d24 100644
--- a/src/js/storyJS.js
+++ b/src/js/storyJS.js
@@ -69,14 +69,16 @@ globalThis.filterInPlace = function(arr, callback, thisArg) {
 
 /** pregmod: are slave2's sperm compatible with slave1's eggs?
  * @param {FC.HumanState} slave1
- * @param {FC.HumanState} slave2
+ * @param {FC.HumanState|App.Entity.Animal} slave2
  * @returns {boolean}
  */
 globalThis.canBreed = function(slave1, slave2) {
 	if (!slave1 || !slave2) {
 		return null;
 	}
-	return (slave1.eggType === slave2.ballType);
+	return (slave2 instanceof App.Entity.Animal
+		? slave1.eggType === slave2.species
+		: slave1.eggType === slave2.ballType);
 };
 
 /** assuming slave1 is fertile, could slave2 impregnate slave1?
diff --git a/src/js/utilsSlave.js b/src/js/utilsSlave.js
index 007708d9ff4..fc914ef5598 100644
--- a/src/js/utilsSlave.js
+++ b/src/js/utilsSlave.js
@@ -3524,7 +3524,7 @@ globalThis.randomRapeRivalryTarget = function(slave, predicate) {
 /**
  * TODO: move this into seX() once interact scenes are converted
  * @param {FC.HumanState} slave
- * @param {FC.HumanState|number} partner The slave's partner, or the ID of the slave's partner.
+ * @param {FC.HumanState|FC.AnimalState|number} partner The slave's partner, or the ID of the slave's partner.
  *
  * | ***ID*** | **Type**              |
  * |---------:|:----------------------|
@@ -3556,8 +3556,9 @@ globalThis.addPartner = function(slave, partner) {
 	} else if ("ID" in partner) {
 		slave.partners.add(partner.ID);
 	} else {
-		throw new TypeError(`partner must be an object or ID, not "${partner}"`);
+		throw new TypeError(`Partner must be an object or ID, not "${partner}"`);
 	}
+
 	const partnerState = getPartnerState();
 	if (partnerState) {
 		partnerState.partners.add(slave.ID);
diff --git a/src/npc/children/ChildState.js b/src/npc/children/ChildState.js
index edcbb7ec0b5..e037afffbb0 100644
--- a/src/npc/children/ChildState.js
+++ b/src/npc/children/ChildState.js
@@ -1822,21 +1822,19 @@ App.Facilities.Nursery.ChildState = class ChildState {
 		 * What species of sperm she produces.
 		 * * "human"
 		 * * "sterile"
-		 * * "dog"
-		 * * "pig"
-		 * * "horse"
-		 * * "cow"
-		 * @type {FC.SpermType}
+		 * * "canine"
+		 * * "hooved"
+		 * * "feline"
+		 * @type {FC.DNAType}
 		 */
 		this.ballType = "human";
 		/**
 		 * What species of ovum she produces.
 		 * * "human"
-		 * * "dog"
-		 * * "pig"
-		 * * "horse"
-		 * * "cow"
-		 * @type {FC.AnimalKind}
+		 * * "canine"
+		 * * "hooved"
+		 * * "feline"
+		 * @type {FC.DNAType}
 		 */
 		this.eggType = "human";
 		/** Eugenics variable. Is the slave allowed to choose to wear chastity.
diff --git a/src/npc/interaction/fAnimal.js b/src/npc/interaction/fAnimal.js
index fb8642c51da..1db7911c34f 100644
--- a/src/npc/interaction/fAnimal.js
+++ b/src/npc/interaction/fAnimal.js
@@ -17,6 +17,7 @@ App.Interact.fAnimal = function(slave, type) {
 
 	const approvingFetishes = ["masochist", "humiliation", "perverted", "sinful"];	// not strictly fetishes, but approvingFetishesAndBehavioralQuirksAndSexualQuirks doesn't have the same ring to it
 
+	/** @type {App.Entity.Animal} */
 	const animal = V.active[type];
 
 	const stretches = App.UI.DOM.makeElement("span", `stretches`, ["lime"]);
@@ -616,6 +617,7 @@ App.Interact.fAnimal = function(slave, type) {
 
 			switch (act) {
 				case Acts.ORAL:
+					seX(slave, 'oral', animal, 'oral');
 					slave.counter.oral++;
 					break;
 				case Acts.VAGINAL:
diff --git a/src/player/js/PlayerState.js b/src/player/js/PlayerState.js
index 5b854cd1a4f..2a7bbc59dc3 100644
--- a/src/player/js/PlayerState.js
+++ b/src/player/js/PlayerState.js
@@ -1900,21 +1900,20 @@ App.Entity.PlayerState = class PlayerState {
 		 * What species of sperm she produces.
 		 * * "human"
 		 * * "sterile"
-		 * * "dog"
-		 * * "pig"
-		 * * "horse"
-		 * * "cow"
-		 * @type {FC.SpermType}
+		 * * "canine"
+		 * * "hooved"
+		 * * "feline"
+		 * @type {FC.DNAType}
 		 */
 		this.ballType = "human";
 		/**
 		 * What species of ovum she produces.
 		 * * "human"
-		 * * "dog"
-		 * * "pig"
-		 * * "horse"
-		 * * "cow"
-		 * @type {FC.AnimalKind}
+		 * * "sterile"
+		 * * "canine"
+		 * * "hooved"
+		 * * "feline"
+		 * @type {FC.DNAType}
 		 */
 		this.eggType = "human";
 		/** */
-- 
GitLab