a munch adventure
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 

1318 lines
50 KiB

  1. (() => {
  2. function checkSuspicion(add = 0) {
  3. const old = getStat("suspicion");
  4. if (add >= 0) {
  5. add *= state.info.awareness.value;
  6. }
  7. changeStat("suspicion", add);
  8. if (getStat("suspicion") >= 100) {
  9. print(["Geta spots you!", "You're snatched up and tossed into the fox's bowl of cereal."]);
  10. goToRoom("in-bowl");
  11. return false;
  12. } else if (getStat("suspicion") >= 75 && old < 75) {
  13. print(["The fox is very suspicious. You're going to get caught if you keep this up..."]);
  14. }
  15. return true;
  16. }
  17. function randomBodyPart() {
  18. const choices = Object.entries(state.player.limbs).filter(([name, status]) => {
  19. return status;
  20. }).map(([name, status]) => name);
  21. return choices[Math.floor(Math.random() * choices.length)];
  22. }
  23. function limbsLost() {
  24. return Object.entries(state.player.limbs).filter(([name, status]) => {
  25. return !status;
  26. }).length;
  27. }
  28. function pickRandom(list) {
  29. return list[Math.floor(Math.random() * list.length)];
  30. }
  31. const word = {
  32. get swallow() { return pickRandom(["swallow", "gulp"]); },
  33. get slimy() { return pickRandom(["slimy", "sloppy", "slick", "glistening"])},
  34. get disgusting() { return pickRandom(["disgusting", "abhorrent", "rank", "horrific", "nauseating", "sickening", "wretched"])},
  35. get foul() { return pickRandom(["foul", "rank", "gross"])},
  36. get fatal() { return pickRandom(["fatal", "deadly"])},
  37. get painful() { return pickRandom(["painful", "agonizing", "unbearable"])}
  38. }
  39. function statLerp(stat, change, duration) {
  40. // pretty sure this'll be a random id...
  41. const id = new Date().getTime() + Math.random();
  42. const iterations = duration / 1000 * 60;
  43. startTimer({
  44. id: id,
  45. func: () => {
  46. changeStat(stat, change / iterations);
  47. return true;
  48. },
  49. delay: 1000 / 60,
  50. loop: true,
  51. classes: [
  52. ]
  53. });
  54. startTimer({
  55. id: id + "-stopper",
  56. func: () => {
  57. stopTimer(id);
  58. return false;
  59. },
  60. delay: duration,
  61. loop: false,
  62. classes: [
  63. ]
  64. });
  65. }
  66. const limbs = {
  67. head: "head",
  68. leftArm: "left arm",
  69. rightArm: "right arm",
  70. leftLeg: "left leg",
  71. rightLeg: "right leg"
  72. };
  73. stories.push({
  74. "id": "geta-unaware",
  75. "info": {
  76. "name": "Geta's Breakfast",
  77. "desc": "Try to sneak past a fox after a catastrophic shrinking incident.",
  78. "tags": [
  79. "prey",
  80. "fatal",
  81. "oral-vore",
  82. "hard-vore",
  83. "hard-digestion",
  84. "macro-micro"
  85. ]
  86. },
  87. "intro": {
  88. "start": "pepper-grinder",
  89. "setup": () => {
  90. state.info.awareness = {
  91. id: "awareness",
  92. name: "Geta's Awareness",
  93. type: "counter",
  94. value: 1,
  95. get render() {
  96. if (this.value < 1) {
  97. return "Distracted";
  98. } else if (this.value == 1) {
  99. return "Normal"
  100. } else {
  101. return "Alert"
  102. }
  103. }
  104. }
  105. state.geta = {};
  106. state.player.stats.health = { name: "Health", type: "meter", value: 100, min: 0, max: 100, color: "rgb(255,55,55)" };
  107. state.player.stats.stamina = { name: "Stamina", type: "meter", value: 100, min: 0, max: 100, color: "rgb(55,255,55)", hidden: true };
  108. state.player.stats.suspicion = { name: "Suspicion", type: "meter", value: 0, min: 0, max: 100, color: "rgb(100,100,100)" };
  109. state.player.stats.mawPos = { "name": "Struggle", "type": "meter", "value": 0.5, "min": 0, "max": 1, "color": "rgb(0,255,0)", hidden: true }
  110. state.player.stats.throatPos = { "name": "Descent", "type": "meter", "value": 0.25, "min": 0, "max": 1, "color": "rgb(155,0,0)", hidden: true }
  111. state.info.time.value = 60 * 60 * 7 + 60 * 17;
  112. state.player.limbs = {};
  113. state.player.limbs.head = true;
  114. state.player.limbs.leftArm = true;
  115. state.player.limbs.rightArm = true;
  116. state.player.limbs.leftLeg = true;
  117. state.player.limbs.rightLeg = true;
  118. startTimer({
  119. id: "clock",
  120. func: () => {
  121. state.info.time.value += 1;
  122. state.info.time.value %= 86000;
  123. return true;
  124. },
  125. delay: 1000,
  126. loop: true,
  127. classes: [
  128. ]
  129. });
  130. startTimer({
  131. id: "suspicion-decay",
  132. func: () => {
  133. checkSuspicion(-0.1);
  134. return true;
  135. },
  136. delay: 100,
  137. loop: true,
  138. classes: [
  139. "free"
  140. ]
  141. });
  142. startTimer({
  143. id: "timeout",
  144. func: () => {
  145. if (state.info.time.value == 60 * 60 * 7 + 60 * 19) {
  146. print(["The fox is almost done with his breakfast..."]);
  147. }
  148. if (state.info.time.value >= 60 * 60 * 7 + 60 * 20) {
  149. print(["Time's up! In you go."]);
  150. goToRoom("maw");
  151. return false;
  152. }
  153. return true;
  154. },
  155. delay: 1000,
  156. loop: true,
  157. classes: [
  158. "free"
  159. ]
  160. });
  161. startTimer({
  162. id: "geta-action",
  163. func: () => {
  164. const random = Math.random();
  165. if (random < 0.7) {
  166. print(["Geta slurps up a spoonful of cereal."]);
  167. return Math.random() * 3000 + 3000
  168. } else if (random < 0.9) {
  169. state.info.awareness.value = 0.1;
  170. print(["The fox yawns and stretches."]);
  171. startTimer({
  172. id: "yawn-end",
  173. func: () => {
  174. print(["Geta finishes his stretch"]);
  175. state.info.awareness.value = 1;
  176. return true;
  177. },
  178. delay: 5000,
  179. loop: false,
  180. classes: [
  181. "free"
  182. ]
  183. });
  184. return Math.random() * 3000 + 5000
  185. } else {
  186. state.info.awareness.value = 2;
  187. print(["Geta narrows his eyes and looks around the table. Something seems off to him..."]);
  188. startTimer({
  189. id: "squint-end",
  190. func: () => {
  191. print(["He goes back to his breakfast."]);
  192. state.info.awareness.value = 1;
  193. return true;
  194. },
  195. delay: 5000,
  196. loop: false,
  197. classes: [
  198. "free"
  199. ]
  200. });
  201. return Math.random() * 1000 + 6000
  202. }
  203. },
  204. delay: 5000,
  205. loop: true,
  206. classes: [
  207. "free"
  208. ]
  209. });
  210. },
  211. "intro": () => {
  212. print(["Game started", newline, "Exposition goes here later."]);
  213. }
  214. },
  215. "sounds": [
  216. "loop/stomach.ogg",
  217. "sfx/absorb.ogg",
  218. "sfx/digest.ogg",
  219. "sfx/swallow.ogg"
  220. ],
  221. "preload": [
  222. ],
  223. "refresh": () => {
  224. setBackgroundColor(50 - state.player.stats.health.value / 2, 0, 0);
  225. },
  226. "world": {
  227. "pepper-grinder": {
  228. "id": "pepper-grinder",
  229. "name": "Pepper Grinder",
  230. "desc": "You're hiding behind a pepper grinder",
  231. "move": (room) => {
  232. print(["You dart over to the pepper grinder, which looms over you like a greatwood."]);
  233. },
  234. "enter": (room) => {
  235. },
  236. "exit": (room) => {
  237. },
  238. "actions": [
  239. {
  240. name: "Tap",
  241. desc: "Bang on the pepper shaker",
  242. execute: (room) => {
  243. print(["You thump the pepper shaker, making a dull thud."]);
  244. const safe = checkSuspicion(25);
  245. if (safe && getStat("suspicion") > 50) {
  246. print(["Geta leans in to have a closer look. He's going to catch you if you don't move!"]);
  247. startTimer({
  248. id: "pepper-investigate",
  249. func: () => {
  250. if (state.player.location == "pepper-grinder") {
  251. print(["He catches you.", newline, "You're tossed into the fox's jaws."]);
  252. goToRoom("maw");
  253. } else {
  254. print(["You evaded the fox."]);
  255. }
  256. },
  257. delay: 3000,
  258. loop: false,
  259. classes: [
  260. "free"
  261. ]
  262. });
  263. }
  264. },
  265. show: [
  266. ],
  267. conditions: [
  268. ]
  269. },
  270. {
  271. name: "Wait",
  272. desc: "Wait for the fox to finish his breakfast. Surely you'll be able to escape after that...right?",
  273. execute: (room) => {
  274. state.info.time.value = 60 * 60 * 7 + 60 * 20;
  275. },
  276. show: [
  277. ],
  278. conditions: [
  279. ]
  280. },
  281. ],
  282. "exits": {
  283. "up": {
  284. "target": "bowl",
  285. "desc": "Walk up to the cereal bowl",
  286. "show": [
  287. ],
  288. "conditions": [
  289. ],
  290. "hooks": [
  291. (room, exit) => {
  292. return checkSuspicion(10);
  293. }
  294. ]
  295. },
  296. "left": {
  297. "target": "table",
  298. "desc": "Run out into the open",
  299. "show": [
  300. ],
  301. "conditions": [
  302. ],
  303. "hooks": [
  304. ]
  305. },
  306. },
  307. "hooks": [
  308. ],
  309. "data": {
  310. "stats": {
  311. }
  312. }
  313. },
  314. "bowl": {
  315. "id": "bowl",
  316. "name": "Behind the Bowl",
  317. "desc": "You're crouched behind Geta's bowl of cereal",
  318. "move": (room) => {
  319. print(["You scurry up to the looming bowl, staying low and out of Geta's sight."]);
  320. },
  321. "enter": (room) => {
  322. },
  323. "exit": (room) => {
  324. },
  325. "actions": [
  326. ],
  327. "exits": {
  328. "ascend": {
  329. "target": "in-bowl",
  330. "desc": "Climb into Geta's cereal",
  331. "show": [
  332. ],
  333. "conditions": [
  334. ],
  335. "hooks": [
  336. ]
  337. },
  338. "down": {
  339. "target": "pepper-grinder",
  340. "desc": "Run back behind the pepper grinder",
  341. "show": [
  342. ],
  343. "conditions": [
  344. ],
  345. "hooks": [
  346. (room, exit) => {
  347. return checkSuspicion(15);
  348. }
  349. ]
  350. },
  351. },
  352. "hooks": [
  353. ],
  354. "data": {
  355. "stats": {
  356. }
  357. }
  358. },
  359. "table": {
  360. "id": "table",
  361. "name": "Table",
  362. "desc": "You're out in the open!",
  363. "move": (room) => {
  364. },
  365. "enter": (room) => {
  366. startTimer({
  367. id: "table-suspicion",
  368. func: () => {
  369. checkSuspicion(1.5);
  370. return true;
  371. },
  372. delay: 100,
  373. loop: true,
  374. classes: [
  375. "free"
  376. ]
  377. });
  378. },
  379. "exit": (room) => {
  380. stopTimer("table-suspicion");
  381. },
  382. "actions": [
  383. ],
  384. "exits": {
  385. "right": {
  386. "target": "pepper-grinder",
  387. "desc": "Run back to cover",
  388. "show": [
  389. ],
  390. "conditions": [
  391. ],
  392. "hooks": [
  393. ]
  394. },
  395. },
  396. "hooks": [
  397. ],
  398. "data": {
  399. "stats": {
  400. }
  401. }
  402. },
  403. "in-bowl": {
  404. "id": "in-bowl",
  405. "name": "Bowl",
  406. "desc": "You're in the cereal bowl...",
  407. "move": (room) => {
  408. print(["Why did you do that?"]);
  409. },
  410. "enter": (room) => {
  411. state.player.stats.suspicion.hidden = true;
  412. stopClassTimers("free");
  413. startTimer({
  414. id: "geta-eat",
  415. func: () => {
  416. if (Math.random() < 0.6) {
  417. print(["Geta scoops up a spoonful of cereal; you narrowly avoid being caught."]);
  418. return true;
  419. } else {
  420. print(["Geta scoops you up and slurps you into his maw."]);
  421. goToRoom("maw");
  422. return false;
  423. }
  424. },
  425. delay: 3000,
  426. loop: true,
  427. classes: [
  428. "free"
  429. ]
  430. });
  431. },
  432. "exit": (room) => {
  433. },
  434. "actions": [
  435. ],
  436. "exits": {
  437. "ascend": {
  438. "target": "bowl",
  439. "desc": "Try to climb back out!",
  440. "show": [
  441. ],
  442. "conditions": [
  443. ],
  444. "hooks": [
  445. (room, exit) => {
  446. print([
  447. "You grab at the rim of the bowl and try to pull yourself out. Alas, your struggles are for naught; Geta easily scoops you up in his spoon and, a heartbeat later, slurps you into his sloppy jaws. You didn't stand a chance."
  448. ]);
  449. goToRoom("maw");
  450. return false;
  451. }
  452. ]
  453. },
  454. },
  455. "hooks": [
  456. ],
  457. "data": {
  458. "stats": {
  459. }
  460. }
  461. },
  462. "maw": {
  463. "id": "maw",
  464. "name": "Geta's Maw",
  465. "desc": "You've been slurped up into the fox's " + word.foul + " jaws",
  466. "move": (room) => {
  467. },
  468. "enter": (room) => {
  469. state.player.stats.suspicion.hidden = true;
  470. stopClassTimers("free");
  471. state.player.stats.stamina.hidden = false;
  472. state.player.stats.mawPos.hidden = false;
  473. state.geta.slurps = 0;
  474. state.geta.chews = 0;
  475. state.geta.swallowsLeft = 3 + Math.floor(Math.random() * 3);
  476. state.geta.mawMovement = 1;
  477. print(["You slip into Geta's maw; the atmosphere is " + word.disgusting + ". He'll swallow you alive if you slip too far back, but crawl too far forward, and you'll meet his fangs..."])
  478. startTimer({
  479. id: "maw-stamina",
  480. func: () => {
  481. changeStat("stamina", 0.1);
  482. return true;
  483. },
  484. delay: 1000 / 60,
  485. loop: true,
  486. classes: [
  487. "maw-struggle"
  488. ]
  489. });
  490. startTimer({
  491. id: "maw-random-movement",
  492. func: () => {
  493. const time = new Date().getTime();
  494. const movementFactor = (state.geta.mawMovement + limbsLost());
  495. const fastPart = Math.sin(time / 200) / 1600 / 3;
  496. const slowPart = Math.sin(time / 1000) / 1600;
  497. changeStat("mawPos", movementFactor * (fastPart + slowPart));
  498. if (getStat("mawPos") <= 0.02) {
  499. print(["You slip too far back. Geta doesn't even have to try to swallow you like the food you are; you're lost from the world, buried in his hot, tight throat."]);
  500. goToRoom("throat");
  501. return false;
  502. } else if (getStat("mawPos") >= 0.98) {
  503. print(["Geta's jaws close like a falling guillotine's blade. You're crushed like an insect. A sharp gulp drags you down to the fox's guts."]);
  504. playSfx("sfx/swallow.ogg");
  505. changeStat("health", -90);
  506. goToRoom("throat");
  507. state.player.flags.throatSurrender = true;
  508. return false;
  509. }
  510. return true;
  511. },
  512. delay: 1000 / 60,
  513. loop: true,
  514. classes: [
  515. "maw-struggle"
  516. ]
  517. });
  518. startTimer({
  519. id: "maw-struggle",
  520. func: () => {
  521. if (state.geta.swallowsLeft <= 0) {
  522. print(["Geta picks up his bowl of cereal and drinks it down, swallowing you in the process."]);
  523. state.geta.swallowsLeft = -1;
  524. goToRoom("throat");
  525. return false;
  526. }
  527. let choice;
  528. if (Math.random() < 0.2) {
  529. const choices = [
  530. "slosh",
  531. "tilt-back",
  532. "shove",
  533. ];
  534. choice = choices[Math.floor(Math.random() * choices.length)];
  535. } else if (Math.random() > state.geta.slurps / 3) {
  536. choice = "slurp";
  537. } else if (state.geta.chews - Math.floor(Math.random() * 3) < state.geta.slurps) {
  538. choice = "chew";
  539. } else {
  540. choice = "swallow";
  541. }
  542. if (choice == "swallow") {
  543. if (getStat("mawPos") < 0.15) {
  544. print(["You're too far back. The fox swallows a mouthful of cereal, taking you with it."]);
  545. goToRoom("throat");
  546. return false;
  547. } else {
  548. printRandom([
  549. ["A light swallow drags a lump of chewed-up cereal into Geta's " + word.fatal + " depths."],
  550. ["Geta swallows, dragging you closer to your demise."],
  551. ["Your captor's throat ripples as he gulps down his breakfast."]
  552. ]);
  553. statLerp("mawPos", -0.25, 500);
  554. state.geta.slurps = 0;
  555. state.geta.chews = 0;
  556. state.geta.swallowsLeft -= 1;
  557. return Math.random() * 1500 + 1500;
  558. }
  559. } else if (choice == "slurp") {
  560. statLerp("mawPos", -0.1, 250);
  561. printRandom([
  562. ["A spoonful of cereal slips into the fox's sloppy maw."],
  563. ["Geta slurps up some more of his breakfast."],
  564. ["You're shoved back a bit as Geta slurps up more cereal."]
  565. ]);
  566. state.geta.slurps += 1;
  567. return Math.random() * 1000 + 2500;
  568. } else if (choice == "chew") {
  569. if (getStat("mawPos") > 0.85) {
  570. const limb = randomBodyPart();
  571. state.player.limbs[limb] = false;
  572. const limbName = limbs[limb];
  573. if (limb == "head") {
  574. print(["Geta's jaws crush down on your head. You die."]);
  575. changeStat("health", -100);
  576. goToRoom("stomach");
  577. } else {
  578. print(["You scream in pain as your " + limbName + " is shattered by the fox's jaws"]);
  579. changeStat("health", -40);
  580. return true;
  581. }
  582. } else {
  583. printRandom([
  584. ["Cruel fangs crush down on the food around you."],
  585. ["Geta chews on his breakfast."],
  586. ["The fox's fangs close with a crackle-crunch of cereal."]
  587. ]);
  588. statLerp("mawPos", Math.random() / 10 - 0.05, 250);
  589. state.geta.chews += 1;
  590. return Math.random() * 500 + 1300;
  591. }
  592. } else if (choice == "slosh") {
  593. print(["Geta's tongue sloshes from side to side, throwing you around his maw like a ship in a storm."]);
  594. state.geta.mawMovement = 3;
  595. startTimer({
  596. id: "maw-slosh-end",
  597. func: () => {
  598. state.geta.mawMovement = 1;
  599. print(["The sloshing ends."]);
  600. return true;
  601. },
  602. delay: 4000,
  603. loop: false,
  604. classes: [
  605. "maw-struggle"
  606. ]
  607. });
  608. return Math.random() * 1500 + 4500;
  609. } else if (choice == "tilt-back") {
  610. print(["Geta tilts his head back, sending rivults of slobber flowing down into that yawning gullet."]);
  611. state.geta.mawMovement = 0.2;
  612. statLerp("mawPos", -1, 4000);
  613. startTimer({
  614. id: "maw-tilt-text",
  615. func: () => {
  616. state.geta.mawMovement = 1;
  617. print(["The fox's muzzle tilts back down as he SWALLOWS hard."]);
  618. statLerp("mawPos", -0.3, 500);
  619. state.geta.swallowsLeft -= 1;
  620. state.geta.slurps = 0;
  621. state.geta.chews = 0;
  622. return true;
  623. },
  624. delay: 4000,
  625. loop: false,
  626. classes: [
  627. ]
  628. });
  629. return 5000 + Math.random() * 1000;
  630. } else if (choice == "shove") {
  631. print(["Geta's tongue lurches forward, shoving you towards the front of his maw!"]);
  632. statLerp("mawPos", 0.2, 500);
  633. return 2000 + Math.random() * 1000;
  634. }
  635. },
  636. delay: 0,
  637. loop: true,
  638. classes: [
  639. "maw-struggle"
  640. ]
  641. });
  642. startTimer({
  643. id: "maw-taunts",
  644. func: () => {
  645. printRandom([
  646. ["\"Did you really think I wouldn't notice you?\""],
  647. ["\"You're going to feel good dying in my guts.\""],
  648. ["\"I could just crush you...but where's the fun in that?\""]
  649. ]);
  650. return Math.random() * 5000 + 5000;
  651. },
  652. delay: 5000,
  653. loop: true,
  654. classes: [
  655. "maw-struggle"
  656. ]
  657. });
  658. },
  659. "exit": (room) => {
  660. state.player.stats.stamina.hidden = true;
  661. state.player.stats.mawPos.hidden = true;
  662. stopClassTimers("maw-struggle");
  663. },
  664. "actions": [
  665. {
  666. name: "Struggle",
  667. desc: "Pull yourself away from the fox's throat! Just don't go too far forward...",
  668. execute: (room) => {
  669. if (getStat("stamina") < 25) {
  670. print(["You're too tired..."]);
  671. } else {
  672. print(["You drag yourself forward"]);
  673. changeStat("stamina", -25);
  674. statLerp("mawPos", 0.15 + Math.random() * 0.05, 250);
  675. }
  676. },
  677. show: [
  678. ],
  679. conditions: [
  680. ]
  681. },
  682. {
  683. name: "Slip Back",
  684. desc: "Slide back towards Geta's gullet",
  685. execute: (room) => {
  686. if (Math.random() * 25 > getStat("stamina")) {
  687. print(["You try to shimmy back an inch or two, but your sore muscles give way; you slide back perilously far!"]);
  688. statLerp("mawPos", -0.3 - Math.random() * 0.25, 250);
  689. }
  690. else if (Math.random() < 0.9) {
  691. print(["You let yourself slip back."]);
  692. statLerp("mawPos", -0.2 - Math.random() * 0.1, 250);
  693. } else {
  694. print(["You lose your grip, sliding back quite far!"]);
  695. statLerp("mawPos", -0.3 - Math.random() * 0.15, 250);
  696. }
  697. },
  698. show: [
  699. ],
  700. conditions: [
  701. ]
  702. },
  703. {
  704. name: "Dive In",
  705. desc: "Throw yourself towards the fox's throat",
  706. execute: (room) => {
  707. print(["Resigned to your fate, you toss yourself into Geta's throat. He seems surprised by your eagerness to submit, but swallows you all the same."]);
  708. goToRoom("throat");
  709. },
  710. show: [
  711. ],
  712. conditions: [
  713. ]
  714. },
  715. ],
  716. "exits": {
  717. },
  718. "hooks": [
  719. ],
  720. "data": {
  721. "stats": {
  722. }
  723. }
  724. },
  725. "throat": {
  726. "id": "throat",
  727. "name": "Geta's Gullet",
  728. "desc": "GULP!",
  729. "move": (room) => {
  730. },
  731. "enter": (room) => {
  732. playSfx("sfx/swallow.ogg");
  733. state.player.stats.stamina.hidden = false;
  734. state.player.stats.throatPos.hidden = false;
  735. startTimer({
  736. id: "throat-stamina",
  737. func: () => {
  738. changeStat("stamina", 0.03);
  739. return true;
  740. },
  741. delay: 1000/60,
  742. loop: true,
  743. classes: [
  744. "throat-struggle"
  745. ]
  746. });
  747. startTimer({
  748. id: "throat-descent",
  749. func: () => {
  750. if (getStat("throatPos") <= 0.01) {
  751. print(["Geta swallows HARD, cramming you back down like the food you are."]);
  752. changeStat("throatPos", 0.1);
  753. statLerp("throatPos", 0.5, 1000);
  754. }
  755. if (getStat("throatPos") >= 0.99) {
  756. goToRoom("stomach");
  757. return false;
  758. }
  759. changeStat("throatPos", state.player.flags.throatSurrender ? 0.0005 : 0.0001);
  760. return true;
  761. },
  762. delay: 1000 / 60,
  763. loop: true,
  764. classes: [
  765. "throat-struggle"
  766. ]
  767. });
  768. startTimer({
  769. id: "throat-swallows",
  770. func: () => {
  771. print(["Geta's throat pumps you deeper"]);
  772. statLerp("throatPos", 0.1, 1250);
  773. return Math.random() * 2000 + 2000;
  774. },
  775. delay: 2000,
  776. loop: true,
  777. classes: [
  778. "throat-struggle"
  779. ]
  780. });
  781. },
  782. "exit": (room) => {
  783. state.player.stats.stamina.hidden = true;
  784. state.player.stats.throatPos.hidden = true;
  785. print(["You slush down into Geta's stomach"]);
  786. stopClassTimers("throat-struggle");
  787. },
  788. "actions": [
  789. {
  790. name: "Struggle",
  791. desc: "Try to climb back out!",
  792. execute: (room) => {
  793. if (Math.random() * 50 > getStat("stamina")) {
  794. print(["You try your best, but your sore muscles are no match."]);
  795. } else {
  796. print(["Your valiant struggles drag you a little closer to freedom."]);
  797. statLerp("throatPos", -0.15, 1000);
  798. changeStat("stamina", -20);
  799. }
  800. },
  801. show: [
  802. (room) => {
  803. return !state.player.flags.throatSurrender;
  804. }
  805. ],
  806. conditions: [
  807. ]
  808. },
  809. {
  810. name: "Give up",
  811. desc: "Dive down into Geta's stomach",
  812. execute: (room) => {
  813. print(["You submit to your predator."]);
  814. state.player.flags.throatSurrender = true;
  815. },
  816. show: [
  817. (room) => {
  818. return !state.player.flags.throatSurrender;
  819. }
  820. ],
  821. conditions: [
  822. ]
  823. },
  824. ],
  825. "exits": {
  826. },
  827. "hooks": [
  828. ],
  829. "data": {
  830. "stats": {
  831. }
  832. }
  833. },
  834. "stomach": {
  835. "id": "stomach",
  836. "name": "Geta's Stomach",
  837. "desc": "Glorp",
  838. "move": (room) => {
  839. },
  840. "enter": (room) => {
  841. playLoop("loop/stomach.ogg");
  842. state.geta.digestionStage = 0;
  843. state.geta.acidStrength = 1;
  844. startTimer({
  845. id: "digest-stages",
  846. func: () => {
  847. if (100 - state.geta.digestionStage * 25 - 25 > getStat("health")) {
  848. state.geta.digestionStage = Math.floor((100 - getStat("health")) / 25);
  849. console.log(state.geta.digestionStage);
  850. switch (state.geta.digestionStage) {
  851. case 1:
  852. print(["Your skin begins to tingle."]);
  853. break;
  854. case 2:
  855. print(["The stinging acids work their way into your tender body."]);
  856. break;
  857. case 3:
  858. print(["You're starting to fall apart..."]);
  859. break;
  860. default:
  861. break;
  862. }
  863. }
  864. return true;
  865. },
  866. delay: 1000,
  867. loop: true,
  868. classes: [
  869. "digestion"
  870. ]
  871. });
  872. startTimer({
  873. id: "digest-random",
  874. func: () => {
  875. const choices = [
  876. () => {
  877. const crushed = randomBodyPart();
  878. const name = limbs[crushed];
  879. if (name == "head") {
  880. print(["A powerful fold of muscle grips your head, crushing it like a grape and killing you instantly."]);
  881. changeStat("health", -100);
  882. return false;
  883. } else {
  884. print(["Geta's stomach grips your " + name + " and crushes it with a horrific CRACK"]);
  885. changeStat("health", -40);
  886. return true;
  887. }
  888. },
  889. () => {
  890. printRandom([["Geta squeezes in on his gut with both hands, sloshing you around in the sickly stew of cereal, milk, and enzymatic slime."],
  891. ["Your organic prison snarls and churns, soaking you in fresh acids and hastening your wretched demise."]]);
  892. statLerp("health", -10, 2000);
  893. return true;
  894. },
  895. () => {
  896. if (state.geta.swallowsLeft == 0) {
  897. print(["A deep series of *glurks* rattles your bones."]);
  898. startTimer({
  899. id: "stomach-milk",
  900. func: () => {
  901. print(["A torrent of cold milk pours into the fox's stomach."]);
  902. return false;
  903. },
  904. delay: 3000,
  905. loop: false,
  906. classes: [
  907. "digestion"
  908. ]
  909. });
  910. } else if (state.geta.swallowsLeft > 0) {
  911. print(["Muffled chewing comes from far above. A moment later, you hear a wet *gluk*"]);
  912. startTimer({
  913. id: "stomach-cereal",
  914. func: () => {
  915. print(["A slimy heap of well-chewed corn flakes splatters down around you."]);
  916. return false;
  917. },
  918. delay: 4000,
  919. loop: false,
  920. classes: [
  921. ]
  922. });
  923. } else if (state.geta.swallowsLeft < 0) {
  924. print(["You hear a few light swallows."]);
  925. startTimer({
  926. id: "stomach-coffee",
  927. func: () => {
  928. print(["Gouts of hot, bitter coffee pour into the fox's guts."]);
  929. return false;
  930. },
  931. delay: 3000,
  932. loop: false,
  933. classes: [
  934. ]
  935. });
  936. }
  937. return true;
  938. },
  939. () => {
  940. print(["\"You were barely worth eating,\" murmurs the fox. \"So small. So weak.\""]);
  941. return true;
  942. }
  943. ];
  944. if (choices[Math.floor(Math.random() * choices.length)]()) {
  945. return Math.random() * 3000 + 3500;
  946. } else {
  947. return false;
  948. }
  949. },
  950. delay: 5000,
  951. loop: true,
  952. classes: [
  953. "digestion"
  954. ]
  955. });
  956. startTimer({
  957. id: "digest",
  958. func: () => {
  959. changeStat("health", -0.3 * state.geta.acidStrength);
  960. if (getStat("health") <= 0) {
  961. print(["You're gradually digested, merciful oblivion ending your torment in the " + word.disgusting + " depths of your captor..."]);
  962. goToRoom("digested");
  963. return false;
  964. }
  965. return true;
  966. },
  967. delay: 100,
  968. loop: true,
  969. classes: [
  970. "digestion"
  971. ]
  972. });
  973. },
  974. "exit": (room) => {
  975. },
  976. "actions": [
  977. {
  978. name: "Squirm",
  979. desc: "Rub at the walls of the fox's churning stomach",
  980. execute: (room) => {
  981. printRandom([
  982. ["You punch and kick at the walls"],
  983. ["A powerful churn grabs hold of you, stifling any attempts at struggling"],
  984. ["Your little thumps and kicks do little to faze your captor"]
  985. ]);
  986. },
  987. show: [
  988. ],
  989. conditions: [
  990. ]
  991. },
  992. {
  993. name: "Beg",
  994. desc: "Plead for your life",
  995. execute: (room) => {
  996. printRandom([
  997. [
  998. "\"PLEASE!\" you scream, thumping on the walls of the vulpine's gut. \"Let me out!\"",
  999. ]
  1000. ])
  1001. if (Math.random() < 0.7) {
  1002. print(["Your pleas fall on deaf ears."]);
  1003. } else {
  1004. printRandom([
  1005. ["\"Shhhh,\" growls Geta, \"you're going to die in me. Stop whimpering.\""],
  1006. ["A long moment passes. \"Poor thing,\" says your captor."]
  1007. ])
  1008. }
  1009. },
  1010. show: [
  1011. ],
  1012. conditions: [
  1013. ]
  1014. },
  1015. {
  1016. name: "Scream",
  1017. desc: "IT HURTS",
  1018. execute: (room) => {
  1019. printRandom([
  1020. [
  1021. "\"Oh god, oh god, oh god,\" you wail...quivering and quaking as you're digested alive. \"GETA!\""
  1022. ],
  1023. [
  1024. "A blood-curdling scream bellows from your burning lungs."
  1025. ],
  1026. [
  1027. "You let out a hideous wail as the fox digests you alive."
  1028. ]
  1029. ]);
  1030. if (Math.random() < 0.5) {
  1031. print(["Geta doesn't notice."]);
  1032. } else {
  1033. print(["A booming chuckle rocks your body."]);
  1034. printRandom([
  1035. ["\"I hope you're suffering in there.\""],
  1036. ["\"Pathetic little snack.\""],
  1037. ["\"Ready to die?\""]
  1038. ]);
  1039. }
  1040. },
  1041. show: [
  1042. ],
  1043. conditions: [
  1044. ]
  1045. },
  1046. ],
  1047. "exits": {
  1048. },
  1049. "hooks": [
  1050. ],
  1051. "data": {
  1052. "stats": {
  1053. }
  1054. }
  1055. },
  1056. "digested": {
  1057. "id": "digested",
  1058. "name": "Geta's Stomach",
  1059. "desc": "You're just mush now",
  1060. "move": (room) => {
  1061. },
  1062. "enter": (room) => {
  1063. stopClassTimers("digestion");
  1064. stopTimer("clock");
  1065. state.player.flags.digestTime = state.info.time.value;
  1066. startTimer({
  1067. id: "absorb-clock",
  1068. func: () => {
  1069. state.info.time.value += 1;
  1070. state.info.time.value %= 86000;
  1071. if (state.info.time.value - state.player.flags.digestTime > 5 * 60) {
  1072. print(["Your molten remains drain into the fox's depths..."]);
  1073. goToRoom("absorbed");
  1074. return false;
  1075. }
  1076. return true;
  1077. },
  1078. delay: 1000 / 15,
  1079. loop: true,
  1080. classes: [
  1081. ]
  1082. });
  1083. playSfx("sfx/digest.ogg");
  1084. },
  1085. "exit": (room) => {
  1086. },
  1087. "actions": [
  1088. {
  1089. name: "Gurgle",
  1090. desc: "Glorp",
  1091. execute: (room) => {
  1092. printRandom([
  1093. ["Grrrrgle"],
  1094. ["Glorp"],
  1095. ["Glrrrrrrnnnnnn..."],
  1096. ["Gwoooooorgle"]
  1097. ]);
  1098. },
  1099. show: [
  1100. ],
  1101. conditions: [
  1102. ]
  1103. },
  1104. ],
  1105. "exits": {
  1106. },
  1107. "hooks": [
  1108. ],
  1109. "data": {
  1110. "stats": {
  1111. }
  1112. }
  1113. },
  1114. "absorbed": {
  1115. "id": "absorbed",
  1116. "name": "Geta's Fat",
  1117. "desc": "You're gone.",
  1118. "move": (room) => {
  1119. },
  1120. "enter": (room) => {
  1121. playSfx("sfx/absorb.ogg");
  1122. },
  1123. "exit": (room) => {
  1124. },
  1125. "actions": [
  1126. ],
  1127. "exits": {
  1128. },
  1129. "hooks": [
  1130. ],
  1131. "data": {
  1132. "stats": {
  1133. }
  1134. }
  1135. },
  1136. }
  1137. });
  1138. })();