munch
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

323 lines
10 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.grappled != true;
  9. }
  10. function isGrappled(entity) {
  11. return entity.grappled == true;
  12. }
  13. function doComp(attackStat, defendStat) {
  14. return Math.random() * attackStat > Math.random() * defendStat;
  15. }
  16. function statCheck(attacker, defender, stat) {
  17. return doComp(attacker[stat], defender[stat]);
  18. }
  19. function statHealthCheck(attacker, defender, stat) {
  20. let attackerPercent = attacker.health / attacker.maxHealth;
  21. let defenderPercent = defender.health / defender.maxHealth;
  22. return doComp(attacker[stat] * attackerPercent, defender[stat] * defenderPercent);
  23. }
  24. function punchAttack(attacker) {
  25. return {
  26. name: "Punch",
  27. desc: "Punch a nerd",
  28. attack: function(defender) {
  29. return "You punch " + defender.description("the") + " for " + attack(attacker, defender, attacker.str) + " damage";
  30. },
  31. attackPlayer: function(defender) {
  32. return attacker.description("The") + " punches you for " + attack(attacker, defender, attacker.str) + " damage";
  33. }, requirements: [
  34. function(attacker, defender) { return isNormal(attacker) && isNormal(defender); }
  35. ],
  36. priority: 1,
  37. weight: function(attacker, defender) { return defender.health / defender.maxHealth; }
  38. };
  39. }
  40. function flankAttack(attacker) {
  41. return {
  42. name: "Flank",
  43. desc: "Be sneaky",
  44. attack: function(defender) {
  45. return "You run around " + defender.description("the") + " and attack for " + attack(attacker, defender, attacker.dex) + " damage";
  46. },
  47. attackPlayer: function(defender) {
  48. return attacker.description("The") + " runs past you, then turns and hits you for " + attack(attacker, defender, attacker.str) + " damage";
  49. }, requirements: [
  50. function(attacker, defender) { return isNormal(attacker) && isNormal(defender); }
  51. ],
  52. priority: 1,
  53. weight: function(attacker, defender) { return defender.health / defender.maxHealth; }
  54. };
  55. }
  56. function grapple(attacker) {
  57. return {
  58. name: "Grapple",
  59. desc: "Try to grab your opponent",
  60. attack: function(defender) {
  61. let success = statHealthCheck(attacker, defender, "str");
  62. if (success) {
  63. defender.grappled = true;
  64. return "You charge at " + defender.description("the") + ", tackling them and knocking them to the ground.";
  65. } else {
  66. return "You charge at " + defender.description("the") + ", but they dodge out of the way!";
  67. }
  68. },
  69. attackPlayer: function(defender) {
  70. let success = Math.random() < 0.5;
  71. if (success) {
  72. defender.grappled = true;
  73. return attacker.description("The") + " lunges at you, pinning you to the floor!";
  74. } else {
  75. return attacker.description("The") + " tries to tackle you, but you deftly avoid them.";
  76. }
  77. },
  78. requirements: [
  79. function(attacker, defender) { return isNormal(attacker) && isNormal(defender); }
  80. ],
  81. priority: 1,
  82. weight: function(attacker, defender) { return 1 - defender.health / defender.maxHealth; }
  83. };
  84. }
  85. function grappleDevour(attacker) {
  86. return {
  87. name: "Devour",
  88. desc: "Try to consume your grappled opponent",
  89. attack: function(defender) {
  90. let success = statHealthCheck(attacker, defender, "str");
  91. if (success) {
  92. attacker.stomach.feed(defender);
  93. defender.grappled = false;
  94. changeMode("explore");
  95. return "You open your jaws wide, stuffing " + defender.description("the") + "'s head into your gullet and greedily wolfing them down. Delicious.";
  96. } else {
  97. return "Your jaws open wide, but " + defender.description("the") + " manages to avoid becoming " + attacker.species + " chow.";
  98. }
  99. },
  100. attackPlayer: function(defender) {
  101. let success = statHealthCheck(attacker, defender, "str");
  102. if(success) {
  103. defender.grappled = false;
  104. changeMode("eaten");
  105. return attacker.description("The") + " forces your head into their sloppy jaws, devouring you despite your frantic struggles. Glp.";
  106. } else {
  107. return attacker.description("The") + " tries to swallow you down, but you manage to resist their hunger.";
  108. }
  109. }, requirements: [
  110. function(attacker, defender) { return isNormal(attacker) && isGrappled(defender); }
  111. ], conditions: [
  112. function(prefs, player=false) { return player || prefs.player.prey; }
  113. ],
  114. priority: 1,
  115. };
  116. }
  117. function grappleAnalVore(attacker) {
  118. return {
  119. name: "Anal Vore",
  120. desc: "Try to shove your opponent up your ass.",
  121. attack: function(defender) {
  122. let success = statHealthCheck(attacker, defender, "str");
  123. if (success) {
  124. attacker.butt.feed(defender);
  125. defender.grappled = false;
  126. changeMode("explore");
  127. 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...";
  128. } else {
  129. return "Your grasp and shove " + defender.description("the") + ", but they manage to avoid becoming " + attacker.species + " chow.";
  130. }
  131. }, requirements: [
  132. function(attacker, defender) { return isNormal(attacker) && isGrappled(defender); }
  133. ], conditions: [
  134. function(prefs, player=false) { return player || prefs.player.prey; }
  135. ],
  136. priority: 1,
  137. };
  138. }
  139. function grappleRelease(attacker) {
  140. return {
  141. name: "Release",
  142. desc: "Release your opponent",
  143. attack: function(defender) {
  144. defender.grappled = false;
  145. return "You throw " + defender.description("the") + " back, dealing " + attack(attacker, defender, attacker.str*1.5) + " damage";
  146. }, requirements: [
  147. function(attacker, defender) { return isNormal(attacker) && isGrappled(defender); }
  148. ],
  149. priority: 1,
  150. };
  151. }
  152. function grappledStruggle(attacker) {
  153. return {
  154. name: "Struggle",
  155. desc: "Try to break your opponent's pin",
  156. attack: function(defender) {
  157. let success = statHealthCheck(attacker, defender, "str");
  158. if (success) {
  159. attacker.grappled = false;
  160. return "You struggle and shove " + defender.description("the") + " off of you.";
  161. } else {
  162. return "You struggle, but to no avail.";
  163. }
  164. },
  165. attackPlayer: function(defender) {
  166. let success = statHealthCheck(attacker, defender, "str");
  167. if (success) {
  168. attacker.grappled = false;
  169. return "Your prey shoves you back, breaking your grapple!";
  170. } else {
  171. return "Your prey squirms, but remains pinned.";
  172. }
  173. },
  174. requirements: [
  175. function(attacker, defender) { return isGrappled(attacker) && isNormal(defender); }
  176. ],
  177. priority: 1,
  178. };
  179. }
  180. function grappledReverse(attacker) {
  181. return {
  182. name: "Reversal",
  183. desc: "Try to pin your grappler. Less likely to work than struggling.",
  184. attack: function(defender) {
  185. let success = statHealthCheck(attacker, defender, "str");
  186. if (success) {
  187. attacker.grappled = false;
  188. defender.grappled = true;
  189. return "You surprise " + defender.description("the") + " with a burst of strength, flipping them over and pinning them.";
  190. } else {
  191. return "You try to throw your opponent off of you, but fail.";
  192. }
  193. },
  194. attackPlayer: function(defender) {
  195. let success = statHealthCheck(attacker, defender, "str");
  196. if (success) {
  197. attacker.grappled = false;
  198. defender.grappled = true;
  199. return "Your prey suddenly grabs hold and flips you over, pinning you!";
  200. } else {
  201. return "Your prey tries to grab at you, but you keep them under control.";
  202. }
  203. },
  204. requirements: [
  205. function(attacker, defender) { return isGrappled(attacker) && isNormal(defender); }
  206. ],
  207. priority: 1,
  208. };
  209. }
  210. function flee(attacker) {
  211. return {
  212. name: "Flee",
  213. desc: "Try to run away",
  214. attack: function(defender) {
  215. let success = statCheck(attacker, defender, "dex");
  216. if (success) {
  217. attacker.grappled = false;
  218. changeMode("explore");
  219. return "You successfully run away.";
  220. } else {
  221. return "You can't escape!";
  222. }
  223. },
  224. requirements: [
  225. function(attacker, defender) { return isNormal(attacker) && !attacker.isGrappling; }
  226. ]
  227. };
  228. }
  229. function pass(attacker) {
  230. return {
  231. name: "Pass",
  232. desc: "You can't do anything!",
  233. attack: function(defender) {
  234. return "You do nothing.";
  235. },
  236. attackPlayer: function(defender) {
  237. return attacker.description("The") + " does nothing.";
  238. },
  239. priority: 0,
  240. };
  241. }
  242. function devourPlayer(attacker) {
  243. return {
  244. name: "Devours YOU!",
  245. desc: "You won't see this",
  246. conditions: [
  247. function(prefs) { return prefs.player.prey; }
  248. ],
  249. requirements: [
  250. function(attacker, defender) { return attacker.leering == true; }
  251. ],
  252. attackPlayer: function(defender) {
  253. changeMode("eaten");
  254. return "The voracious " + attacker.description() + " pins you down and devours you in seconds.";
  255. },
  256. priority: 1,
  257. };
  258. }
  259. function leer(attacker) {
  260. return {
  261. name: "Leer",
  262. desc: "Leer at something",
  263. attackPlayer: function(defender) {
  264. attacker.leering = true;
  265. return attacker.description("The") + " leers at you.";
  266. },
  267. requirements: [
  268. function(attacker, defender) { return attacker.leering != true && attacker.grappled != true; }
  269. ],
  270. priority: 1,
  271. };
  272. }
  273. function poke(attacker) {
  274. return {
  275. name: "Poke",
  276. desc: "Poke a nerd",
  277. attackPlayer: function(defender) {
  278. return attacker.description("The") + " pokes you on the snout for " + attack(attacker, defender, 1e12) + " damage";
  279. },
  280. priority: 1,
  281. };
  282. }
  283. function digestPlayerStomach(predator,damage=20) {
  284. return {
  285. digest: function(player) {
  286. attack(predator, player, damage);
  287. return predator.description("The") + "'s stomach grinds over your body, swiftly digesting you.";
  288. },
  289. priority: 1,
  290. };
  291. }
  292. function instakillPlayerStomach(pedator) {
  293. return {
  294. digest: function(player) {
  295. player.health = -100;
  296. return "The stomach walls churn, clench, and swiftly crush you into nothingnes.";
  297. },
  298. priority: 1,
  299. weight: function(attacker, defender) { return 1/3; },
  300. };
  301. }