| @@ -226,6 +226,96 @@ function grappleAnalVore(attacker) { | |||
| }; | |||
| } | |||
| function grappleCockVore(attacker) { | |||
| return { | |||
| name: "Cock Vore", | |||
| desc: "Try to shove your opponent down your shaft.", | |||
| attack: function(defender) { | |||
| let success = statHealthCheck(attacker, defender, "str"); | |||
| if (success) { | |||
| attacker.changeStamina(-10); | |||
| defender.changeStamina(-25); | |||
| attacker.balls.feed(defender); | |||
| defender.flags.grappled = false; | |||
| attacker.cash += defender.cash; | |||
| changeMode("explore"); | |||
| return ["You gasp with pleasure as you shove " + defender.description("the") + "'s head into your throbbing shaft, quickly pulling them down into your churning balls.", newline, "You notice their wallet with $" + defender.cash + " lying on the ground. Score!"]; | |||
| } else { | |||
| attacker.changeStamina(-25); | |||
| defender.changeStamina(-10); | |||
| return ["Your grasp and shove " + defender.description("the") + ", but they manage to avoid becoming " + attacker.species + " chow."]; | |||
| } | |||
| }, requirements: [ | |||
| function(attacker, defender) { return isNormal(attacker) && isGrappled(defender) && defender.flags.shrunk != true ; } | |||
| ], conditions: [ | |||
| function(attacker, defender) { return defender.prefs.prey; }, | |||
| function(attacker, defender) { return defender.prefs.vore.cock > 0; }, | |||
| function(attacker, defender) { return attacker.prefs.pred.cock; } | |||
| ], | |||
| priority: 1, | |||
| }; | |||
| } | |||
| function grappleUnbirth(attacker) { | |||
| return { | |||
| name: "Unbirth", | |||
| desc: "Try to shove your opponent into your snatch.", | |||
| attack: function(defender) { | |||
| let success = statHealthCheck(attacker, defender, "str"); | |||
| if (success) { | |||
| attacker.changeStamina(-10); | |||
| defender.changeStamina(-25); | |||
| attacker.womb.feed(defender); | |||
| defender.flags.grappled = false; | |||
| attacker.cash += defender.cash; | |||
| changeMode("explore"); | |||
| return [defender.description("The") + " is powerless to resist as you stuff them head-first into your dripping sex. Ripples of pleasure roll up your spine as rhythmic clenches pull them deeper and deeper, eventually imprisoning your prey into your hot, tight womb.", newline, "You notice their wallet with $" + defender.cash + " lying on the ground. Score!"]; | |||
| } else { | |||
| attacker.changeStamina(-25); | |||
| defender.changeStamina(-10); | |||
| return ["Your grasp and shove " + defender.description("the") + ", but they manage to avoid becoming a " + attacker.species + " toy."]; | |||
| } | |||
| }, requirements: [ | |||
| function(attacker, defender) { return isNormal(attacker) && isGrappled(defender) && defender.flags.shrunk != true ; } | |||
| ], conditions: [ | |||
| function(attacker, defender) { return defender.prefs.prey; }, | |||
| function(attacker, defender) { return defender.prefs.vore.unbirth > 0; }, | |||
| function(attacker, defender) { return attacker.prefs.pred.unbirth; } | |||
| ], | |||
| priority: 1, | |||
| }; | |||
| } | |||
| function grappleBreastVore(attacker) { | |||
| return { | |||
| name: "Breast Vore", | |||
| desc: "Try to shove your opponent into your breasts.", | |||
| attack: function(defender) { | |||
| let success = statHealthCheck(attacker, defender, "str"); | |||
| if (success) { | |||
| attacker.changeStamina(-10); | |||
| defender.changeStamina(-25); | |||
| attacker.breasts.feed(defender); | |||
| defender.flags.grappled = false; | |||
| attacker.cash += defender.cash; | |||
| changeMode("explore"); | |||
| return ["You grin and ram " + defender.description("the") + " against your bare chest, enveloping their head in your greedy breast! Before they can recover from the surprise, you swiftly stuff the rest of their squirming body inside.", newline, "You notice their wallet with $" + defender.cash + " lying on the ground. Score!"]; | |||
| } else { | |||
| attacker.changeStamina(-25); | |||
| defender.changeStamina(-10); | |||
| return ["Your grasp and shove " + defender.description("the") + ", but they manage to avoid becoming " + attacker.species + " chow."]; | |||
| } | |||
| }, requirements: [ | |||
| function(attacker, defender) { return isNormal(attacker) && isGrappled(defender) && defender.flags.shrunk != true ; } | |||
| ], conditions: [ | |||
| function(attacker, defender) { return defender.prefs.prey; }, | |||
| function(attacker, defender) { return defender.prefs.vore.breast > 0; }, | |||
| function(attacker, defender) { return attacker.prefs.pred.breast; } | |||
| ], | |||
| priority: 1, | |||
| }; | |||
| } | |||
| function grappleRelease(attacker) { | |||
| return { | |||
| name: "Release", | |||
| @@ -198,6 +198,37 @@ | |||
| <label for="character-prefs-prey">Player can be eaten</label> | |||
| <input type="checkbox" id="character-prefs-prey" name="prefs-prey" checked="true" /> | |||
| </li> | |||
| <li> | |||
| <ul class="pref-list"> | |||
| <div>Player stuff</div> | |||
| <li class="pref-select"> | |||
| <span class="pref-type">Cock/balls</span> | |||
| <input type="radio" class="pref-radio" id="character-parts-cock-off" name="parts-cock" value="0" /> | |||
| <label class="pref-disable" for="character-parts-cock-off">Disable</label> | |||
| <input type="radio" class="pref-radio" id="character-parts-cock-on" name="parts-cock" checked="true" value="1" /> | |||
| <label class="pref-enable" for="character-parts-cock-on" checked="true">Enable</label> | |||
| <input type="radio" class="pref-radio" id="character-parts-cock-vore" name="parts-cock" checked="true" value="2" /> | |||
| <label class="pref-prefer" for="character-parts-cock-vore" checked="true">Enable Vore</label> | |||
| </li> | |||
| <li class="pref-select"> | |||
| <span class="pref-type">Slit/womb</span> | |||
| <input type="radio" class="pref-radio" id="character-parts-unbirth-off" name="parts-unbirth" value="0" /> | |||
| <label class="pref-disable" for="character-parts-unbirth-off">Disable</label> | |||
| <input type="radio" class="pref-radio" id="character-parts-unbirth-on" name="parts-unbirth" checked="true" value="1" /> | |||
| <label class="pref-enable" for="character-parts-unbirth-on" checked="true">Enable</label> | |||
| <input type="radio" class="pref-radio" id="character-parts-unbirth-vore" name="parts-unbirth" checked="true" value="2" /> | |||
| <label class="pref-prefer" for="character-parts-unbirth-vore" checked="true">Enable Vore</label> | |||
| </li> | |||
| <li class="pref-select"> | |||
| <span class="pref-type">Breasts</span> | |||
| <input type="radio" class="pref-radio" id="character-parts-breast-off" name="parts-breast" value="0" /> | |||
| <label class="pref-disable" for="character-parts-breast-off">Disable</label> | |||
| <input type="radio" class="pref-radio" id="character-parts-breast-on" name="parts-breast" checked="true" value="1" /> | |||
| <label class="pref-enable" for="character-parts-breast-on" checked="true">Enable</label> | |||
| <input type="radio" class="pref-radio" id="character-parts-breast-vore" name="parts-breast" checked="true" value="2" /> | |||
| <label class="pref-prefer" for="character-parts-breast-vore" checked="true">Enable Vore</label> | |||
| </li> | |||
| </ul> | |||
| <li> | |||
| <ul class="pref-list"> | |||
| <div>Enemy vore types</div> | |||
| @@ -256,6 +287,17 @@ | |||
| <input type="radio" class="pref-radio" id="character-prefs-vore-unbirth-3" name="prefs-vore-unbirth" value="3" /> | |||
| <label class="pref-prefer" for="character-prefs-vore-unbirth-3">Prefer</label> | |||
| </li> | |||
| <li class="pref-select"> | |||
| <span class="pref-type">Breast</span> | |||
| <input type="radio" class="pref-radio" id="character-prefs-vore-breast-0" name="prefs-vore-breast" value="0" /> | |||
| <label class="pref-disable" for="character-prefs-vore-breast-0">Disable</label> | |||
| <input type="radio" class="pref-radio" id="character-prefs-vore-breast-1" name="prefs-vore-breast" value="1" /> | |||
| <label class="pref-avoid" for="character-prefs-vore-breast-1">Avoid</label> | |||
| <input type="radio" class="pref-radio" id="character-prefs-vore-breast-2" name="prefs-vore-breast" checked="true" value="2" /> | |||
| <label class="pref-enable" for="character-prefs-vore-breast-2">Enable</label> | |||
| <input type="radio" class="pref-radio" id="character-prefs-vore-breast-3" name="prefs-vore-breast" value="3" /> | |||
| <label class="pref-prefer" for="character-prefs-vore-breast-3">Prefer</label> | |||
| </li> | |||
| <li class="pref-select"> | |||
| <span class="pref-type">Hard</span> | |||
| <input type="radio" class="pref-radio" id="character-prefs-vore-hard-0" name="prefs-vore-hard" checked="true" value="0" /> | |||
| @@ -279,6 +279,8 @@ function advanceTime(amount) { | |||
| update(player.stomach.digest(amount)); | |||
| update(player.butt.digest(amount)); | |||
| update(player.balls.digest(amount)); | |||
| update(player.womb.digest(amount)); | |||
| update(player.breasts.digest(amount)); | |||
| } | |||
| function renderTime(time) { | |||
| @@ -386,12 +388,23 @@ function applySettings(settings) { | |||
| if (key.match(/prefs/)) { | |||
| let tokens = key.split("-"); | |||
| let pref = player.prefs; | |||
| // construct missing child dictionaries if needed :) | |||
| pref = tokens.slice(1,-1).reduce(function(pref, key) { | |||
| if (pref[key] == undefined) | |||
| pref[key] = {}; | |||
| return pref[key]; | |||
| }, pref); | |||
| pref[tokens.slice(-1)[0]] = settings[key]; | |||
| } else if(key.match(/parts/)) { | |||
| let tokens = key.split("-"); | |||
| player.parts[tokens[1]] = settings[key] >= 1; | |||
| if (player.prefs.pred == undefined) | |||
| player.prefs.pred = {}; | |||
| player.prefs.pred[tokens[1]] = settings[key] >= 2; | |||
| } | |||
| } | |||
| } | |||
| @@ -503,7 +516,7 @@ function respawn(respawnRoom) { | |||
| player.clear(); | |||
| player.stomach.contents = []; | |||
| player.butt.contents = []; | |||
| player.bowels.contents = []; | |||
| player.bowels.digested = []; | |||
| player.bowels.fullness = 0; | |||
| advanceTime(Math.floor(86400 / 2 * (Math.random() * 0.5 - 0.25 + 1))); | |||
| changeMode("explore"); | |||
| @@ -730,6 +743,99 @@ function status() { | |||
| lines.push(newline); | |||
| } | |||
| if (player.parts.cock) { | |||
| if (player.balls.contents.length > 0) { | |||
| lines.push("Your balls are bulging with prey."); | |||
| player.balls.contents.map(function(prey) { | |||
| let state = ""; | |||
| let healthRatio = prey.health / prey.maxHealth; | |||
| if (healthRatio > 0.75) { | |||
| state = "is writhing in your sac"; | |||
| } else if (healthRatio > 0.5) { | |||
| state = "is struggling in a pool of cum"; | |||
| } else if (healthRatio > 0.25) { | |||
| state = "is starting to turn soft"; | |||
| } else if (healthRatio > 0) { | |||
| state = "is barely visible anymore"; | |||
| } else { | |||
| state = "has succumbed to your balls"; | |||
| } | |||
| lines.push(prey.description("A") + " " + state); | |||
| }); | |||
| lines.push(newline); | |||
| } else { | |||
| if (player.balls.fullness > 0) { | |||
| lines.push("Your balls are heavy with cum."); | |||
| lines.push(newline); | |||
| } | |||
| } | |||
| } | |||
| if (player.parts.unbirth) { | |||
| if (player.womb.contents.length > 0) { | |||
| lines.push("Your slit drips, hinting at prey trapped within."); | |||
| player.womb.contents.map(function(prey) { | |||
| let state = ""; | |||
| let healthRatio = prey.health / prey.maxHealth; | |||
| if (healthRatio > 0.75) { | |||
| state = "is thrashing in your womb"; | |||
| } else if (healthRatio > 0.5) { | |||
| state = "is pressing out inside your lower belly"; | |||
| } else if (healthRatio > 0.25) { | |||
| state = "is still trying to escape"; | |||
| } else if (healthRatio > 0) { | |||
| state = "is barely moving"; | |||
| } else { | |||
| state = "is dissolving into femcum"; | |||
| } | |||
| lines.push(prey.description("A") + " " + state); | |||
| }); | |||
| lines.push(newline); | |||
| } else { | |||
| if (player.womb.fullness > 0) { | |||
| lines.push("Your slit drips, holding back a tide of femcum."); | |||
| lines.push(newline); | |||
| } | |||
| } | |||
| } | |||
| if (player.parts.breast) { | |||
| if (player.breasts.contents.length > 0) { | |||
| lines.push("Your breasts are bulging with prey."); | |||
| player.breasts.contents.map(function(prey) { | |||
| let state = ""; | |||
| let healthRatio = prey.health / prey.maxHealth; | |||
| if (healthRatio > 0.75) { | |||
| state = "is struggling to escape"; | |||
| } else if (healthRatio > 0.5) { | |||
| state = "is putting up a fight"; | |||
| } else if (healthRatio > 0.25) { | |||
| state = "is starting to weaken"; | |||
| } else if (healthRatio > 0) { | |||
| state = "is struggling to keep their head free of your milk"; | |||
| } else { | |||
| state = "has succumbed, swiftly melting into milk"; | |||
| } | |||
| lines.push(prey.description("A") + " " + state); | |||
| }); | |||
| lines.push(newline); | |||
| } else { | |||
| if (player.breasts.fullness > 0) { | |||
| lines.push("Your breasts slosh with milk."); | |||
| lines.push(newline); | |||
| } | |||
| } | |||
| } | |||
| update(lines); | |||
| } | |||
| @@ -37,11 +37,11 @@ function Toilet() { | |||
| player.bowels.fullness = 0; | |||
| } | |||
| if (player.bowels.contents.length > 0) { | |||
| lines.push("The remains of " + join(player.bowels.contents) + " empty into the sewers as you flush them away."); | |||
| if (player.bowels.digested.length > 0) { | |||
| lines.push("The remains of " + join(player.bowels.digested) + " empty into the sewers as you flush them away."); | |||
| } | |||
| player.bowels.contents = []; | |||
| player.bowels.digested = []; | |||
| update(lines); | |||
| }, | |||
| @@ -4,10 +4,6 @@ function Creature(name = "Creature", str = 10, dex = 10, con = 10) { | |||
| this.name = name; | |||
| this.mass = 80; | |||
| this.bowels = new Bowels(); | |||
| this.stomach = new Stomach(this, this.bowels); | |||
| this.butt = new Butt(this, this.bowels, this.stomach); | |||
| this.balls = new Balls(this); | |||
| this.attacks = []; | |||
| this.baseStr = str; | |||
| @@ -89,6 +85,7 @@ function Creature(name = "Creature", str = 10, dex = 10, con = 10) { | |||
| anal: 1, | |||
| cock: 1, | |||
| unbirth: 1, | |||
| breast: 1, | |||
| hard: 1, | |||
| soul: 1 | |||
| } | |||
| @@ -138,28 +135,40 @@ function Player(name = "Player") { | |||
| return this.stomach.fullness() + this.butt.fullness(); | |||
| }; | |||
| this.attacks.push(new punchAttack(this)); | |||
| this.attacks.push(new flankAttack(this)); | |||
| this.attacks.push(punchAttack(this)); | |||
| this.attacks.push(flankAttack(this)); | |||
| this.attacks.push(new grapple(this)); | |||
| this.attacks.push(new grappleSubdue(this)); | |||
| this.attacks.push(new grappleDevour(this)); | |||
| this.attacks.push(new grappleAnalVore(this)); | |||
| this.attacks.push(new grappleRelease(this)); | |||
| this.attacks.push(grapple(this)); | |||
| this.attacks.push(grappleSubdue(this)); | |||
| this.attacks.push(grappleDevour(this)); | |||
| this.attacks.push(grappleAnalVore(this)); | |||
| this.attacks.push(grappleCockVore(this)); | |||
| this.attacks.push(grappleUnbirth(this)); | |||
| this.attacks.push(grappleBreastVore(this)); | |||
| this.attacks.push(grappleRelease(this)); | |||
| this.attacks.push(new grappledStruggle(this)); | |||
| this.attacks.push(new grappledReverse(this)); | |||
| this.attacks.push(grappledStruggle(this)); | |||
| this.attacks.push(grappledReverse(this)); | |||
| this.attacks.push(new shrunkGrapple(this)); | |||
| this.attacks.push(new shrunkSwallow(this)); | |||
| this.attacks.push(new shrunkStomp(this)); | |||
| this.attacks.push(shrunkGrapple(this)); | |||
| this.attacks.push(shrunkSwallow(this)); | |||
| this.attacks.push(shrunkStomp(this)); | |||
| this.attacks.push(new pass(this)); | |||
| this.attacks.push(new flee(this)); | |||
| this.attacks.push(pass(this)); | |||
| this.attacks.push(flee(this)); | |||
| this.backupAttack = new pass(this); | |||
| this.backupAttack = pass(this); | |||
| this.cash = 100; | |||
| this.bowels = new Bowels(); | |||
| this.stomach = new Stomach(this, this.bowels); | |||
| this.butt = new Butt(this, this.bowels, this.stomach); | |||
| this.balls = new Balls(this); | |||
| this.womb = new Womb(this); | |||
| this.breasts = new Breasts(this); | |||
| this.parts = {}; | |||
| } | |||
| function Anthro(name = "Anthro") { | |||
| @@ -422,7 +431,7 @@ function WasteContainer(name) { | |||
| this.fullness = 0; | |||
| this.contents = []; | |||
| this.digested = []; | |||
| this.add = function(amount) { | |||
| this.fullness += amount; | |||
| @@ -430,7 +439,7 @@ function WasteContainer(name) { | |||
| this.finish = function(prey) { | |||
| if (prey.prefs.scat) | |||
| this.contents.push(prey); | |||
| this.digested.push(prey); | |||
| }; | |||
| } | |||
| @@ -456,7 +465,59 @@ function Balls(owner) { | |||
| this.finish = function(prey) { | |||
| if (prey.prefs.scat) | |||
| this.contents.push(prey); | |||
| this.digested.push(prey); | |||
| }; | |||
| } | |||
| function Womb(owner) { | |||
| Container.call(this, owner); | |||
| WasteContainer.call(this, "Womb"); | |||
| this.describeDamage = function(prey) { | |||
| return "You shiver as " + prey.description("the") + " squrims within your womb."; | |||
| }; | |||
| this.describeKill = function(prey) { | |||
| return "Your womb clenches and squeezes, overwhelming " + prey.description("the") + " trapped within."; | |||
| }; | |||
| this.describeFinish = function(prey) { | |||
| return "Your womb dissolves " + prey.description("a") + " into femcum."; | |||
| }; | |||
| this.fill = function(amount) { | |||
| this.add(amount); | |||
| }; | |||
| this.finish = function(prey) { | |||
| if (prey.prefs.scat) | |||
| this.digested.push(prey); | |||
| }; | |||
| } | |||
| function Breasts(owner) { | |||
| Container.call(this, owner); | |||
| WasteContainer.call(this, "Breasts"); | |||
| this.describeDamage = function(prey) { | |||
| return "Your breasts slosh from side to side, steadily softening " + prey.description("the") + " trapped within."; | |||
| }; | |||
| this.describeKill = function(prey) { | |||
| return prey.description("The") + " gives one last mighty shove...and then slumps back in your breasts."; | |||
| }; | |||
| this.describeFinish = function(prey) { | |||
| return "Your breasts have broken " + prey.description("a") + " down to creamy milk."; | |||
| }; | |||
| this.fill = function(amount) { | |||
| this.add(amount); | |||
| }; | |||
| this.finish = function(prey) { | |||
| if (prey.prefs.scat) | |||
| this.digested.push(prey); | |||
| }; | |||
| } | |||