munch
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 

769 рядки
30 KiB

  1. "use strict";
  2. function attack(attacker, defender, baseDamage) {
  3. let damage = Math.round((Math.random() * 0.5 - 0.25 + 1) * baseDamage);
  4. defender.health -= damage;
  5. return damage;
  6. }
  7. function isNormal(entity) {
  8. return entity.flags.grappled != true && entity.flags.shrunk != true;
  9. }
  10. function isNormalSize(entity) {
  11. return entity.flags.shrunk != true;
  12. }
  13. function isGrappled(entity) {
  14. return entity.flags.grappled == true;
  15. }
  16. function doComp(attackStat, defendStat) {
  17. return Math.random() * attackStat > Math.random() * defendStat;
  18. }
  19. function statCheck(attacker, defender, stat) {
  20. return doComp(attacker[stat], defender[stat]);
  21. }
  22. function statHealthCheck(attacker, defender, stat) {
  23. let attackerPercent = 0.5 + 0.5 * attacker.health / attacker.maxHealth;
  24. let defenderPercent = 0.5 + 0.5 * defender.health / defender.maxHealth;
  25. if (attacker.stamina <= 0)
  26. attackerPercent /= 2;
  27. if (defender.stamina <= 0)
  28. defenderPercent /= 2;
  29. return doComp(attacker[stat] * attackerPercent, defender[stat] * defenderPercent);
  30. }
  31. function punchAttack(attacker) {
  32. return {
  33. name: "Punch",
  34. desc: "Punch a nerd",
  35. attack: function(defender) {
  36. return ["You punch " + defender.description("the") + " for " + attack(attacker, defender, attacker.str) + " damage"];
  37. },
  38. attackPlayer: function(defender) {
  39. return [attacker.description("The") + " punches you for " + attack(attacker, defender, attacker.str) + " damage"];
  40. }, requirements: [
  41. function(attacker, defender) { return isNormal(attacker) && isNormal(defender); }
  42. ],
  43. priority: 1,
  44. weight: function(attacker, defender) { return defender.health / defender.maxHealth; }
  45. };
  46. }
  47. function flankAttack(attacker) {
  48. return {
  49. name: "Flank",
  50. desc: "Be sneaky",
  51. attack: function(defender) {
  52. return ["You run around " + defender.description("the") + " and attack for " + attack(attacker, defender, attacker.dex) + " damage"];
  53. },
  54. attackPlayer: function(defender) {
  55. return [attacker.description("The") + " runs past you, then turns and hits you for " + attack(attacker, defender, attacker.str) + " damage"];
  56. }, requirements: [
  57. function(attacker, defender) { return isNormal(attacker) && isNormal(defender); }
  58. ],
  59. priority: 1,
  60. weight: function(attacker, defender) { return defender.health / defender.maxHealth; }
  61. };
  62. }
  63. function grapple(attacker, weightFactor = 1) {
  64. return {
  65. name: "Grapple",
  66. desc: "Try to grab your opponent",
  67. attack: function(defender) {
  68. let success = statHealthCheck(attacker, defender, "str");
  69. if (success) {
  70. attacker.changeStamina(-20);
  71. defender.changeStamina(-20);
  72. defender.flags.grappled = true;
  73. return ["You charge at " + defender.description("the") + ", tackling them and knocking them to the ground."];
  74. } else {
  75. attacker.changeStamina(-20);
  76. return ["You charge at " + defender.description("the") + ", but they dodge out of the way!"];
  77. }
  78. },
  79. attackPlayer: function(defender) {
  80. let success = statHealthCheck(attacker, defender, "str");
  81. if (success) {
  82. attacker.changeStamina(-20);
  83. defender.changeStamina(-20);
  84. defender.flags.grappled = true;
  85. return [attacker.description("The") + " lunges at you, pinning you to the floor!"];
  86. } else {
  87. return [attacker.description("The") + " tries to tackle you, but you deftly avoid them."];
  88. }
  89. },
  90. requirements: [
  91. function(attacker, defender) { return isNormal(attacker) && isNormal(defender); },
  92. function(attacker, defender) { return defender.prefs.grapple; }
  93. ],
  94. priority: 1,
  95. weight: function(attacker, defender) { return weightFactor - weightFactor * defender.health / defender.maxHealth; }
  96. };
  97. }
  98. function grappleSubdue(attacker) {
  99. return {
  100. name: "Subdue",
  101. desc: "Try to subdue your opponent",
  102. attack: function(defender) {
  103. attacker.changeStamina(-10);
  104. defender.changeStamina(-30);
  105. return ["You beat on " + defender.description("the") + " for " + attack(attacker, defender, attacker.str * 2) + " damage."];
  106. },
  107. attackPlayer: function(defender) {
  108. attacker.changeStamina(-10);
  109. defender.changeStamina(-30);
  110. return [attacker.description("The") + " beats you for " + attack(attacker, defender, attacker.str * 2) + " damage"];
  111. },
  112. requirements: [
  113. function(attacker, defender) {
  114. return isNormal(attacker) && isGrappled(defender);
  115. }
  116. ],
  117. priority: 1,
  118. weight: function(attacker, defender) { return defender.health / defender.maxHealth; }
  119. };
  120. }
  121. function grappleDevour(attacker) {
  122. return {
  123. name: "Devour",
  124. desc: "Try to consume your grappled opponent",
  125. attack: function(defender) {
  126. let success = statHealthCheck(attacker, defender, "str");
  127. if (success) {
  128. attacker.changeStamina(-10);
  129. defender.changeStamina(-25);
  130. attacker.stomach.feed(defender);
  131. defender.flags.grappled = false;
  132. changeMode("explore");
  133. attacker.cash += defender.cash;
  134. return ["You open your jaws wide, stuffing " + defender.description("the") + "'s head into your gullet and greedily wolfing them down. Delicious.", newline, "You hack up their wallet with $" + defender.cash + " inside a moment later. Nice!"];
  135. } else {
  136. attacker.changeStamina(-25);
  137. defender.changeStamina(-10);
  138. return ["Your jaws open wide, but " + defender.description("the") + " manages to avoid becoming " + attacker.species + " chow."];
  139. }
  140. },
  141. attackPlayer: function(defender) {
  142. let success = statHealthCheck(attacker, defender, "str");
  143. if(success) {
  144. defender.flags.grappled = false;
  145. changeMode("eaten");
  146. return [attacker.description("The") + " forces your head into their sloppy jaws, devouring you despite your frantic struggles. Glp."];
  147. } else {
  148. return [attacker.description("The") + " tries to swallow you down, but you manage to resist their hunger."];
  149. }
  150. }, requirements: [
  151. function(attacker, defender) { return isNormal(attacker) && isGrappled(defender) && defender.flags.shrunk != true; }
  152. ], conditions: [
  153. function(attacker, defender) { return defender.prefs.prey; },
  154. function(attacker, defender) { return defender.prefs.vore.oral > 0; }
  155. ],
  156. priority: 1,
  157. weight: function(attacker, defender) { return 1 - defender.health / defender.maxHealth; }
  158. };
  159. }
  160. function grappledDevour(attacker) {
  161. return {
  162. name: "Devour",
  163. desc: "Try to consume your grappling opponent",
  164. attackPlayer: function(defender) {
  165. let success = statHealthCheck(attacker, defender, "str");
  166. if(success) {
  167. defender.flags.grappled = false;
  168. changeMode("eaten");
  169. return [attacker.description("The") + " breaks your pin and crams your upper body into their maw, swallowing you down in seconds."];
  170. } else {
  171. attacker.changeStamina(-10);
  172. return [attacker.description("The") + " thrashes at you in an attempt to devour you, but you avoid their jaws."];
  173. }
  174. }, requirements: [
  175. function(attacker, defender) { return isGrappled(attacker) && isNormal(defender) && attacker.flags.shrunk != true; }
  176. ], conditions: [
  177. function(attacker, defender) { return defender.prefs.prey; },
  178. function(attacker, defender) { return defender.prefs.vore.oral > 0; }
  179. ],
  180. priority: 1,
  181. };
  182. }
  183. function grappleAnalVore(attacker) {
  184. return {
  185. name: "Anal Vore",
  186. desc: "Try to shove your opponent up your ass.",
  187. attack: function(defender) {
  188. let success = statHealthCheck(attacker, defender, "str");
  189. if (success) {
  190. attacker.changeStamina(-10);
  191. defender.changeStamina(-25);
  192. attacker.bowels.feed(defender);
  193. defender.flags.grappled = false;
  194. attacker.cash += defender.cash;
  195. changeMode("explore");
  196. return ["You shove " + defender.description("the") + " between your cheeks. Their head slips into your ass with a wet <i>shlk</i>, and the rest of their body follows suit. You moan and gasp, working them deeper and deeper.", newline, "You notice their wallet with $" + defender.cash + " lying on the ground. Score!"];
  197. } else {
  198. attacker.changeStamina(-25);
  199. defender.changeStamina(-10);
  200. return ["Your grasp and shove " + defender.description("the") + ", but they manage to avoid becoming " + attacker.species + " chow."];
  201. }
  202. }, requirements: [
  203. function(attacker, defender) { return isNormal(attacker) && isGrappled(defender) && defender.flags.shrunk != true ; }
  204. ], conditions: [
  205. function(attacker, defender) { return defender.prefs.prey; },
  206. function(attacker, defender) { return defender.prefs.vore.anal > 0; },
  207. function(attacker, defender) { return attacker.prefs.pred.anal; }
  208. ],
  209. priority: 1,
  210. };
  211. }
  212. function grappleCockVore(attacker) {
  213. return {
  214. name: "Cock Vore",
  215. desc: "Try to shove your opponent down your shaft.",
  216. attack: function(defender) {
  217. let success = statHealthCheck(attacker, defender, "str");
  218. if (success) {
  219. attacker.changeStamina(-10);
  220. defender.changeStamina(-25);
  221. attacker.balls.feed(defender);
  222. defender.flags.grappled = false;
  223. attacker.cash += defender.cash;
  224. changeMode("explore");
  225. 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!"];
  226. } else {
  227. attacker.changeStamina(-25);
  228. defender.changeStamina(-10);
  229. return ["Your grasp and shove " + defender.description("the") + ", but they manage to avoid becoming " + attacker.species + " chow."];
  230. }
  231. }, requirements: [
  232. function(attacker, defender) { return isNormal(attacker) && isGrappled(defender) && defender.flags.shrunk != true ; }
  233. ], conditions: [
  234. function(attacker, defender) { return defender.prefs.prey; },
  235. function(attacker, defender) { return defender.prefs.vore.cock > 0; },
  236. function(attacker, defender) { return attacker.prefs.pred.cock; }
  237. ],
  238. priority: 1,
  239. };
  240. }
  241. function grappleUnbirth(attacker) {
  242. return {
  243. name: "Unbirth",
  244. desc: "Try to shove your opponent into your snatch.",
  245. attack: function(defender) {
  246. let success = statHealthCheck(attacker, defender, "str");
  247. if (success) {
  248. attacker.changeStamina(-10);
  249. defender.changeStamina(-25);
  250. attacker.womb.feed(defender);
  251. defender.flags.grappled = false;
  252. attacker.cash += defender.cash;
  253. changeMode("explore");
  254. 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!"];
  255. } else {
  256. attacker.changeStamina(-25);
  257. defender.changeStamina(-10);
  258. return ["Your grasp and shove " + defender.description("the") + ", but they manage to avoid becoming a " + attacker.species + " toy."];
  259. }
  260. }, requirements: [
  261. function(attacker, defender) { return isNormal(attacker) && isGrappled(defender) && defender.flags.shrunk != true ; }
  262. ], conditions: [
  263. function(attacker, defender) { return defender.prefs.prey; },
  264. function(attacker, defender) { return defender.prefs.vore.unbirth > 0; },
  265. function(attacker, defender) { return attacker.prefs.pred.unbirth; }
  266. ],
  267. priority: 1,
  268. };
  269. }
  270. function grappleBreastVore(attacker) {
  271. return {
  272. name: "Breast Vore",
  273. desc: "Try to shove your opponent into your breasts.",
  274. attack: function(defender) {
  275. let success = statHealthCheck(attacker, defender, "str");
  276. if (success) {
  277. attacker.changeStamina(-10);
  278. defender.changeStamina(-25);
  279. attacker.breasts.feed(defender);
  280. defender.flags.grappled = false;
  281. attacker.cash += defender.cash;
  282. changeMode("explore");
  283. 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!"];
  284. } else {
  285. attacker.changeStamina(-25);
  286. defender.changeStamina(-10);
  287. return ["Your grasp and shove " + defender.description("the") + ", but they manage to avoid becoming " + attacker.species + " chow."];
  288. }
  289. }, requirements: [
  290. function(attacker, defender) { return isNormal(attacker) && isGrappled(defender) && defender.flags.shrunk != true ; }
  291. ], conditions: [
  292. function(attacker, defender) { return defender.prefs.prey; },
  293. function(attacker, defender) { return defender.prefs.vore.breast > 0; },
  294. function(attacker, defender) { return attacker.prefs.pred.breast; }
  295. ],
  296. priority: 1,
  297. };
  298. }
  299. function grappleRelease(attacker) {
  300. return {
  301. name: "Release",
  302. desc: "Release your opponent",
  303. attack: function(defender) {
  304. defender.flags.grappled = false;
  305. defender.changeStamina(-15);
  306. return ["You throw " + defender.description("the") + " back, dealing " + attack(attacker, defender, attacker.str*1.5) + " damage"];
  307. }, requirements: [
  308. function(attacker, defender) { return isNormal(attacker) && isGrappled(defender); }
  309. ],
  310. priority: 1,
  311. };
  312. }
  313. function grappledStruggle(attacker) {
  314. return {
  315. name: "Struggle",
  316. desc: "Try to break your opponent's pin",
  317. attack: function(defender) {
  318. let success = statHealthCheck(attacker, defender, "str");
  319. if (success) {
  320. attacker.changeStamina(-5);
  321. defender.changeStamina(-10);
  322. attacker.flags.grappled = false;
  323. return ["You struggle and shove " + defender.description("the") + " off of you."];
  324. } else {
  325. attacker.changeStamina(-10);
  326. defender.changeStamina(-5);
  327. return ["You struggle, but to no avail."];
  328. }
  329. },
  330. attackPlayer: function(defender) {
  331. let success = statHealthCheck(attacker, defender, "str");
  332. if (success) {
  333. attacker.changeStamina(-5);
  334. defender.changeStamina(-10);
  335. attacker.flags.grappled = false;
  336. return ["Your prey shoves you back, breaking your grapple!"];
  337. } else {
  338. attacker.changeStamina(-10);
  339. defender.changeStamina(-5);
  340. return ["Your prey squirms, but remains pinned."];
  341. }
  342. },
  343. requirements: [
  344. function(attacker, defender) { return isGrappled(attacker) && isNormalSize(attacker) && isNormal(defender); }
  345. ],
  346. priority: 1,
  347. };
  348. }
  349. function grappledReverse(attacker) {
  350. return {
  351. name: "Reversal",
  352. desc: "Try to pin your grappler. Less likely to work than struggling.",
  353. attack: function(defender) {
  354. let success = statHealthCheck(attacker, defender, "str");
  355. if (success) {
  356. attacker.changeStamina(-5);
  357. defender.changeStamina(-15);
  358. attacker.flags.grappled = false;
  359. defender.flags.grappled = true;
  360. return ["You surprise " + defender.description("the") + " with a burst of strength, flipping them over and pinning them."];
  361. } else {
  362. attacker.changeStamina(-15);
  363. return ["You try to throw your opponent off of you, but fail."];
  364. }
  365. },
  366. attackPlayer: function(defender) {
  367. let success = statHealthCheck(attacker, defender, "str");
  368. if (success) {
  369. attacker.changeStamina(-5);
  370. defender.changeStamina(-15);
  371. attacker.flags.grappled = false;
  372. defender.flags.grappled = true;
  373. return ["Your prey suddenly grabs hold and flips you over, pinning you!"];
  374. } else {
  375. attacker.changeStamina(-15);
  376. return ["Your prey tries to grab at you, but you keep them under control."];
  377. }
  378. },
  379. conditions: [
  380. function(attacker, defender) { return defender.flags.grapple; }
  381. ],
  382. requirements: [
  383. function(attacker, defender) { return isGrappled(attacker) && isNormalSize(attacker) && isNormal(defender); },
  384. function(attacker, defender) { return attacker.flags.grappled; }
  385. ],
  386. priority: 1,
  387. };
  388. }
  389. function shrunkGrapple(attacker) {
  390. return {
  391. name: "Grab",
  392. desc: "Grab this fun-sized snack",
  393. attack: function(defender) {
  394. let success = statCheck(attacker, defender, "dex") || statCheck(attacker, defender, "dex");
  395. if (success) {
  396. defender.changeStamina(-25);
  397. defender.flags.grappled = true;
  398. return ["You snatch up " + defender.description("the")];
  399. } else {
  400. return ["You try to grab " + defender.description("the") + ", but they elude your grasp."];
  401. }
  402. },
  403. requirements: [
  404. function(attacker, defender) {
  405. return isNormal(attacker) && defender.flags.grappled != true && defender.flags.shrunk == true;
  406. }
  407. ],
  408. priority: 2
  409. };
  410. }
  411. function shrunkSwallow(attacker) {
  412. return {
  413. name: "Swallow",
  414. desc: "Swallow your prey",
  415. attack: function(defender) {
  416. defender.changeStamina(-50);
  417. changeMode("explore");
  418. attacker.stomach.feed(defender);
  419. return ["With a light swallow, " + defender.description("the") + " is dragged down to your sloppy guts."];
  420. },
  421. requirements: [
  422. function(attacker, defender) {
  423. return isNormal(attacker) && defender.flags.grappled == true && defender.flags.shrunk == true;
  424. }
  425. ], conditions: [
  426. function(attacker, defender) { return defender.prefs.prey; },
  427. function(attacker, defender) { return defender.prefs.vore.oral > 0; }
  428. ],
  429. priority: 2
  430. };
  431. }
  432. function shrunkStomp(attacker) {
  433. return {
  434. name: "Stomp",
  435. desc: "Stomp on your shrunken prey",
  436. attack: function(defender) {
  437. let success = statCheck(attacker, defender, "dex") || statCheck(attacker, defender, "dex") || defender.stamina == 0;
  438. defender.stamina = 0;
  439. defender.health = Math.max(0, defender.health - 50);
  440. return ["Your paw comes crashing down on " + defender.description("the") + ", burying them under your heavy toes and pinning them down hard."];
  441. },
  442. requirements: [
  443. function(attacker, defender) {
  444. return isNormal(attacker) && defender.flags.grappled != true && defender.flags.shrunk == true;
  445. }
  446. ]
  447. };
  448. }
  449. function flee(attacker) {
  450. return {
  451. name: "Flee",
  452. desc: "Try to run away",
  453. attack: function(defender) {
  454. let success = statCheck(attacker, defender, "dex");
  455. if (success) {
  456. attacker.changeStamina(-25);
  457. attacker.clear();
  458. changeMode("explore");
  459. return ["You successfully run away."];
  460. } else {
  461. attacker.changeStamina(-25);
  462. defender.changeStamina(-25);
  463. return ["You can't escape!"];
  464. }
  465. },
  466. requirements: [
  467. function(attacker, defender) { return isNormal(attacker) && !attacker.isGrappling; }
  468. ]
  469. };
  470. }
  471. function pass(attacker) {
  472. return {
  473. name: "Pass",
  474. desc: "You can't do anything!",
  475. attack: function(defender) {
  476. return ["You do nothing."];
  477. },
  478. attackPlayer: function(defender) {
  479. return [attacker.description("The") + " does nothing."];
  480. },
  481. priority: 0,
  482. };
  483. }
  484. function devourPlayer(attacker) {
  485. return {
  486. requirements: [
  487. function(attacker, defender) { return attacker.leering == true; }
  488. ],
  489. attackPlayer: function(defender) {
  490. attacker.flags.voreType = "oral";
  491. changeMode("eaten");
  492. return ["The voracious " + attacker.description() + " pins you down, his slimy maw spreading wide and engulfing your upper body with ease. He swallows and shoves you deeper, cramming your succulent frame into churning, crushing depths in seconds. A lazy, drawn-out <i>belch</i> escapes his gullet, his hunger briefly sated...and your existence now in inescapable peril."];
  493. }, conditions: [
  494. function(attacker, defender) { return defender.prefs.prey; },
  495. function(attacker, defender) { return defender.prefs.vore.oral > 0; }
  496. ],
  497. priority: 1,
  498. weight: function(attacker, defender) { return defender.prefs.vore.oral; }
  499. };
  500. }
  501. function devourPlayerAnal(attacker) {
  502. return {
  503. requirements: [
  504. function(attacker, defender) { return attacker.leering == true; }
  505. ],
  506. attackPlayer: function(defender) {
  507. attacker.flags.voreType = "anal";
  508. changeMode("eaten");
  509. return ["Fen grabs you and shoves you against the wall, turning around and slamming his ass against your face. Your entire head slips into his bowels with a wet <i>shlllrp</i>; there he holds you for a long minute, clenching and squeezing on his latest toy.",newline,"After what seems an eternity, his depths begin to pull...and within seconds, you're gone, dragged up his ass and imprisoned in his intestines. He moans softly, panting and curling his toes in delight."];
  510. }, conditions: [
  511. function(attacker, defender) { return defender.prefs.prey; },
  512. function(attacker, defender) { return defender.prefs.vore.anal > 0; }
  513. ],
  514. priority: 1,
  515. weight: function(attacker, defender) { return defender.prefs.vore.anal;}
  516. };
  517. }
  518. function devourPlayerHard(attacker) {
  519. return {
  520. requirements: [
  521. function(attacker, defender) { return attacker.leering == true; }
  522. ],
  523. attackPlayer: function(defender) {
  524. attacker.flags.voreType = "hard";
  525. attacker.flags.hardTurns = 0;
  526. changeMode("eaten");
  527. return [
  528. "Fen lunges at you, closing the gap in an instant, and slams you against a wall. His terrible jaws split wide and dive in, clamping around your shoulder and - with a disgusting <i>CRUNCH</i> - severs your left arm. His claws rake along your chest and shred your skin, ripping open your chest and breaking your ribcage with a mighty shove.",
  529. ];
  530. }, conditions: [
  531. function(attacker, defender) { return defender.prefs.prey; },
  532. function(attacker, defender) { return defender.prefs.vore.hard > 0; }
  533. ],
  534. priority: 1,
  535. weight: function(attacker, defender) { return defender.prefs.vore.hard;}
  536. };
  537. }
  538. function fenFeedHard(attacker) {
  539. return {
  540. digest: function(defender) {
  541. attacker.flags.hardTurns++;
  542. switch(attacker.flags.hardTurns) {
  543. case 1: return ["Growling and grunting, he holds you fast with one hand as he scarfs down your arm with the other, cracking bone and shredding flesh with ease...before leaning in and taking a small bite from your neck, cutting open your windpipe."];
  544. case 2: return ["Fen's jaws sever your other arm, ripping open your chest as he tears it free and swallows whole, a bulge forming in his neck as your limb sinks into his boiling stomach."];
  545. case 3: return ["The beast grabs your bloodied stumps and hoists you overhead, casually taking in your legs to the knees and shattering them with a crushing bite. <i>Glrrrrrph</i>."];
  546. case 4: return ["Another wretched bite severs your body above the hips, pulling your mostly-intact thighs down to be digested. Blood and gore pours from your body, staining the ground and the beast's fur with equal abandon."];
  547. case 5: return ["The crux disembowels you in seconds, consuming your body with unrelenting speed. You're little more than a bleeding, twitching chest and head..."];
  548. case 6: if (defender.prefs.vore.soul <= 0) {
  549. defender.health = -100;
  550. } else {
  551. attacker.flags.voreType = "hard-soul";
  552. }
  553. let lines = ["Taking pity - if that's the right word - the beast turns you over and stuffs your head into his maw, cutting it off and swallowing it whole."];
  554. if (defender.prefs.vore.soul > 0) {
  555. lines.push(newline);
  556. lines.push("...but he isn't done with you yet, ripping your soul from your dying, destroyed body and sucking it down into his hellish stomach. Your wispy essence stews amongst a thick, bubbling stew of meat and bone.");
  557. }
  558. return lines;
  559. }
  560. },
  561. requirements: [
  562. function(attacker, defender) {
  563. return attacker.flags.voreType == "hard";
  564. }
  565. ],
  566. priority: 1,
  567. gameover: function() { return "Ripped to shreds and consumed alive by " + attacker.description("a"); }
  568. };
  569. }
  570. function devourPlayerSoul(attacker) {
  571. return {
  572. requirements: [
  573. function(attacker, defender) { return attacker.leering == true; }
  574. ],
  575. attackPlayer: function(defender) {
  576. attacker.flags.voreType = "soul";
  577. changeMode("eaten");
  578. return [
  579. "Fen's gaze locks with yours, and you freeze up like a deer in headlights. A brief pulse of amber light washes through them...and he rips out your soul, sucking your essence out from your gaping mouth with terrifying ease. You watch it flow forth from your own eyes for several seconds before you're pulled out entirely, leaving your mind in a helpless, wispy cloud.",
  580. newline,
  581. "You pour into the crux's jaws like water, crammed into his throat and devoured in an instant. The rippling walls contain you as easily as they would any other prey, and before long you're plunged into a roiling hellscape of acid and slime."
  582. ];
  583. }, conditions: [
  584. function(attacker, defender) { return defender.prefs.prey; },
  585. function(attacker, defender) { return defender.prefs.vore.soul > 0; }
  586. ],
  587. priority: 1,
  588. weight: function(attacker, defender) { return defender.prefs.vore.soul;}
  589. };
  590. }
  591. function leer(attacker) {
  592. return {
  593. name: "Leer",
  594. desc: "Leer at something",
  595. attackPlayer: function(defender) {
  596. attacker.leering = true;
  597. defender.changeStamina(-100);
  598. return [attacker.description("The") + " leers at you."];
  599. },
  600. requirements: [
  601. function(attacker, defender) { return attacker.leering != true && attacker.flags.grappled != true; }
  602. ],
  603. priority: 1,
  604. };
  605. }
  606. function poke(attacker) {
  607. return {
  608. name: "Poke",
  609. desc: "Poke a nerd",
  610. attackPlayer: function(defender) {
  611. return [attacker.description("The") + " pokes you on the snout for " + attack(attacker, defender, 1e12) + " damage"];
  612. },
  613. priority: 1,
  614. };
  615. }
  616. function digestPlayerStomach(predator,damage=20) {
  617. return {
  618. digest: function(player) {
  619. player.changeStamina(-25);
  620. attack(predator, player, damage);
  621. return [predator.description("The") + "'s stomach grinds over your body, swiftly digesting you."];
  622. },
  623. priority: 1,
  624. gameover: function() { return "Digested by " + predator.description("a"); }
  625. };
  626. }
  627. function instakillPlayerStomach(predator) {
  628. return {
  629. digest: function(player) {
  630. player.health = -100;
  631. let lines = ["The stomach walls churn, clench, and swiftly crush you into nothingness."];
  632. if (player.prefs.scat == true) {
  633. fenAddScatEnding(lines);
  634. }
  635. return lines;
  636. },
  637. priority: 1,
  638. weight: function(attacker, defender) { return 1; },
  639. requirements: [
  640. function(attacker, defender) {
  641. return attacker.flags.voreType == "oral";
  642. }
  643. ],
  644. gameover: function() { return "Crushed by Fen's stomach"; }
  645. };
  646. }
  647. function instakillPlayerStomachSoul(predator) {
  648. return {
  649. digest: function(player) {
  650. player.health = -100;
  651. let lines = ["Your soul catches alight in the horrific depths of the crux's stomach, breaking up and melting in seconds. You're gone..."];
  652. if (player.prefs.scat == true && (predator.flags.voreType != "soul")) {
  653. fenAddScatEnding(lines);
  654. }
  655. return lines;
  656. },
  657. priority: 1,
  658. weight: function(attacker, defender) { return 1; },
  659. requirements: [
  660. function(attacker, defender) {
  661. return attacker.flags.voreType == "oral-soul" || attacker.flags.voreType == "hard-soul" ||
  662. attacker.flags.voreType == "soul";
  663. }
  664. ],
  665. gameover: function() {
  666. if (predator.flags.voreType == "soul") {
  667. return "Soul obliterated by Fen's abyssal gut";
  668. } else if (predator.flags.voreType == "oral-soul") {
  669. return "Body and soul digested by Fen's crushing stomach";
  670. } else if (predator.flags.voreType == "hard-soul") {
  671. return "Ripped to shreds, devoured alive, and soul obliterated by Fen";
  672. }
  673. }
  674. };
  675. }
  676. function instakillPlayerBowels(predator) {
  677. return {
  678. digest: function(player) {
  679. player.health = -100;
  680. let lines = ["Fen's intestines clench, and clench and <i>clench</i>. Your flesh and fat liquefy; your bones groan, break, and dissolve. He takes everything from you, absorbing your obliterated body with a slow, unstoppable squeeze - and in seconds, you're gone, just another victim of the beast's ravenous body"];
  681. if (player.prefs.scat == true) {
  682. fenAddScatEnding(lines);
  683. }
  684. return lines;
  685. },
  686. priority: 1,
  687. weight: function(attacker, defender) { return 1; },
  688. requirements: [
  689. function(attacker, defender) {
  690. return attacker.flags.voreType == "anal";
  691. }
  692. ],
  693. gameover: function() { return "Absorbed into Fen's bowels"; }
  694. };
  695. }
  696. function fenAddScatEnding(lines) {
  697. lines.push(newline);
  698. lines.push("The beast growls and squats down, muscular thighs bulging as he holds up the weight of two creatures...before his pucker opens wide and releases a thick, greasy log of scat. He snarls as the smooth, bone-flecked shit piles up in the street, tongue lolling out as your acid-pitted skull peeks out...and shatters as he clenches, raining broken hunks of bone down onto your unrecognizable remains.");
  699. }
  700. function fenPlayerBowelsSoul(predator) {
  701. return {
  702. digest: function(player) {
  703. predator.flags.voreType = "oral-soul";
  704. return ["Fen's crushing bowels obliterate your body in seconds, breaking you like a bug underfoot and ripping out your soul. Your dazed, helpless essence is drawn up into his stomach..."];
  705. },
  706. priority: 1,
  707. weight: function(attacker, defender) { return defender.prefs.vore.soul; },
  708. requirements: [
  709. function(attacker, defender) {
  710. return attacker.flags.voreType == "anal";
  711. },
  712. function(attacker, defender) {
  713. return defender.prefs.vore.soul > 0;
  714. }
  715. ],
  716. gameover: function() { return "Absorbed into Fen's bowels"; }
  717. };
  718. }