diff --git a/src/npc/interaction/fAnimal.js b/src/npc/interaction/fAnimal.js
index ec858e070950873602b997bd947201854fd3d045..e60f7b6cd767812e08e3118e89da66ed9fc12111 100644
--- a/src/npc/interaction/fAnimal.js
+++ b/src/npc/interaction/fAnimal.js
@@ -87,7 +87,11 @@ App.Interact.fAnimal = function(slave, type) {
 
 	const mainDiv = App.UI.DOM.appendNewElement("div", frag);
 
-	r.push(canWalk(slave) ? `You call ${him} over and ` : `You order another slave to bring ${slave.slaveName} over. Once ${he} is situated, you`, `tell ${him} you want to watch ${him} ${act !== oral ? `get fucked by` : `suck off`} ${a} ${animal}.`);
+	r.push(canWalk(slave) ? `You call ${him} over and ` : `You order another slave to bring ${slave.slaveName} over. Once ${he} is situated, you`, `tell ${him} you want to watch ${him} ${act === oral ?
+		`suck off` :
+		act === vaginal ?
+			`get fucked by` :
+			`get fucked in the ass by`} ${a} ${animal}.`);
 
 	if (slave.fetish !== "mindbroken") {
 		if (slave.devotion > 50) {
@@ -201,59 +205,143 @@ App.Interact.fAnimal = function(slave, type) {
 
 	function consummationDevoted() {
 		if (act === oral) {
-			r.push(`You have ${him} kneel on the floor before calling in the ${animal}. The beast slowly saunters up to the slave where ${he} waits, showing little concern when the slave reaches out and begins masturbating it to begin the process of getting the animal hard. Once the ${animal} is hard enough, ${slave.slaveName} takes its cock and begins to give a few tentative licks before finally putting it in ${his} mouth.`);
-			if (slaveApproves) {
-				r.push(`The slave seems to quickly get over the fact that dick currently in ${his} mouth is not a human one as ${his} more carnal desires kick in.`);
-			} else {
-				r.push(`The slave visibly gags as the unfamiliar texture of ${a} ${animal}'s cock fills it.`);
-			}
+			r.push(`You have ${him} kneel on the floor before calling in the ${animal}. The beast slowly saunters up to the slave where ${he} waits, showing little concern when the slave reaches out and begins masturbating it to begin the process of getting the animal hard. Once the ${animal} is hard enough, ${slave.slaveName} takes its cock and begins to give it a few tentative licks before finally putting it in ${his} mouth.`);
 		} else {
 			r.push(`You have ${slave.clothes !== "no clothing" ? `take off ${his} clothes and ` : ``} get on the floor, ass in the air, before calling in the ${animal}. The beast slowly saunters up to the slave, where it takes only a few short moments for its animal brain to realize that what it is standing behind is a warm hole that needs to be filled with seed.`);
+		}
 
-			switch (animal) {
-				case V.activeCanine:
-					consummationDevotedCanine();
-					break;
-				case V.activeHooved:
-					consummationDevotedHooved();
-					break;
-				case V.activeFeline:
-					consummationDevotedFeline();
-					break;
-				default:
-					throw new Error(`Unexpected animal type '${type}' in consummationDevoted()`);
-			}
+		switch (animal) {
+			case V.activeCanine:
+				consummationDevotedCanine(act);
+				break;
+			case V.activeHooved:
+				consummationDevotedHooved(act);
+				break;
+			case V.activeFeline:
+				consummationDevotedFeline(act);
+				break;
+			default:
+				throw new Error(`Unexpected animal type '${type}' in consummationDevoted()`);
+		}
 
+		if (act !== oral) {
 			virginityCheck(act);
-			virginityEffects(act);
 		}
 
-		function consummationDevotedCanine() {
-			if (canWalk(slave)) {
-				r.push(`The canine clambers up to mount ${slave.slaveName}, eliciting a squeal from the ${girl} as its claws dig into ${his} flesh.`);
+		function consummationDevotedCanine(type) {
+			if (type === oral) {
+				// TODO: write more
+				if (slaveApproves) {
+					r.push(`The slave seems to quickly get over the fact that dick currently in ${his} mouth is not a human one as ${his} more carnal desires kick in.`);
+				} else {
+					r.push(`The slave visibly gags as the unfamiliar texture of ${a} ${animal}'s cock fills it, then gives a groan as the beast thrusts, stretching ${his} throat to the limit.`);
+				}
 			} else {
-				r.push(`The canine takes a few curious sniffs, then lines up its large cock with ${slave.slaveName}'s ${act === vaginal ? `pussy` : `asshole`}.`);
-			}
+				if (canWalk(slave)) {
+					r.push(`The canine clambers up to mount ${slave.slaveName}, eliciting a squeal from the ${girl} as its claws dig into ${his} flesh.`);
+				} else {
+					r.push(`The canine takes a few curious sniffs, then lines up its large cock with ${slave.slaveName}'s ${act === vaginal ? `pussy` : `asshole`}.`);
+				}
 
-			r.push(`It takes a few tries, but the ${animal} finally manages to sink its cock into ${his} ${slaveApproves && act === vaginal ? `wet ` : ``}${act === vaginal ? `cunt` : `asshole`} and begin to hammer away in the way that only canines can.`);
+				r.push(`It takes a few tries, but the ${animal} finally manages to sink its cock into ${his} ${slaveApproves && act === vaginal ? `wet ` : ``}${act === vaginal ? `cunt` : `asshole`} and begin to hammer away in the way that only canines can.`);
+			}
 		}
 
-		function consummationDevotedHooved() {
-			r.push(`${slave.slaveName} gives a long, drawn-out moan as the huge phallus fills ${his} ${act === vaginal ? `pussy` : `asshole`} nearly to its breaking point.`);
+		function consummationDevotedHooved(type) {
+			if (type === oral) {
+				// TODO: write more
+				if (slaveApproves) {
+					r.push(`The slave seems to quickly get over the fact that dick currently in ${his} mouth is not a human one as ${his} more carnal desires kick in.`);
+				} else {
+					r.push(`The slave visibly gags as the unfamiliar texture of ${a} ${animal}'s cock fills it, then gives a groan as the beast thrusts, stretching ${his} throat to the limit.`);
+				}
+			} else {
+				r.push(`${slave.slaveName} gives a long, drawn-out moan as the huge phallus fills ${his} ${act === vaginal ? `pussy` : `asshole`} nearly to its breaking point.`);
+			}
 		}
 
-		function consummationDevotedFeline() {
-			r.push(`${slave.slaveName} gives a squeal of pain as the barbed cock makes its way into ${his} ${act === vaginal ? `pussy` : `asshole`}.`);
+		function consummationDevotedFeline(type) {
+			if (type === oral) {
+				// TODO: write more
+				if (slaveApproves) {
+					r.push(`The slave seems to quickly get over the fact that dick currently in ${his} mouth is not a human one as ${his} more carnal desires kick in.`);
+				} else {
+					r.push(`The slave visibly gags as the unfamiliar texture of ${a} ${animal}'s cock fills it, then gives a groan as the beast thrusts, stretching ${his} throat to the limit.`);
+				}
+			} else {
+				r.push(`${slave.slaveName} gives a squeal of pain as the barbed cock makes its way into ${his} ${act === vaginal ? `pussy` : `asshole`}.`);
+			}
 		}
 	}
 
 	function consummationNondevoted() {
 		if (act === oral) {
-			r.push(`You tell ${him} to kneel on the floor before calling in the ${animal}. The beast slowly saunters up to the slave where ${he} waits, showing little concern when the slave hesitantly reaches out and begins masturbating it to begin the process of getting the animal hard.`);
-			// TODO: finish writing this
+			r.push(`You tell ${him} to kneel on the floor before calling in the ${animal}. The beast slowly saunters up to the slave where ${he} waits, showing little concern when the slave hesitantly reaches out and begins masturbating it to begin the process of getting the animal hard. Once the ${animal} is hard enough, ${slave.slaveName} takes its cock, and, after taking a moment to steel ${his} resolve, begins to give it a few reluctant licks before putting it in ${his} mouth.`);
 		} else {
-			r.push(`You tell ${him} to ${slave.clothes !== "no clothing" ? `take off ${his} clothes and ` : ``} get on the floor, ass in the air, before calling in the ${animal}. The beast slowly saunters up to the slave, where it takes only a few seconds for its animal brain to realize that what it is standing behind is a warm hole that needs to be filled with seed. Another slave lines its cock up with ${slave.slaveName}'s ${act === vaginal ? `pussy` : `ass`}, then with a thrust, the ${animal} begins to fuck ${him}.`);
-			// TODO: finish writing this
+			r.push(`You tell ${him} to ${slave.clothes !== "no clothing" ? `take off ${his} clothes and ` : ``} get on the floor, ass in the air, before calling in the ${animal}. The beast slowly saunters up to the slave, where it takes only a few seconds for its animal brain to realize that what it is standing behind is a warm hole that needs to be filled with seed.`);
+		}
+
+		switch (animal) {
+			case V.activeCanine:
+				consummationNondevotedCanine(act);
+				break;
+			case V.activeHooved:
+				consummationNondevotedHooved(act);
+				break;
+			case V.activeFeline:
+				consummationNondevotedFeline(act);
+				break;
+			default:
+				throw new Error(`Unexpected animal type '${type}' in consummationDevoted()`);
+		}
+
+		if (act !== oral) {
+			virginityCheck(act);
+		}
+
+		function consummationNondevotedCanine(type) {
+			if (type === oral) {
+				// TODO: write more
+				if (slaveApproves) {
+					r.push(`Though the slave still seems to have some reservations about sucking off an animal, ${he} seems to forget that the cock in ${his} mouth isn't human soon enough, once ${his} carnal desires kick in.`);
+				} else {
+					r.push(`The slave visibly gags as the unfamiliar texture of ${a} ${animal}'s cock fills it, and you get the feeling ${he} is beginning to reevaluate just how much ${he} wants to avoid punishment.`);
+				}
+			} else {
+				if (canWalk(slave)) {
+					r.push(`The canine clambers up to mount ${slave.slaveName}, eliciting a squeal from the ${girl} as its claws dig into ${his} flesh.`);
+				} else {
+					r.push(`The canine takes a few curious sniffs, then lines up its large cock with ${slave.slaveName}'s ${act === vaginal ? `pussy` : `asshole`}.`);
+				}
+
+				r.push(`It takes a few tries, but the ${animal} finally manages to sink its cock into ${his} ${slaveApproves && act === vaginal ? `wet ` : ``}${act === vaginal ? `cunt` : `asshole`} and begin to hammer away in the way that only canines can.`);
+			}
+		}
+
+		function consummationNondevotedHooved(type) {
+			if (type === oral) {
+				// TODO: write more
+				if (slaveApproves) {
+					r.push(`Though the slave still seems to have some reservations about sucking off an animal, ${he} seems to forget that the cock in ${his} mouth isn't human soon enough, once ${his} carnal desires kick in.`);
+				} else {
+					r.push(`The slave visibly gags as the unfamiliar texture of ${a} ${animal}'s cock fills it, and you get the feeling ${he} is beginning to reevaluate just how much ${he} wants to avoid punishment.`);
+				}
+			} else {
+				r.push(`${slave.slaveName} gives a long, drawn-out groan as the huge phallus fills ${his} ${act === vaginal ? `pussy` : `asshole`} nearly to its breaking point.`);
+			}
+		}
+
+		function consummationNondevotedFeline(type) {
+			if (type === oral) {
+				// TODO: write more
+				if (slaveApproves) {
+					r.push(`Though the slave still seems to have some reservations about sucking off an animal, ${he} seems to forget that the cock in ${his} mouth isn't human soon enough, once ${his} carnal desires kick in.`);
+				} else {
+					r.push(`The slave visibly gags as the unfamiliar texture of ${a} ${animal}'s cock fills it, and you get the feeling ${he} is beginning to reevaluate just how much ${he} wants to avoid punishment.`);
+				}
+			} else {
+				r.push(`${slave.slaveName} gives a squeal of pain as the barbed cock makes its way into ${his} ${act === vaginal ? `pussy` : `asshole`}.`);
+			}
 		}
 	}
 
@@ -266,13 +354,17 @@ App.Interact.fAnimal = function(slave, type) {
 			case vaginal:
 				if (act === vaginal && slave.vagina === 0) {
 					r.push(`The slave gives a loud ${slave.devotion > 20 ? `moan` : `groan`} as ${his} virginity is taken from ${him}${slave.devotion < -20 ? ` by force` : ``}.`);
+
+					virginityEffects(type);
 				}
-				return;
+				break;
 			case anal:
 				if (act === anal && slave.anus === 0) {
 					r.push(`The slave gives a loud ${slave.devotion > 20 ? `moan` : `groan`} as ${his} anal virginity is taken from ${him}${slave.devotion < -20 ? ` by force` : ``}.`);
+
+					virginityEffects(type);
 				}
-				return;
+				break;
 			default:
 				throw new Error(`Unexpected type value '${type}' in virginityCheck()`);
 		}