a munch adventure
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 

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