munch
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 

481 wiersze
16 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. ],
  155. priority: 1,
  156. weight: function(attacker, defender) { return 1 - defender.health / defender.maxHealth; }
  157. };
  158. }
  159. function grappledDevour(attacker) {
  160. return {
  161. name: "Devour",
  162. desc: "Try to consume your grappling opponent",
  163. attackPlayer: function(defender) {
  164. let success = statHealthCheck(attacker, defender, "str");
  165. if(success) {
  166. defender.flags.grappled = false;
  167. changeMode("eaten");
  168. return [attacker.description("The") + " breaks your pin and crams your upper body into their maw, swallowing you down in seconds."];
  169. } else {
  170. attacker.changeStamina(-10);
  171. return [attacker.description("The") + " thrashes at you in an attempt to devour you, but you avoid their jaws."];
  172. }
  173. }, requirements: [
  174. function(attacker, defender) { return isGrappled(attacker) && isNormal(defender) && attacker.flags.shrunk != true; }
  175. ], conditions: [
  176. function(attacker, defender) { return defender.prefs.prey; }
  177. ],
  178. priority: 1,
  179. };
  180. }
  181. function grappleAnalVore(attacker) {
  182. return {
  183. name: "Anal Vore",
  184. desc: "Try to shove your opponent up your ass.",
  185. attack: function(defender) {
  186. let success = statHealthCheck(attacker, defender, "str");
  187. if (success) {
  188. attacker.changeStamina(-10);
  189. defender.changeStamina(-25);
  190. attacker.butt.feed(defender);
  191. defender.flags.grappled = false;
  192. attacker.cash += defender.cash;
  193. changeMode("explore");
  194. 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!"];
  195. } else {
  196. attacker.changeStamina(-25);
  197. defender.changeStamina(-10);
  198. return ["Your grasp and shove " + defender.description("the") + ", but they manage to avoid becoming " + attacker.species + " chow."];
  199. }
  200. }, requirements: [
  201. function(attacker, defender) { return isNormal(attacker) && isGrappled(defender) && defender.flags.shrunk != true ; }
  202. ], conditions: [
  203. function(attacker, defender) { return defender.prefs.prey && defender.prefs.analVore; }
  204. ],
  205. priority: 1,
  206. };
  207. }
  208. function grappleRelease(attacker) {
  209. return {
  210. name: "Release",
  211. desc: "Release your opponent",
  212. attack: function(defender) {
  213. defender.flags.grappled = false;
  214. defender.changeStamina(-15);
  215. return ["You throw " + defender.description("the") + " back, dealing " + attack(attacker, defender, attacker.str*1.5) + " damage"];
  216. }, requirements: [
  217. function(attacker, defender) { return isNormal(attacker) && isGrappled(defender); }
  218. ],
  219. priority: 1,
  220. };
  221. }
  222. function grappledStruggle(attacker) {
  223. return {
  224. name: "Struggle",
  225. desc: "Try to break your opponent's pin",
  226. attack: function(defender) {
  227. let success = statHealthCheck(attacker, defender, "str");
  228. if (success) {
  229. attacker.changeStamina(-5);
  230. defender.changeStamina(-10);
  231. attacker.flags.grappled = false;
  232. return ["You struggle and shove " + defender.description("the") + " off of you."];
  233. } else {
  234. attacker.changeStamina(-10);
  235. defender.changeStamina(-5);
  236. return ["You struggle, but to no avail."];
  237. }
  238. },
  239. attackPlayer: function(defender) {
  240. let success = statHealthCheck(attacker, defender, "str");
  241. if (success) {
  242. attacker.changeStamina(-5);
  243. defender.changeStamina(-10);
  244. attacker.flags.grappled = false;
  245. return ["Your prey shoves you back, breaking your grapple!"];
  246. } else {
  247. attacker.changeStamina(-10);
  248. defender.changeStamina(-5);
  249. return ["Your prey squirms, but remains pinned."];
  250. }
  251. },
  252. requirements: [
  253. function(attacker, defender) { return isGrappled(attacker) && isNormalSize(attacker) && isNormal(defender); }
  254. ],
  255. priority: 1,
  256. };
  257. }
  258. function grappledReverse(attacker) {
  259. return {
  260. name: "Reversal",
  261. desc: "Try to pin your grappler. Less likely to work than struggling.",
  262. attack: function(defender) {
  263. let success = statHealthCheck(attacker, defender, "str");
  264. if (success) {
  265. attacker.changeStamina(-5);
  266. defender.changeStamina(-15);
  267. attacker.flags.grappled = false;
  268. defender.flags.grappled = true;
  269. return ["You surprise " + defender.description("the") + " with a burst of strength, flipping them over and pinning them."];
  270. } else {
  271. attacker.changeStamina(-15);
  272. return ["You try to throw your opponent off of you, but fail."];
  273. }
  274. },
  275. attackPlayer: function(defender) {
  276. let success = statHealthCheck(attacker, defender, "str");
  277. if (success) {
  278. attacker.changeStamina(-5);
  279. defender.changeStamina(-15);
  280. attacker.flags.grappled = false;
  281. defender.flags.grappled = true;
  282. return ["Your prey suddenly grabs hold and flips you over, pinning you!"];
  283. } else {
  284. attacker.changeStamina(-15);
  285. return ["Your prey tries to grab at you, but you keep them under control."];
  286. }
  287. },
  288. requirements: [
  289. function(attacker, defender) { return isGrappled(attacker) && isNormalSize(attacker) && isNormal(defender); },
  290. function(attacker, defender) { return defender.flags.grapple; }
  291. ],
  292. priority: 1,
  293. };
  294. }
  295. function shrunkGrapple(attacker) {
  296. return {
  297. name: "Grab",
  298. desc: "Grab this fun-sized snack",
  299. attack: function(defender) {
  300. let success = statCheck(attacker, defender, "dex") || statCheck(attacker, defender, "dex");
  301. if (success) {
  302. defender.changeStamina(-25);
  303. defender.flags.grappled = true;
  304. return ["You snatch up " + defender.description("the")];
  305. } else {
  306. return ["You try to grab " + defender.description("the") + ", but they elude your grasp."];
  307. }
  308. },
  309. requirements: [
  310. function(attacker, defender) {
  311. return isNormal(attacker) && defender.flags.grappled != true && defender.flags.shrunk == true;
  312. }
  313. ],
  314. priority: 2
  315. };
  316. }
  317. function shrunkSwallow(attacker) {
  318. return {
  319. name: "Swallow",
  320. desc: "Swallow your prey",
  321. attack: function(defender) {
  322. defender.changeStamina(-50);
  323. changeMode("explore");
  324. attacker.stomach.feed(defender);
  325. return ["With a light swallow, " + defender.description("the") + " is dragged down to your sloppy guts."];
  326. },
  327. requirements: [
  328. function(attacker, defender) {
  329. return isNormal(attacker) && defender.flags.grappled == true && defender.flags.shrunk == true;
  330. }
  331. ],
  332. priority: 2
  333. };
  334. }
  335. function shrunkStomp(attacker) {
  336. return {
  337. name: "Stomp",
  338. desc: "Stomp on your shrunken prey",
  339. attack: function(defender) {
  340. let success = statCheck(attacker, defender, "dex") || statCheck(attacker, defender, "dex") || defender.stamina == 0;
  341. defender.stamina = 0;
  342. defender.health = Math.max(0, defender.health - 50);
  343. return ["Your paw comes crashing down on " + defender.description("the") + ", burying them under your heavy toes and pinning them down hard."];
  344. },
  345. requirements: [
  346. function(attacker, defender) {
  347. return isNormal(attacker) && defender.flags.grappled != true && defender.flags.shrunk == true;
  348. }
  349. ]
  350. };
  351. }
  352. function flee(attacker) {
  353. return {
  354. name: "Flee",
  355. desc: "Try to run away",
  356. attack: function(defender) {
  357. let success = statCheck(attacker, defender, "dex");
  358. if (success) {
  359. attacker.changeStamina(-25);
  360. attacker.clear();
  361. changeMode("explore");
  362. return ["You successfully run away."];
  363. } else {
  364. attacker.changeStamina(-25);
  365. defender.changeStamina(-25);
  366. return ["You can't escape!"];
  367. }
  368. },
  369. requirements: [
  370. function(attacker, defender) { return isNormal(attacker) && !attacker.isGrappling; }
  371. ]
  372. };
  373. }
  374. function pass(attacker) {
  375. return {
  376. name: "Pass",
  377. desc: "You can't do anything!",
  378. attack: function(defender) {
  379. return ["You do nothing."];
  380. },
  381. attackPlayer: function(defender) {
  382. return [attacker.description("The") + " does nothing."];
  383. },
  384. priority: 0,
  385. };
  386. }
  387. function devourPlayer(attacker) {
  388. return {
  389. name: "Devours YOU!",
  390. desc: "You won't see this",
  391. conditions: [
  392. function(attacker, defender) { return defender.prefs.prey; }
  393. ],
  394. requirements: [
  395. function(attacker, defender) { return attacker.leering == true; }
  396. ],
  397. attackPlayer: function(defender) {
  398. changeMode("eaten");
  399. 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."];
  400. },
  401. priority: 1,
  402. };
  403. }
  404. function leer(attacker) {
  405. return {
  406. name: "Leer",
  407. desc: "Leer at something",
  408. attackPlayer: function(defender) {
  409. attacker.leering = true;
  410. defender.changeStamina(-100);
  411. return [attacker.description("The") + " leers at you."];
  412. },
  413. requirements: [
  414. function(attacker, defender) { return attacker.leering != true && attacker.flags.grappled != true; }
  415. ],
  416. priority: 1,
  417. };
  418. }
  419. function poke(attacker) {
  420. return {
  421. name: "Poke",
  422. desc: "Poke a nerd",
  423. attackPlayer: function(defender) {
  424. return [attacker.description("The") + " pokes you on the snout for " + attack(attacker, defender, 1e12) + " damage"];
  425. },
  426. priority: 1,
  427. };
  428. }
  429. function digestPlayerStomach(predator,damage=20) {
  430. return {
  431. digest: function(player) {
  432. player.changeStamina(-25);
  433. attack(predator, player, damage);
  434. return [predator.description("The") + "'s stomach grinds over your body, swiftly digesting you."];
  435. },
  436. priority: 1,
  437. gameover: function() { return "Digested by " + predator.description("a"); }
  438. };
  439. }
  440. function instakillPlayerStomach(predator) {
  441. return {
  442. digest: function(player) {
  443. player.health = -100;
  444. return ["The stomach walls churn, clench, and swiftly crush you into nothingnes."];
  445. },
  446. priority: 1,
  447. weight: function(attacker, defender) { return 1/3; },
  448. gameover: function() { return "Digested by " + predator.description("a"); }
  449. };
  450. }