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

781 lines
26 KiB

  1. (() => {
  2. function checkSuspicion(state, add = 0) {
  3. const old = getStat("suspicion", state);
  4. if (add >= 0) {
  5. add *= state.info.awareness.value;
  6. }
  7. changeStat("suspicion", add, state);
  8. if (getStat("suspicion", state) >= 100) {
  9. print(["Geta spots you!", "You're snatched up and tossed into the fox's bowl of cereal."]);
  10. goToRoom("in-bowl", state);
  11. return false;
  12. } else if (getStat("suspicion", state) >= 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. stories.push({
  18. "id": "geta-unaware",
  19. "name": "Geta's Breakfast",
  20. "tags": [
  21. "Player Prey",
  22. "Digestion",
  23. "Macro/Micro",
  24. "Hard Vore"
  25. ],
  26. "intro": {
  27. "start": "pepper-grinder",
  28. "setup": state => {
  29. state.info.awareness = {
  30. id: "awareness",
  31. name: "Geta's Awareness",
  32. type: "counter",
  33. value: 1,
  34. get render() {
  35. if (this.value < 1) {
  36. return "Distracted";
  37. } else if (this.value == 1) {
  38. return "Normal"
  39. } else {
  40. return "Alert"
  41. }
  42. }
  43. }
  44. state.geta = {};
  45. state.player.stats.health = { name: "Health", type: "meter", value: 100, min: 0, max: 100, color: "rgb(255,55,55)" };
  46. state.player.stats.suspicion = { name: "Suspicion", type: "meter", value: 0, min: 0, max: 100, color: "rgb(100,100,100)" };
  47. state.player.stats.mawPos = { "name": "Struggle", "type": "meter", "value": 0.5, "min": 0, "max": 1, "color": "rgb(0,255,0)", hidden: true }
  48. state.info.time.value = 60 * 60 * 7 + 60 * 17;
  49. startTimer({
  50. id: "clock",
  51. func: state => {
  52. state.info.time.value += 1;
  53. state.info.time.value %= 86000;
  54. return true;
  55. },
  56. delay: 1000,
  57. loop: true,
  58. classes: [
  59. ]
  60. }, state);
  61. startTimer({
  62. id: "suspicion-decay",
  63. func: state => {
  64. checkSuspicion(state, -0.1);
  65. return true;
  66. },
  67. delay: 100,
  68. loop: true,
  69. classes: [
  70. "free"
  71. ]
  72. }, state);
  73. startTimer({
  74. id: "timeout",
  75. func: state => {
  76. if (state.info.time.value == 60 * 60 * 7 + 60 * 19) {
  77. print(["The fox is almost done with his breakfast..."]);
  78. }
  79. if (state.info.time.value >= 60 * 60 * 7 + 60 * 20) {
  80. print(["Time's up! In you go."]);
  81. goToRoom("maw", state);
  82. return false;
  83. }
  84. return true;
  85. },
  86. delay: 1000,
  87. loop: true,
  88. classes: [
  89. "free"
  90. ]
  91. }, state);
  92. startTimer({
  93. id: "geta-action",
  94. func: state => {
  95. const random = Math.random();
  96. if (random < 0.7) {
  97. print(["Geta slurps up a spoonful of cereal."]);
  98. return Math.random() * 3000 + 3000
  99. } else if (random < 0.9) {
  100. state.info.awareness.value = 0.1;
  101. print(["The fox yawns and stretches."]);
  102. startTimer({
  103. id: "yawn-end",
  104. func: state => {
  105. print(["Geta finishes his stretch"]);
  106. state.info.awareness.value = 1;
  107. return true;
  108. },
  109. delay: 5000,
  110. loop: false,
  111. classes: [
  112. "free"
  113. ]
  114. }, state);
  115. return Math.random() * 3000 + 5000
  116. } else {
  117. state.info.awareness.value = 2;
  118. print(["Geta narrows his eyes and looks around the table. Something seems off to him..."]);
  119. startTimer({
  120. id: "squint-end",
  121. func: state => {
  122. print(["He goes back to his breakfast."]);
  123. state.info.awareness.value = 1;
  124. return true;
  125. },
  126. delay: 5000,
  127. loop: false,
  128. classes: [
  129. "free"
  130. ]
  131. }, state);
  132. return Math.random() * 1000 + 6000
  133. }
  134. },
  135. delay: 5000,
  136. loop: true,
  137. classes: [
  138. "free"
  139. ]
  140. }, state);
  141. },
  142. "intro": state => {
  143. print(["Game started", newline, "Exposition goes here later."]);
  144. }
  145. },
  146. "sounds": [
  147. "loop/stomach.ogg"
  148. ],
  149. "preload": [
  150. ],
  151. "world": {
  152. "pepper-grinder": {
  153. "id": "pepper-grinder",
  154. "name": "Pepper Grinder",
  155. "desc": "You're hiding behind a pepper grinder",
  156. "move": (room, state) => {
  157. print(["You dart over to the pepper grinder, which looms over you like a greatwood."]);
  158. },
  159. "enter": (room, state) => {
  160. },
  161. "exit": (room, state) => {
  162. },
  163. "actions": [
  164. {
  165. name: "Tap",
  166. desc: "Bang on the pepper shaker",
  167. execute: (room, state) => {
  168. print(["You thump the pepper shaker, making a dull thud."]);
  169. const safe = checkSuspicion(state, 25);
  170. if (safe && getStat("suspicion", state) > 50) {
  171. print(["Geta leans in to have a closer look. He's going to catch you if you don't move!"]);
  172. startTimer({
  173. id: "pepper-investigate",
  174. func: state => {
  175. if (state.player.location == "pepper-grinder") {
  176. print(["He catches you.", newline, "You're tossed into the fox's jaws."]);
  177. goToRoom("maw", state);
  178. } else {
  179. print(["You evaded the fox."]);
  180. }
  181. },
  182. delay: 3000,
  183. loop: false,
  184. classes: [
  185. "free"
  186. ]
  187. }, state);
  188. }
  189. },
  190. show: [
  191. ],
  192. conditions: [
  193. ]
  194. },
  195. {
  196. name: "Wait",
  197. desc: "Wait for the fox to finish his breakfast. Surely you'll be able to escape after that...right?",
  198. execute: (room, state) => {
  199. state.info.time.value = 60 * 60 * 7 + 60 * 20;
  200. },
  201. show: [
  202. ],
  203. conditions: [
  204. ]
  205. },
  206. ],
  207. "exits": {
  208. "up": {
  209. "target": "bowl",
  210. "desc": "Walk up to the cereal bowl",
  211. "show": [
  212. ],
  213. "conditions": [
  214. ],
  215. "hooks": [
  216. (room, exit, state) => {
  217. return checkSuspicion(state, 10);
  218. }
  219. ]
  220. },
  221. "left": {
  222. "target": "table",
  223. "desc": "Run out into the open",
  224. "show": [
  225. ],
  226. "conditions": [
  227. ],
  228. "hooks": [
  229. ]
  230. },
  231. },
  232. "hooks": [
  233. ],
  234. "data": {
  235. "stats": {
  236. }
  237. }
  238. },
  239. "bowl": {
  240. "id": "bowl",
  241. "name": "Behind the Bowl",
  242. "desc": "You're crouched behind Geta's bowl of cereal",
  243. "move": (room, state) => {
  244. print(["You scurry up to the looming bowl, staying low and out of Geta's sight."]);
  245. },
  246. "enter": (room, state) => {
  247. },
  248. "exit": (room, state) => {
  249. },
  250. "actions": [
  251. ],
  252. "exits": {
  253. "ascend": {
  254. "target": "in-bowl",
  255. "desc": "Climb into Geta's cereal",
  256. "show": [
  257. ],
  258. "conditions": [
  259. ],
  260. "hooks": [
  261. ]
  262. },
  263. "down": {
  264. "target": "pepper-grinder",
  265. "desc": "Run back behind the pepper grinder",
  266. "show": [
  267. ],
  268. "conditions": [
  269. ],
  270. "hooks": [
  271. (room, exit, state) => {
  272. return checkSuspicion(state, 15);
  273. }
  274. ]
  275. },
  276. },
  277. "hooks": [
  278. ],
  279. "data": {
  280. "stats": {
  281. }
  282. }
  283. },
  284. "table": {
  285. "id": "table",
  286. "name": "Table",
  287. "desc": "You're out in the open!",
  288. "move": (room, state) => {
  289. },
  290. "enter": (room, state) => {
  291. startTimer({
  292. id: "table-suspicion",
  293. func: state => {
  294. checkSuspicion(state, 1.5);
  295. return true;
  296. },
  297. delay: 100,
  298. loop: true,
  299. classes: [
  300. "free"
  301. ]
  302. }, state);
  303. },
  304. "exit": (room, state) => {
  305. stopTimer("table-suspicion", state);
  306. },
  307. "actions": [
  308. ],
  309. "exits": {
  310. "right": {
  311. "target": "pepper-grinder",
  312. "desc": "Run back to cover",
  313. "show": [
  314. ],
  315. "conditions": [
  316. ],
  317. "hooks": [
  318. ]
  319. },
  320. },
  321. "hooks": [
  322. ],
  323. "data": {
  324. "stats": {
  325. }
  326. }
  327. },
  328. "in-bowl": {
  329. "id": "in-bowl",
  330. "name": "Bowl",
  331. "desc": "You're in the cereal bowl...",
  332. "move": (room, state) => {
  333. print(["Why did you do that?"]);
  334. },
  335. "enter": (room, state) => {
  336. stopClassTimers("free", state);
  337. startTimer({
  338. id: "geta-eat",
  339. func: state => {
  340. if (Math.random() < 0.6) {
  341. print(["Geta scoops up a spoonful of cereal; you narrowly avoid being caught."]);
  342. return true;
  343. } else {
  344. print(["Geta scoops you up and slurps you into his maw."]);
  345. goToRoom("maw", state);
  346. return false;
  347. }
  348. },
  349. delay: 3000,
  350. loop: true,
  351. classes: [
  352. "free"
  353. ]
  354. }, state);
  355. },
  356. "exit": (room, state) => {
  357. },
  358. "actions": [
  359. ],
  360. "exits": {
  361. "ascend": {
  362. "target": "bowl",
  363. "desc": "Try to climb back out!",
  364. "show": [
  365. ],
  366. "conditions": [
  367. ],
  368. "hooks": [
  369. (room, exit, state) => {
  370. print([
  371. "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."
  372. ]);
  373. goToRoom("maw", state);
  374. return false;
  375. }
  376. ]
  377. },
  378. },
  379. "hooks": [
  380. ],
  381. "data": {
  382. "stats": {
  383. }
  384. }
  385. },
  386. "maw": {
  387. "id": "maw",
  388. "name": "Geta's Maw",
  389. "desc": "You've been slurped up into the fox's jaws",
  390. "move": (room, state) => {
  391. },
  392. "enter": (room, state) => {
  393. stopClassTimers("free", state);
  394. state.player.stats.mawPos.hidden = false;
  395. state.geta.slurps = 0;
  396. state.geta.chews = 0;
  397. startTimer({
  398. id: "maw-random-movement",
  399. func: state => {
  400. changeStat("mawPos", Math.random()/50 - 0.01, state);
  401. return true;
  402. },
  403. delay: 100,
  404. loop: true,
  405. classes: [
  406. "maw-struggle"
  407. ]
  408. }, state);
  409. startTimer({
  410. id: "maw-struggle",
  411. func: state => {
  412. if (getStat("mawPos", state) <= 0.05) {
  413. print(["Swallowed!"]);
  414. goToRoom("throat", state);
  415. return false;
  416. } else if (getStat("mawPos", state) >= 0.95) {
  417. print(["Chewed!"]);
  418. changeStat("health", -90, state);
  419. goToRoom("stomach", state);
  420. return false;
  421. }
  422. let choice;
  423. if (Math.random() > state.geta.slurps / 3) {
  424. choice = "slurp";
  425. } else if (state.geta.chews - Math.floor(Math.random()*3) < state.geta.slurps) {
  426. choice = "chew";
  427. } else {
  428. choice = "swallow";
  429. }
  430. if (choice == "swallow") {
  431. if (getStat("mawPos", state) < 0.15) {
  432. print(["Swallowed!"]);
  433. goToRoom("throat", state);
  434. return false;
  435. } else {
  436. print(["Swallows"]);
  437. changeStat("mawPos", -0.25, state);
  438. state.geta.slurps = 0;
  439. state.geta.chews = 0;
  440. return Math.random() * 1500 + 2500;
  441. }
  442. } else if (choice == "slurp") {
  443. changeStat("mawPos", -0.1, state);
  444. print(["Slurps"]);
  445. state.geta.slurps += 1;
  446. return Math.random() * 1000 + 1500;
  447. } else if (choice == "chew") {
  448. if (getStat("mawPos", state) > 0.85) {
  449. print(["Chewed!"]);
  450. changeStat("health", -90, state);
  451. goToRoom("stomach", state);
  452. return false;
  453. } else {
  454. print(["Chews"]);
  455. state.geta.chews += 1;
  456. return Math.random() * 500 + 1000;
  457. }
  458. }
  459. },
  460. delay: 0,
  461. loop: true,
  462. classes: [
  463. "maw-struggle"
  464. ]
  465. }, state);
  466. },
  467. "exit": (room, state) => {
  468. },
  469. "actions": [
  470. {
  471. name: "Struggle",
  472. desc: "Pull yourself away from the fox's throat! Just don't go too far forward...",
  473. execute: (room, state) => {
  474. print(["You drag yourself forward"]);
  475. changeStat("mawPos", Math.random() * 0.1 + 0.15, state);
  476. },
  477. show: [
  478. ],
  479. conditions: [
  480. ]
  481. },
  482. {
  483. name: "Slip Back",
  484. desc: "Slide back towards Geta's gullet",
  485. execute: (room, state) => {
  486. print(["You let yourself slip back"]);
  487. changeStat("mawPos", -Math.random() / 5 - 0.2, state);
  488. },
  489. show: [
  490. ],
  491. conditions: [
  492. ]
  493. },
  494. ],
  495. "exits": {
  496. },
  497. "hooks": [
  498. ],
  499. "data": {
  500. "stats": {
  501. }
  502. }
  503. },
  504. "throat": {
  505. "id": "throat",
  506. "name": "Geta's Gullet",
  507. "desc": "GULP!",
  508. "move": (room, state) => {
  509. },
  510. "enter": (room, state) => {
  511. state.player.stats.mawPos.hidden = true;
  512. stopClassTimers("maw-struggle", state);
  513. startTimer({
  514. id: "throat-swallow",
  515. func: state => {
  516. print(["You slush down into Geta's stomach"]);
  517. goToRoom("stomach", state);
  518. return true;
  519. },
  520. delay: 7000,
  521. loop: false,
  522. classes: [
  523. ]
  524. }, state);
  525. },
  526. "exit": (room, state) => {
  527. },
  528. "actions": [
  529. {
  530. name: "Struggle",
  531. desc: "Try to climb back out!",
  532. execute: (room, state) => {
  533. print(["Nope"]);
  534. },
  535. show: [
  536. ],
  537. conditions: [
  538. ]
  539. },
  540. {
  541. name: "Give up",
  542. desc: "Dive down into Geta's stomach",
  543. execute: (room, state) => {
  544. print(["You submit to your predator."]);
  545. goToRoom("stomach", state);
  546. stopTimer("throat-swallow", state);
  547. },
  548. show: [
  549. ],
  550. conditions: [
  551. ]
  552. },
  553. ],
  554. "exits": {
  555. },
  556. "hooks": [
  557. ],
  558. "data": {
  559. "stats": {
  560. }
  561. }
  562. },
  563. "stomach": {
  564. "id": "stomach",
  565. "name": "Geta's Stomach",
  566. "desc": "Glorp",
  567. "move": (room, state) => {
  568. },
  569. "enter": (room, state) => {
  570. playLoop("loop/stomach.ogg");
  571. stopClassTimers("maw-struggle", state);
  572. startTimer({
  573. id: "digest",
  574. func: state => {
  575. changeStat("health", -0.3, state);
  576. if (getStat("health", state) <= 0) {
  577. print(["You're digested before too long."]);
  578. goToRoom("digested", state);
  579. return false;
  580. }
  581. return true;
  582. },
  583. delay: 100,
  584. loop: true,
  585. classes: [
  586. ]
  587. }, state);
  588. },
  589. "exit": (room, state) => {
  590. },
  591. "actions": [
  592. {
  593. name: "Squirm",
  594. desc: "Rub at the walls of the fox's churning stomach",
  595. execute: (room, state) => {
  596. printRandom([
  597. ["You punch and kick at the walls"],
  598. ["A powerful churn grabs hold of you, stifling any attempts at struggling"],
  599. ["Your little thumps and kicks do little to faze your captor"]
  600. ]);
  601. },
  602. show: [
  603. ],
  604. conditions: [
  605. ]
  606. },
  607. ],
  608. "exits": {
  609. },
  610. "hooks": [
  611. ],
  612. "data": {
  613. "stats": {
  614. }
  615. }
  616. },
  617. "digested": {
  618. "id": "digested",
  619. "name": "Fat",
  620. "desc": "You're just fat now",
  621. "move": (room, state) => {
  622. },
  623. "enter": (room, state) => {
  624. },
  625. "exit": (room, state) => {
  626. },
  627. "actions": [
  628. {
  629. name: "Gurgle",
  630. desc: "Glorp",
  631. execute: (room, state) => {
  632. printRandom([
  633. ["Grrrrgle"],
  634. ["Glorp"],
  635. ["Glrrrrrrnnnnnn..."],
  636. ["Gwoooooorgle"]
  637. ]);
  638. },
  639. show: [
  640. ],
  641. conditions: [
  642. ]
  643. },
  644. ],
  645. "exits": {
  646. },
  647. "hooks": [
  648. ],
  649. "data": {
  650. "stats": {
  651. }
  652. }
  653. },
  654. }
  655. });
  656. })();