munch
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

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