/** * @param {App.Entity.SlaveState} slave * @param {string} type */ App.Interact.fAnimal = function(slave, type) { const frag = new DocumentFragment(); const {He, he, him, His, his, girl} = getPronouns(slave); /** @enum {string} */ const Acts = { VAGINAL: "vaginal", ANAL: "anal", ORAL: "oral", }; const vaginal = Acts.VAGINAL; const anal = Acts.ANAL; const oral = Acts.ORAL; const approvingFetishes = ["masochist", "humiliation", "perverted", "sinful"]; // not strictly fetishes, but approvingFetishesAndBehavioralQuirksAndSexualQuirks doesn't have the same ring to it const animal = V.active[type]; let fetishDesc; let act; let hole; let orifice = []; const anAnimal = animal.articleAn ? `an ${animal.name}` : `a ${animal.name}`; if (slave.assignment === Job.FUCKTOY || slave.assignment === Job.MASTERSUITE) { if (slave.toyHole === "pussy") { act = vaginal; } else if (slave.toyHole === "ass") { act = anal; } else if (slave.toyHole === "mouth") { act = oral; } else { if (canDoVaginal(slave)) { act = vaginal; } else if (canDoAnal(slave)) { act = anal; } else { act = oral; } } } else if (canDoVaginal(slave)) { act = vaginal; } else if (canDoAnal(slave)) { act = anal; } else { act = oral; } const slaveApproves = () => approvingFetishes.includes(slave.fetish) || approvingFetishes.includes(slave.sexualQuirk) || approvingFetishes.includes(slave.behavioralQuirk) || slave.fetish === "buttslut" && act === anal || slave.fetish === "cumslut" && act === oral || slave.sexualQuirk === "gagfuck queen" && act === oral; switch (act) { case oral: orifice = ["mouth", "throat"]; break; case vaginal: orifice = ["pussy", "cunt"]; hole = 0; break; case anal: orifice = ["asshole", "rectum"]; hole = 1; break; default: throw new Error(`Unexpected act type '${act}' in fAnimal()`); } if (slave.fetish === "cumslut" && act === oral) { fetishDesc = `getting to drink more cum`; } else if (slave.fetish === "humiliation") { fetishDesc = `committing such a humiliating act`; } else if (slave.fetish === "buttslut" && act === anal) { fetishDesc = `getting to take a cock up ${his} ass`; } else if (slave.fetish === "masochist") { fetishDesc = `committing such a painful act`; } else if (slave.sexualQuirk === "perverted") { fetishDesc = `committing such a perverted act`; } else if (slave.sexualQuirk === "gagfuck queen" && act === oral) { fetishDesc = `getting to suck more dick`; } else if (slave.behavioralQuirk === "sinful") { fetishDesc = `committing such a sinful act`; } const mainDiv = App.UI.DOM.appendNewElement("div", frag); mainDiv.append(intro(), consummation(), completion(), sexEffects()); if (V.postSexCleanUp) { mainDiv.append(cleanUp()); } return frag; // MARK: Intro Functions function intro() { const mainSpan = document.createElement("span"); const r = []; if (canWalk(slave)) { r.push(`You call ${him} over and`); } else { r.push(`You order another slave to bring ${slave.slaveName} over. Once ${he} is situated, you`); } r.push(`tell ${him} you want to watch ${him} ${act === oral ? `suck off` : act === vaginal ? `get fucked by` : `get fucked in the ass by`} ${anAnimal}. `); if (slave.fetish === "mindbroken") { r.push(`${slave.slaveName} nods ${his} head dumbly, ${his} eyes vacant${!canSee(slave) ? ` as always` : ``}. `); } mainSpan.append(r.join(' ')); if (slave.fetish !== "mindbroken") { if (slave.devotion > 50) { mainSpan.append(introDevoted()); } else if (slave.devotion > 20) { mainSpan.append(introNondevoted()); } else if (slave.devotion >= -20) { mainSpan.append(introNonresistant()); } else { mainSpan.append(introResistant()); } } return mainSpan; function introDevoted() { const mainSpan = document.createElement("span"); if (act === oral) { if (slaveApproves()) { mainSpan.append(`${slave.slaveName}'s face visibly brightens at the prospect of ${fetishDesc}, even if it's an animal${slave.fetish === "cumslut" ? `'s cum` : ` that ${he} has to suck off`}. `); } else { mainSpan.append(`${slave.slaveName} visibly blanches at the thought of having to suck down an animal's cum, but ${he} is so devoted to you that ${he} reluctantly agrees. `); } } else { if ((act === vaginal && slave.vagina > 0) || (act === anal && slave.anus > 0)) { if (slaveApproves()) { mainSpan.append(`${slave.slaveName}'s face visibly brightens at the thought of ${fetishDesc}, even if the dick is an animal's. `); } else { mainSpan.append(`${slave.slaveName} looks visibly disturbed, but is so attentive to your will that ${he} agrees. `); } } else { if (slaveApproves()) { mainSpan.append(`${slave.slaveName}'s face visibly brightens at the thought of ${fetishDesc}, although ${he} seems a bit hesitant at the thought of giving ${his} virginity to an animal. `); } else { mainSpan.append(`${slave.slaveName} looks visibly shaken at the thought of having ${his} precious ${!canDoVaginal(slave) ? `anal ` : ``}virginity taken by an animal, but is so attentive to your will that ${he} ultimately agrees. `); } } } return mainSpan; } function introNondevoted() { const mainSpan = document.createElement("span"); if (act === oral) { if (slaveApproves()) { mainSpan.append(`${slave.slaveName} isn't too keen on the idea of sucking off an animal, but the idea of ${fetishDesc} is enough to get ${him} to comply. `); } else { mainSpan.append(`${slave.slaveName} tries in vain to conceal ${his} horror at the thought of blowing an animal, but quickly regains ${his} composure. `); } } else { if ((act === vaginal && slave.vagina > 0) || (act === anal && slave.anus > 0)) { if (slaveApproves()) { mainSpan.append(`${slave.slaveName} doesn't seem terribly keen on the idea of fucking an animal, but the thought of ${fetishDesc} seems to be enough to win ${him} over. `); } else { mainSpan.append(`${slave.slaveName} tries in vain to conceal ${his} horror at the thought of fucking an animal, but quickly regains ${his} composure. `); } } else { if (slaveApproves()) { mainSpan.append(`${slave.slaveName} clearly has some reservations about having ${his} ${act === anal ? `anal ` : ``}virginity taken by ${anAnimal}, but the thought of ${fetishDesc} is enough to make agree to comply. `); } else { mainSpan.append(`${slave.slaveName} tries in vain to conceal ${his} horror at the thought of having ${his} precious ${act === anal ? `rosebud` : `pearl`} taken by a beast, but quickly regains ${his} composure. `); } } } return mainSpan; } function introNonresistant() { const mainSpan = document.createElement("span"); if (act === oral) { if (slaveApproves()) { mainSpan.append(`${slave.slaveName} looks disgusted at the thought of sucking off an animal at first, but the thought of the ${fetishDesc} that comes with it seems to spark a small flame of lust in ${him}. `); } else { mainSpan.append(`${slave.slaveName} tries in vain to conceal ${his} horror at the thought of blowing an animal${canWalk(slave) ? `, and only the threat of worse punishment keeps ${him} from running away as fast as ${he} can` : ``}. `); } } else { if ((act === vaginal && slave.vagina > 0) || (act === anal && slave.anus > 0)) { if (slaveApproves()) { mainSpan.append(`${slave.slaveName} looks disgusted at the thought of fucking an animal at first, but the thought of the ${fetishDesc} that comes with it seems to spark a small flame of lust in ${him}. `); } else { mainSpan.append(`${slave.slaveName} tries in vain to conceal ${his} horror at the thought of fucking an animal${canWalk(slave) ? `, and only the threat of worse punishment keeps ${him} from running away as fast as ${he} can` : ``}. `); } } else { if (slaveApproves()) { mainSpan.append(`${slave.slaveName} clearly has some reservations about having ${his} ${act === anal ? `anal ` : ``}virginity taken by ${anAnimal}, but the thought of ${fetishDesc} is enough to make agree to comply. `); } else { mainSpan.append(`${slave.slaveName} tries in vain to conceal ${his} horror at the thought of having ${his} precious ${act === anal ? `rosebud` : `pearl`} taken by a beast${canWalk(slave) ? `, and only the threat of worse punishment keeps ${him} from running away as fast as ${he} can` : ``}. `); } } } return mainSpan; } function introResistant() { const mainSpan = document.createElement("span"); mainSpan.append(`${slave.slaveName}'s face contorts into a mixture of ${slave.devotion < -50 ? `hatred, anger, and disgust` : `anger and disgust`}, ${canWalk(slave) ? `and only the threat of far worse punishment is enough to prevent ${him} from running out of the room` : `but ${he} knows ${he} is powerless to stop you`}. `); return mainSpan; } } // MARK: Consummation Functions function consummation() { if (slave.devotion > 50) { return consummationDevoted(); } else if (slave.devotion > 20) { return consummationNondevoted(); } else if (slave.devotion > -20) { return consummationNonresistant(); } else { return consummationResistant(); } function consummationDevoted() { const mainSpan = document.createElement("span"), r = []; if (act === oral) { r.push(`You have ${him} kneel on the floor before calling in the ${animal.name}. 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.name} 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 ${him} ${slave.clothes !== "no clothing" ? `take off ${his} clothes and ` : ``}get on the floor, ass in the air, before calling in the ${animal.name}. 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.active.canine: consummationDevotedCanine(act); break; case V.active.hooved: consummationDevotedHooved(act); break; case V.active.feline: consummationDevotedFeline(act); break; default: throw new Error(`Unexpected animal type '${animal}' in consummationDevoted()`); } if (act !== oral) { mainSpan.append(virginityCheck(act)); } function consummationDevotedCanine(type) { if (type === oral) { if (slaveApproves()) { r.push(`The slave seems to quickly get over the fact that the dick currently in ${his} mouth belongs to a canine as ${his} more carnal desires kick in. `); } else { r.push(`The slave visibly gags as the unfamiliar texture of ${anAnimal}'s cock fills it, then gives a groan as the beast thrusts, filling ${his} throat. `); } } 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.name} 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(type) { if (type === oral) { 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 ${anAnimal}'s cock fills it, then gives a groan as the beast thrusts, stretching ${his} poor 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(type) { if (type === oral) { if (slaveApproves()) { r.push(`The slave seems to quickly get over the fact that dick currently in ${his} mouth belongs to ${anAnimal} as ${his} more carnal desires kick in. `); } else { r.push(`The slave visibly gags as the unfamiliar texture of ${anAnimal}'s cock fills it, then gives a groan as the beast thrusts, the barbs on its cock rubbing the inside of ${his} mouth raw. `); } } else { r.push(`${slave.slaveName} gives a squeal of pain as the barbed cock makes its way into ${his} ${act === vaginal ? `pussy` : `asshole`}. `); } } mainSpan.append(r.join(' ')); return mainSpan; } function consummationNondevoted() { const mainSpan = document.createElement("span"), r = []; if (act === oral) { r.push(`You tell ${him} to kneel on the floor before calling in the ${animal.name}. 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.name} 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.name}. 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.active.canine: consummationNondevotedCanine(act); break; case V.active.hooved: consummationNondevotedHooved(act); break; case V.active.feline: consummationNondevotedFeline(act); break; default: throw new Error(`Unexpected animal type '${animal}' in consummationDevoted()`); } if (act !== oral) { mainSpan.append(virginityCheck(act)); } function consummationNondevotedCanine(type) { if (type === oral) { 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 belongs to ${anAnimal} soon enough, once ${his} carnal desires kick in. `); } else { r.push(`The slave visibly gags as the unfamiliar texture of ${anAnimal}'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.name} 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) { if (slaveApproves()) { r.push(`Though the slave still seems to have some reservations about sucking off ${anAnimal}, ${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 ${anAnimal}'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) { 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 belongs to a feline soon enough, once ${his} carnal desires kick in. `); } else { r.push(`The slave visibly gags as the unfamiliar texture of ${anAnimal}'s barbed dick 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`}. `); } } mainSpan.append(r.join(' ')); return mainSpan; } function consummationNonresistant() { const mainSpan = document.createElement("span"), r = []; if (act === oral) { r.push(`You force ${him} to kneel on the floor before calling in the ${animal.name}. The beast slowly saunters up to the slave where ${he} waits, showing little concern when the slave reluctantly reaches out and begins masturbating it to begin the process of getting the animal hard. Once the ${animal.name} 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 force ${him} to ${slave.clothes !== "no clothing" ? `take off ${his} clothes and ` : ``}get on the floor, ass in the air, before calling in the ${animal.name}. 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.active.canine: consummationNonresistantCanine(act); break; case V.active.hooved: consummationNonresistantHooved(act); break; case V.active.feline: consummationNonresistantFeline(act); break; default: throw new Error(`Unexpected animal type '${animal}' in consummationNonresistant()`); } if (act !== oral) { mainSpan.append(virginityCheck(act)); } function consummationNonresistantCanine(type) { if (type === oral) { 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 belongs to ${anAnimal} soon enough, once ${his} carnal desires kick in. `); } else { r.push(`The slave visibly gags as the unfamiliar texture of ${anAnimal}'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.name} 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 consummationNonresistantHooved(type) { if (type === oral) { if (slaveApproves()) { r.push(`Though the slave still seems to have some reservations about sucking off ${anAnimal}, ${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 ${anAnimal}'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 consummationNonresistantFeline(type) { if (type === oral) { 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 belongs to a feline soon enough, once ${his} carnal desires kick in. `); } else { r.push(`The slave visibly gags as the unfamiliar texture of ${anAnimal}'s barbed dick 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`}. `); } } mainSpan.append(r.join(' ')); return mainSpan; } function consummationResistant() { const mainSpan = document.createElement("span"), r = []; if (act === oral) { r.push(`You have to physically force ${him} to kneel on the floor before calling in the ${animal.name}. The beast slowly saunters up to the slave where ${he} is restrained, showing little concern when another slave reaches out and begins masturbating it to begin the process of getting the animal hard. Once the ${animal.name} is hard enough, the slave takes its cock and lines it up with ${slave.slaveName}'s mouth. The animal needs no prompting, and thrusts itself into ${his} ring-gagged mouth. `); } else { r.push(`You have to physically force ${him} to ${slave.clothes !== "no clothing" ? `take off ${his} clothes and ` : ``} get on the floor, ass in the air and restraints around ${his} wrists and ankles, before calling in the ${animal.name}. 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.active.canine: consummationResistantCanine(act); break; case V.active.hooved: consummationResistantHooved(act); break; case V.active.feline: consummationResistantFeline(act); break; default: throw new Error(`Unexpected animal type '${animal}' in consummationResistant()`); } if (act !== oral) { mainSpan.append(virginityCheck(act)); } function consummationResistantCanine(type) { if (type === oral) { if (slaveApproves()) { r.push(`The slave glares daggers at you as ${he} takes the full length of the canine's cock in ${his} mouth, but ${slave.dick ? canAchieveErection(slave) ? `${his} fully-erect dick` : `the precum leaking from ${his} dick` : slave.vagina > -1 ? `a slight sheen on ${his} pussylips` : `a slight blush to ${his} cheeks`} tells you that ${he}'s enjoying this, at least a little. `); } else { r.push(`The slave visibly gags as the unfamiliar texture of ${anAnimal}'s cock fills it, and you get the feeling ${he} would have run away a long time ago if ${he} wasn't a little tied up at the moment. `); } } 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.name} 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 consummationResistantHooved(type) { if (type === oral) { if (slaveApproves()) { r.push(`The slave glares daggers at you as ${he} takes the full length of the ${animal.name}'s cock in ${his} mouth, but ${slave.dick ? canAchieveErection(slave) ? `${his} fully-erect dick` : `the precum leaking from ${his} dick` : slave.vagina > -1 ? `a slight sheen on ${his} pussylips` : `a slight blush to ${his} cheeks`} tells you that ${he}'s enjoying this, at least a little. `); } else { r.push(`The slave visibly gags as the unfamiliar texture of ${anAnimal}'s cock fills it, and you get the feeling ${he} would have run away a long time ago if ${he} wasn't a little tied up at the moment. `); } } else { r.push(`${slave.slaveName} lets out a blood-curdling scream as the huge phallus fills ${his} ${act === vaginal ? `pussy` : `asshole`} nearly to its breaking point. `); } } function consummationResistantFeline(type) { if (type === oral) { if (slaveApproves()) { r.push(`The slave glares daggers at you as ${he} takes the full length of the feline's cock in ${his} mouth, but ${slave.dick ? canAchieveErection(slave) ? `${his} fully-erect dick` : `the precum leaking from ${his} dick` : slave.vagina > -1 ? `a slight sheen on ${his} pussylips` : `a slight blush to ${his} cheeks`} tells you that ${he}'s enjoying this, at least a little. `); } else { r.push(`The slave visibly gags as the unfamiliar texture of ${anAnimal}'s barbed dick fills it, and you get the feeling ${he} would have run away a long time ago if ${he} wasn't a little tied up at the moment .`); } } else { r.push(`${slave.slaveName} lets out a blood-curdling scream as the barbed cock makes its way into ${his} ${act === vaginal ? `pussy` : `asshole`}. `); } } mainSpan.append(r.join(' ')); return mainSpan; } } // MARK: Completion Function function completion() { const mainSpan = document.createElement("span"), r = []; switch (animal) { case V.active.canine: completionCanine(); break; case V.active.hooved: completionHooved(); break; case V.active.feline: completionFeline(); break; default: throw new Error(`Unexpected animal type '${animal}' in completion()`); } if (act !== oral && canGetPregnant(slave) && canBreed(slave, animal)) { knockMeUp(slave, 5, hole, -8); } function completionCanine() { if (act === oral) { r.push(`The ${animal.species === "dog" ? `hound` : animal.name} wastes no time in beginning to hammer away at ${his} ${orifice[0]}, causing ${slave.slaveName} to moan uncontrollably as its thick, veiny member probes the depths of ${his} ${orifice[1]}. A few short minutes later, ${he} gives a loud groan ${slaveApproves() ? `and shakes in orgasm ` : ``}as the ${animal.name}'s knot begins to swell and its dick begins to erupt a thick stream of jizz down ${his} abused throat. Soon enough, the ${animal.name} finally finishes cumming and its knot is sufficiently small enough to slip out of ${slave.slaveName}'s mouth, causing ${him} to immediately begin coughing and retching uncontrollably. Having finished its business, the ${animal.name} runs off, presumably in search of food. `); } else { r.push(`The ${animal.species === "dog" ? `hound` : animal.name} wastes no time in beginning to hammer away at ${his} ${orifice[0]}, causing ${slave.slaveName} to moan uncontrollably as its thick, veiny member probes the depths of ${his} ${orifice[1]}. A few short minutes later, ${he} gives a loud groan ${slaveApproves() ? `and shakes in orgasm ` : ``}as the ${animal.name}'s knot begins to swell and its dick begins to erupt a thick stream of jizz into ${his} ${orifice[0]}. Soon enough, the ${animal.name} finally finishes cumming and its knot is sufficiently small enough to slip out of ${slave.slaveName}'s ${act === vaginal && slave.vagina < 3 || act === anal && slave.anus < 2 ? `now-gaping ${orifice[0]}` : orifice[0]}, causing a thick stream of cum to slide out of it. Having finished its business, the ${animal.name} runs off, presumably in search of food. `); } switch (act) { case oral: slave.counter.oral++; break; case vaginal: slave.counter.vaginal++; slave.vagina = slave.vagina < 3 ? 3 : slave.vagina; break; case anal: slave.counter.anal++; slave.anus = slave.anus < 2 ? 2 : slave.anus; break; default: throw new Error(`Unexpected act type '${act} in completionCanine().`); } } function completionHooved() { if (act === oral) { r.push(`The ${animal.species === "horse" ? `stallion` : animal.name} begins to thrust faster and faster, causing ${him} to moan and groan past the huge ${animal.species} cock stretching ${his} poor throat to its limits. Before too long, the ${animal.name}'s movements begin to slow, and you can see its large testicles contract as its begins to erupt and pour its thick semen down ${his} throat and into ${his} stomach, filling it to the brim. After what seems like an impossibly long time, the ${animal.name}'s dick finally begins to soften and pull out, causing ${slave.slaveName} to begin coughing and retching uncontrollably. You have another slave lead the ${animal.name} away, with a fresh apple as a treat for its good performance. `); } else { r.push(`The ${animal.species === "horse" ? `stallion` : animal.name} begins to thrust faster and faster, causing ${him} to moan and groan as the huge ${animal.species} cock ${act === vaginal ? `batters ${his} cervix` : `fills ${him} completely`}. Before too long, the ${animal.name}'s movements begin to slow, and you can see its large testicles contract as its begins to erupt and fill ${his} ${orifice[1]} with its thick baby batter. After what seems like an impossibly long time, the ${animal.name}'s dick finally begins to soften and pull out, leaving ${slave.slaveName} panting and covered in sweat. You have another slave lead the ${animal.name} away, with a fresh apple as a treat for its good performance. `); } switch (act) { case oral: slave.counter.oral++; break; case vaginal: slave.counter.vaginal++; slave.vagina = slave.vagina < 4 ? 4 : slave.vagina; break; case anal: slave.counter.anal++; slave.anus = slave.anus < 3 ? 3 : slave.anus; break; default: throw new Error(`Unexpected act type '${act} in completionHooved().`); } } function completionFeline() { if (act === oral) { r.push(`The ${animal.name} begins to move, thrusting faster and faster. The ${girl} underneath it can't stop a groan of pain from escaping ${his} lips as the ${animal.species}'s barbed dick rubs the inside of ${his} mouth and throat raw. After a few minutes of painful coupling, the ${animal.species}'s thrusts finally slow, then stop completely as its ${animal.species !== "cat" ? `large` : ``} cock erupts down ${slave.slaveName}'s throat. With a ${animal.species !== "cat" ? `deep bellow` : `loud meow`}, he finally dismounts, gives you a long look, then stalks off. `); } else { r.push(`The ${animal.name} begins to move, thrusting faster and faster. The ${girl} underneath it can't stop a groan of pain from escaping ${his} lips as the ${animal.species}'s barbed dick rubs the inside of ${his} ${orifice[0]} raw. After a few minutes of painful coupling, the ${animal.species}'s thrusts finally slow, then stop completely as its ${animal.species !== "cat" ? `large` : ``} cock erupts, filling ${slave.slaveName} with its sperm. With a ${animal.species !== "cat" ? `deep bellow` : `loud meow`}, he finally dismounts, gives you a long look, then stalks off. `); } healthDamage(slave, 1); switch (act) { case oral: slave.counter.oral++; return; case vaginal: slave.counter.vaginal++; slave.vagina = slave.vagina < 2 ? 2 : slave.vagina; return; case anal: slave.counter.anal++; slave.anus = slave.anus < 1 ? 1 : slave.anus; return; default: throw new Error(`Unexpected act type '${act} in completionFeline().`); } } mainSpan.append(r.join(' ')); return mainSpan; } // Post-sex Functions function sexEffects() { const mainSpan = App.UI.DOM.makeElement("span", '', ["flaw", "gain"]); if (jsRandom(1, 100) > 100 + slave.devotion) { switch (act) { case oral: if (slave.energy < 95 && slave.sexualFlaw !== "hates oral") { mainSpan.append(`Having ${anAnimal} fuck ${his} throat by force has given ${him} a hatred of oral sex. `); } slave.sexualFlaw = "hates oral"; break; case vaginal: if (slave.energy < 95 && slave.sexualFlaw !== "hates penetration") { mainSpan.append(`Having ${anAnimal} fuck ${him} by force has given ${him} a hatred of penetration. `); } slave.sexualFlaw = "hates penetration"; break; case anal: if (slave.energy < 95 && slave.sexualFlaw !== "hates anal") { mainSpan.append(`Having ${anAnimal} fuck ${his} asshole by force has given ${him} a hatred of anal penetration. `); } slave.sexualFlaw = "hates anal"; break; default: throw new Error(`Unexpected act type '${act}' in sexEffects().`); } } return mainSpan; } function cleanUp() { const mainSpan = document.createElement("span"), r = []; if (act !== oral) { if (act === vaginal) { if (slave.vagina === 3) { r.push(`${capFirstChar(animal.name)} cum drips out out of ${his} fucked-out hole. `); } else if (slave.vagina === 2) { r.push(`${capFirstChar(animal.name)} cum drips out out of ${his} stretched vagina. `); } else if (slave.vagina === 1) { r.push(`${His} still-tight pussy keeps the ${animal.name}'s cum inside ${him}. `); } else { r.push(`${capFirstChar(animal.name)} cum slides right out of ${his} gaping hole. `); } } else { if (slave.anus === 1) { r.push(`${His} still-tight asshole keeps the ${animal.name}'s cum inside ${him}. `); } else if (slave.anus === 2) { r.push(`${capFirstChar(animal.name)} cum drips out of ${his} loosened anus. `); } else { r.push(`${capFirstChar(animal.name)} cum slides right out of ${his} fucked-out asshole. `); } } if (canWalk(slave)) { if (slave.vagina > 0) { r.push(`${He} uses a quick douche to clean ${his} ${slave.vagina < 2 ? `tight` : slave.vagina > 3 ? `loose` : ``} pussy,`); } else { r.push(`${He} uses an enema to clean ${his} ${slave.anus < 2 ? `tight` : slave.anus < 3 ? `used` : `gaping`} butthole,`); } switch (slave.assignment) { case Job.BROTHEL: r.push(`just like ${he} does between each customer. `); break; case Job.CLUB: r.push(`just like ${he} does in the club. `); break; case Job.DAIRY: r.push(`to avoid besmirching the nice clean dairy. `); break; case Job.FARMYARD: r.push(`to avoid tainting the food in ${V.farmyardName}. `); break; case Job.QUARTER: r.push(`mostly to keep everything ${he} has to clean from getting any dirtier. `); break; case Job.WHORE: r.push(`before returning to offering it for sale. `); break; case Job.PUBLIC: r.push(`before returning to offering it for free. `); break; case Job.REST: r.push(`before crawling back into bed. `); break; case Job.MILKED: r.push(`${slave.lactation > 0 ? `before going to get ${his} uncomfortably milk-filled tits drained` : `and then rests until ${his} balls are ready to be drained again`}. `); break; case Job.HOUSE: r.push(`since ${his} chores didn't perform themselves while you used ${his} fuckhole. `); break; case Job.FUCKTOY: r.push(`before returning to await your next use of ${his} fuckhole, as though nothing had happened. `); break; case Job.SUBORDINATE: r.push(`though it's only a matter of time before another slave decides to play with ${his} fuckhole. `); break; case Job.HEADGIRL: r.push(`worried that ${his} charges got up to trouble while ${he} enjoyed ${his} ${properMaster()}'s use. `); break; case Job.BODYGUARD: r.push(`so ${he} can be fresh and ready for more sexual use even as ${he} guards your person. `); break; case Job.TEACHER: r.push(`before ${he} returns to teaching ${his} classes. `); break; default: r.push(`before ${he} returns to ${slave.assignment}. `); break; } } } mainSpan.append(r.join(' ')); return mainSpan; } // MARK: Virginity Check Functions function virginityCheck(type) { const mainSpan = document.createElement("span"), virginityLossSpan = App.UI.DOM.makeElement("span", '', ["virginity", "loss"]); switch (type) { case vaginal: if (act === vaginal && slave.vagina === 0) { virginityLossSpan.append(`${his} virginity is taken from ${him}${slave.devotion < -20 ? ` by force` : ``}. `); mainSpan.append(`The slave gives a loud ${slave.devotion > 20 ? `moan` : `groan`} as `, virginityLossSpan, ` `); mainSpan.append(virginityEffects(type)); } return mainSpan; case anal: if (act === anal && slave.anus === 0) { mainSpan.append(`The slave gives a loud ${slave.devotion > 20 ? `moan` : `groan`} as ${his} anal virginity is taken from ${him}${slave.devotion < -20 ? ` by force` : ``}. `); mainSpan.append(virginityEffects(type)); } return mainSpan; default: throw new Error(`Unexpected type value '${type}' in virginityCheck().`); } } function virginityEffects(type) { const mainSpan = document.createElement("span"), devotionSpan = document.createElement("span"), trustSpan = document.createElement("span"), healthSpan = App.UI.DOM.makeElement("span", '', ["health", "dec"]); switch (type) { case vaginal: if (slave.devotion >= -20) { if (slaveApproves()) { devotionSpan.classList.add("devotion", "inc"); devotionSpan.append(`increased ${his} devotion to you. `); mainSpan.append(`Losing ${his} virginity in such a painful manner has `, devotionSpan); slave.devotion += 10; } else { if (slave.devotion > 50) { devotionSpan.classList.add("devotion", "inc"); devotionSpan.append(`increased ${his} submission to you. `); mainSpan.append(`Since ${he} is well broken, losing ${his} virginity in such a manner has`, devotionSpan); slave.devotion += 5; } else if (slave.devotion >= -20) { devotionSpan.classList.add("devotion", "inc"); trustSpan.classList.add("trust", "dec"); devotionSpan.append(`increased ${his} submission to you,`); trustSpan.append(`fearful`); mainSpan.append(`Losing ${his} virginity in such a manner has`, devotionSpan, ` though ${he} is `, trustSpan, ` that you'll decide to only use ${him} to sate your animals' lust. `); slave.devotion += 5; slave.trust -= 5; } else { devotionSpan.classList.add("devotion", "dec"); trustSpan.classList.add("trust", "dec"); devotionSpan.append(`unhappy`); trustSpan.append(`fears`); mainSpan.append(`${He} is clearly `, devotionSpan, ` in the manner in which ${his} virginity has been taken, and ${he} `, trustSpan, ` you'll decide to only use ${him} to sate your animals' lust. `); slave.devotion -= 10; slave.trust -= 10; } } } else { devotionSpan.classList.add("devotion", "dec"); trustSpan.classList.add("trust", "dec"); devotionSpan.append(`reinforced the hatred ${he} holds towards you,`); trustSpan.append(`terrified`); mainSpan.append(`Having ${his} pearl of great price taken by a mere beast has `, devotionSpan, ` and ${he} is `, trustSpan, ` you'll only use ${him} as a plaything for your animals. `); slave.devotion -= 10; slave.trust -= 10; } healthSpan.append(`slightly damaged ${his} health. `); mainSpan.append(`Having ${his} cherry popped in such a manner was extremely painful and `, healthSpan); healthDamage(slave, 5); return mainSpan; case anal: if (slave.devotion >= -20) { if (slaveApproves()) { devotionSpan.classList.add("devotion", "inc"); devotionSpan.append(`increased ${his} devotion to you. `); mainSpan.append(`Losing ${his} anal virginity in such a painful manner has `, devotionSpan); slave.devotion += 10; } else { if (slave.devotion > 50) { devotionSpan.classList.add("devotion", "inc"); devotionSpan.append(`increased ${his} submission to you. `); mainSpan.append(`Since ${he} is well broken, losing ${his} anal virginity in such a manner has `, devotionSpan); slave.devotion += 5; } else if (slave.devotion >= -20) { devotionSpan.classList.add("devotion", "inc"); trustSpan.classList.add("trust", "dec"); devotionSpan.append(`increased ${his} submission to you,`); trustSpan.append(`fearful`); mainSpan.append(`Losing ${his} anal virginity in such a manner has `, devotionSpan, ` though ${he} is `, trustSpan, ` that you'll decide to only use ${him} to sate your animals' lust. `); slave.devotion += 5; slave.trust -= 5; } else { devotionSpan.classList.add("devotion", "dec"); trustSpan.classList.add("trust", "dec"); devotionSpan.append(`unhappy`); trustSpan.append(`fears`); mainSpan.append(`${He} is clearly `, devotionSpan, ` in the manner in which ${his} anal virginity has been taken, and ${he} `, trustSpan, ` you'll decide to only use ${him} to sate your animals' lust. `); slave.devotion -= 10; slave.trust -= 10; } } } else { devotionSpan.classList.add("devotion", "dec"); trustSpan.classList.add("trust", "dec"); devotionSpan.append(`reinforced the hatred ${he} holds towards you,`); trustSpan.append(`terrified`); mainSpan.append(`Having ${his} pearl of great price taken by a mere beast has `, devotionSpan, ` and ${he} is `, trustSpan, ` you'll only use ${him} as a plaything for your animals. `); slave.devotion -= 10; slave.trust -= 10; } healthSpan.append(`slightly damaged ${his} health. `); mainSpan.append(`Having ${his} rosebud broken in in such a manner was extremely painful and `, healthSpan); healthDamage(slave, 5); return mainSpan; default: throw new Error(`Unexpected type value '${type}' in virginityEffects().`); } } };