a munch adventure
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

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