Newer
Older
/**
* @param {App.Entity.SlaveState} slave
*/
App.Interact.fAnimal = function(slave, type) {
const
frag = new DocumentFragment(),
r = [],

brickode
committed
{He, he, him, his, girl} = getPronouns(slave),
acts = {
VAGINAL: "vaginal",
ANAL: "anal",
ORAL: "oral",
},
vaginal = acts.VAGINAL,
anal = acts.ANAL,
oral = acts.ORAL;
let
animal,
fetishDesc,
act;
switch (type) {
case "canine":
animal = V.activeCanine;
break;
case "hooved":
animal = V.activeHooved;
break;
case "feline":
animal = V.activeFeline;
break;
}
if (slave.assignment === Job.FUCKTOY || slave.assignment === Job.MASTERSUITE) {
isVowel = e => /[aeiou]/.test(e),
a = isVowel(animal.charAt(0).toLowerCase()) ? `an` : `a`,
slaveApproves = () => slave.fetish.includes("masochist" || "humiliation") ||
slave.fetish === "buttslut" && act === anal ||
slave.fetish === "cumslut" && act === oral ||
slave.sexualQuirk === "gagfuck queen" && act === oral ||
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);
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) {
introDevoted();
} else if (slave.devotion > 20) {
introNondevoted();
}
} else {
r.push(`${slave.slaveName} nods ${his} head dumbly, ${his} eyes vacant${!canSee(slave) ? ` as always` : ``}.`);
}
if (slave.devotion > 50) {
consummationDevoted();
} else if (slave.devotion > 20) {
consummationNondevoted();
mainDiv.append(r.join(' '));
return frag;
if (slaveApproves()) {
r.push(`${slave.slaveName}'s face visibly brightens at the prospect of ${fetishDesc}, even if it's ${a} ${animal}'s cum.`);
} else {
r.push(`${slave.slaveName} visibly blanches at the thought of having to suck down ${a} ${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)) {
r.push(`${slave.slaveName}'s face visibly brightens at the thought of ${fetishDesc}, even if the dick is ${a} ${animal}'s.`);
r.push(`${slave.slaveName} looks visibly disturbed, but is so attentive to your will that ${he} agrees.`);
if (slaveApproves()) {
r.push(`${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 {
r.push(`${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.`);
if (slaveApproves()) {
r.push(`${slave.slaveName} isn't too keen on the idea of sucking off ${a} ${animal}, but the idea of ${fetishDesc} is enough to get ${him} to comply.`);
} else {
r.push(`${slave.slaveName} tries in vain to conceal ${his} horror at the thought of blowing ${a} ${animal}, but quickly regains ${his} composure.`);
}
} else {
if ((act === vaginal && slave.vagina > 0) || (act === anal && slave.anus > 0)) {
if (slaveApproves()) {
r.push(`${slave.slaveName} doesn't seem terribly keen on the idea of fucking ${a} ${animal}, but the thought of ${fetishDesc} seems to be enough to win ${him} over.`);
} else {
r.push(`${slave.slaveName} tries in vain to coneal ${his} horror at the thought of fucking ${a} ${animal}, but quickly regains ${his} composure.`);
}
} else {
if (slaveApproves()) {
r.push(`${slave.slaveName} clearly has some reservations about having ${his} ${act === anal ? `anal ` : ``}virginity taken by ${a} ${fetishDesc}, but the thought of ${fetishDesc} is enough to make agree to comply.`);
r.push(`${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.`);
if (slaveApproves()) {
r.push(`${slave.slaveName} looks disgusted at the thought of sucking off ${a} ${animal} at first, but the thought of the ${fetishDesc} that comes with it seems to spark a small flame of lust in ${him}.`);
} else {
r.push(`${slave.slaveName} tries in vain to conceal ${his} horror at the thought of blowing ${a} ${animal}${canWalk(slave) ? `, and only the threat of worse punishment keeps ${him} from running away as fast as ${he} can` : ``}.`);
if ((act === vaginal && slave.vagina > 0) || (act === anal && slave.anus > 0)) {
if (slaveApproves()) {
r.push(`${slave.slaveName} looks disgusted at the thought of fucking ${a} ${animal} at first, but the thought of the ${fetishDesc} that comes with it seems to spark a small flame of lust in ${him}.`);
} else {
r.push(`${slave.slaveName} tries in vain to coneal ${his} horror at the thought of fucking ${a} ${animal}${canWalk(slave) ? `, and only the threat of worse punishment keeps ${him} from running away as fast as ${he} can` : ``}.`);
r.push(`${slave.slaveName} clearly has some reservations about having ${his} ${act === anal ? `anal ` : ``}virginity taken by ${a} ${fetishDesc}, but the thought of ${fetishDesc} is enough to make agree to comply.`);
r.push(`${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` : ``}.`);
function introResistant() {
r.push(`${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`}.`);
}
// MARK: Consummation Functions
function consummationDevoted() {
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.`);

brickode
committed
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.`);

brickode
committed
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()`);
}

brickode
committed

brickode
committed
virginityCheck(act);
}
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.`);
}

brickode
committed
} 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`}.`);
}

brickode
committed
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.`);
}

brickode
committed
}
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.`);
}

brickode
committed
}
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() {
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.`);
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
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`}.`);
}

brickode
committed
// MARK: Virginity Check Functions
function virginityCheck(type) {
switch (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);

brickode
committed
}

brickode
committed
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);

brickode
committed
}

brickode
committed
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
default:
throw new Error(`Unexpected type value '${type}' in virginityCheck()`);
}
}
function virginityEffects(type) {
switch (type) {
case vaginal:
if (slave.devotion >= -20) {
if (slaveApproves) {
r.push(`Losing ${his} virginity in such a painful manner has increased ${his} devotion to you.`);
slave.devotion += 10;
} else {
if (slave.devotion > 50) {
r.push(`Since ${he} is well broken, losing ${his} virginity in such a manner has increased ${his} submission to you.`);
slave.devotion += 5;
} else if (slave.devotion >= -20) {
r.push(`Losing ${his} virginity in such a manner has increased ${his} submission to you, though ${he} is fearful that you'll decide to only use ${him} to sate your animals' lust.`);
slave.devotion += 5;
slave.trust -= 5;
} else {
r.push(`${He} is clearly unhappy in the manner in which ${his} virginity has been taken, and ${he} fears you'll decide to only use ${him} to sate your animals' lust.`);
slave.devotion -= 10;
slave.trust -= 10;
}
}
} else {
r.push(`Having ${his} pearl of great price taken by a mere beast has reinforced the hatred ${he} holds towards you, and ${he} is terrified you'll only use ${him} as a plaything for your animals.`);
slave.devotion -= 10;
slave.trust -= 10;
}
r.push(`Having ${his} cherry popped in such a manner was extremely painful and slightly damaged ${his} health.`);
healthDamage(slave, 5);
return;
case anal:
if (slave.devotion >= -20) {
if (slaveApproves) {
r.push(`Losing ${his} anal virginity in such a painful manner has increased ${his} devotion to you.`);
slave.devotion += 10;
} else {
if (slave.devotion > 50) {
r.push(`Since ${he} is well broken, losing ${his} anal virginity in such a manner has increased ${his} submission to you.`);
slave.devotion += 5;
} else if (slave.devotion >= -20) {
r.push(`Losing ${his} anal virginity in such a manner has increased ${his} submission to you, though ${he} is fearful that you'll decide to only use ${him} to sate your animals' lust.`);
slave.devotion += 5;
slave.trust -= 5;
} else {
r.push(`${He} is clearly unhappy in the manner in which ${his} anal virginity has been taken, and ${he} fears you'll decide to only use ${him} to sate your animals' lust.`);
slave.devotion -= 10;
slave.trust -= 10;
}
}
} else {
r.push(`Having ${his} pearl of great price taken by a mere beast has reinforced the hatred ${he} holds towards you, and ${he} is terrified you'll only use ${him} as a plaything for your animals.`);
slave.devotion -= 10;
slave.trust -= 10;
}
r.push(`Having ${his} rosebud broken in in such a manner was extremely painful and slightly damaged ${his} health.`);
healthDamage(slave, 5);
return;
default:
throw new Error(`Unexpected type value '${type}' in virginityEffects()`);
}
}