munch
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.
 
 
 

414 lines
11 KiB

  1. let currentRoom = null;
  2. let currentDialog = null;
  3. let dirButtons = [];
  4. let actionButtons = [];
  5. let mode = "explore";
  6. let actions = [];
  7. let time = 9*60*60;
  8. let newline = " ";
  9. let player = new Player();
  10. let respawnRoom;
  11. let prefs = {
  12. player: {
  13. prey: true
  14. }
  15. };
  16. function round(number, digits) {
  17. return Math.round(number * Math.pow(10,digits)) / Math.pow(10,digits);
  18. }
  19. function updateExploreCompass() {
  20. for (let i = 0; i < dirButtons.length; i++) {
  21. let button = dirButtons[i];
  22. if (currentRoom.exits[i] == null) {
  23. button.disabled = true;
  24. button.classList.remove("active-compass-button");
  25. button.classList.add("inactive-button");
  26. button.innerHTML = "";
  27. } else {
  28. button.disabled = false;
  29. button.classList.remove("inactive-button");
  30. button.classList.add("active-compass-button");
  31. button.innerHTML = currentRoom.exits[i].name;
  32. }
  33. }
  34. }
  35. function updateExploreActions() {
  36. for (let i = 0; i < actionButtons.length; i++) {
  37. if (i < actions.length) {
  38. actionButtons[i].disabled = false;
  39. actionButtons[i].innerHTML = actions[i].name;
  40. actionButtons[i].classList.remove("inactive-button");
  41. actionButtons[i].classList.add("active-button");
  42. }
  43. else {
  44. actionButtons[i].disabled = true;
  45. actionButtons[i].innerHTML = "";
  46. actionButtons[i].classList.remove("active-button");
  47. actionButtons[i].classList.add("inactive-button");
  48. }
  49. }
  50. }
  51. function updateExplore() {
  52. updateExploreCompass();
  53. updateExploreActions();
  54. }
  55. function updateEaten() {
  56. let list = document.getElementById("eaten");
  57. while(list.firstChild) {
  58. list.removeChild(list.firstChild);
  59. }
  60. for (let i = 0; i < currentFoe.struggles.length; i++) {
  61. let li = document.createElement("li");
  62. let button = document.createElement("button");
  63. button.classList.add("eaten-button");
  64. button.innerHTML = currentFoe.struggles[i].name;
  65. button.addEventListener("click", function() { struggleClicked(i); } );
  66. button.addEventListener("mouseover", function() { struggleHovered(i); } );
  67. li.appendChild(button);
  68. list.appendChild(li);
  69. }
  70. }
  71. function updateCombat() {
  72. let list = document.getElementById("combat");
  73. while(list.firstChild) {
  74. list.removeChild(list.firstChild);
  75. }
  76. for (let i = 0; i < player.attacks.length; i++) {
  77. let li = document.createElement("li");
  78. let button = document.createElement("button");
  79. button.classList.add("combat-button");
  80. button.innerHTML = player.attacks[i].name;
  81. button.addEventListener("click", function() { attackClicked(i); } );
  82. button.addEventListener("mouseover", function() { attackHovered(i); } );
  83. li.appendChild(button);
  84. list.appendChild(li);
  85. }
  86. }
  87. function updateDialog() {
  88. let list = document.getElementById("dialog");
  89. while(list.firstChild) {
  90. list.removeChild(list.firstChild);
  91. }
  92. for (let i = 0; i < currentDialog.choices.length; i++) {
  93. let li = document.createElement("li");
  94. let button = document.createElement("button");
  95. button.classList.add("dialog-button");
  96. button.innerHTML = currentDialog.choices[i].text;
  97. button.addEventListener("click", function() { dialogClicked(i); });
  98. li.appendChild(button);
  99. list.appendChild(li);
  100. }
  101. }
  102. function updateDisplay() {
  103. document.querySelectorAll(".selector").forEach(function (x) {
  104. x.style.display = "none";
  105. });
  106. switch(mode) {
  107. case "explore":
  108. document.getElementById("selector-explore").style.display = "flex";
  109. updateExplore();
  110. break;
  111. case "combat":
  112. document.getElementById("selector-combat").style.display = "flex";
  113. updateCombat();
  114. break;
  115. case "dialog":
  116. document.getElementById("selector-dialog").style.display = "flex";
  117. updateDialog();
  118. break;
  119. case "eaten":
  120. document.getElementById("selector-eaten").style.display = "flex";
  121. updateEaten();
  122. break;
  123. }
  124. document.getElementById("time").innerHTML = "Time: " + renderTime(time);
  125. document.getElementById("stat-name").innerHTML = "Name: " + player.name;
  126. document.getElementById("stat-health").innerHTML = "Health: " + player.health + "/" + player.maxHealth;
  127. document.getElementById("stat-fullness").innerHTML = "Fullness: " + round(player.fullness(),0);
  128. }
  129. function advanceTime(amount) {
  130. time = (time + amount) % 86400;
  131. update(player.stomach.digest(amount));
  132. }
  133. function renderTime(time) {
  134. let suffix = (time < 43200) ? "AM" : "PM";
  135. let hour = Math.floor((time % 43200) / 3600);
  136. if (hour == 0)
  137. hour = 12;
  138. let minute = Math.floor(time / 60) % 60;
  139. if (minute < 9)
  140. minute = "0" + minute;
  141. return hour + ":" + minute + " " + suffix;
  142. }
  143. function move(direction) {
  144. let target = currentRoom.exits[direction];
  145. if (target == null) {
  146. alert("Tried to move to an empty room!");
  147. return;
  148. }
  149. moveTo(target,currentRoom.exitDescs[direction]);
  150. }
  151. function moveTo(room,desc="You go places lol") {
  152. actions = [];
  153. currentRoom = room;
  154. advanceTime(30);
  155. currentRoom.objects.forEach(function (object) {
  156. object.actions.forEach(function (action) {
  157. actions.push(action);
  158. });
  159. });
  160. update([desc,newline]);
  161. currentRoom.visit();
  162. }
  163. window.addEventListener('load', function(event) {
  164. document.getElementById("start-button").addEventListener("click", start, false);
  165. });
  166. function start() {
  167. applySettings(generateSettings());
  168. document.getElementById("create").style.display = "none";
  169. document.getElementById("game").style.display = "block";
  170. loadActions();
  171. loadCompass();
  172. loadDialog();
  173. currentRoom = createWorld();
  174. respawnRoom = currentRoom;
  175. moveTo(currentRoom);
  176. updateDisplay();
  177. }
  178. // copied from Stroll LUL
  179. function generateSettings() {
  180. let form = document.forms.namedItem("character-form");
  181. let settings = {};
  182. for (let i=0; i<form.length; i++) {
  183. let value = form[i].value == "" ? form[i].placeholder : form[i].value;
  184. if (form[i].type == "text")
  185. settings[form[i].name] = value;
  186. else if (form[i].type == "number")
  187. settings[form[i].name] = parseFloat(value);
  188. else if (form[i].type == "checkbox") {
  189. settings[form[i].name] = form[i].checked;
  190. } else if (form[i].type == "radio") {
  191. let name = form[i].name;
  192. if (form[i].checked)
  193. settings[name] = form[i].value;
  194. } else if (form[i].type == "select-one") {
  195. settings[form[i].name] = form[i][form[i].selectedIndex].value;
  196. }
  197. }
  198. return settings;
  199. }
  200. function applySettings(settings) {
  201. player.name = settings.name;
  202. for (let key in settings) {
  203. if (settings.hasOwnProperty(key)) {
  204. if (key.match(/prefs/)) {
  205. let tokens = key.split("-");
  206. let pref = prefs;
  207. pref = tokens.slice(1,-1).reduce((pref, key) => pref[key], pref);
  208. pref[tokens.slice(-1)[0]] = settings[key];
  209. }
  210. }
  211. }
  212. }
  213. function saveSettings() {
  214. window.localStorage.setItem("settings", JSON.stringify(generateSettings()));
  215. }
  216. function retrieveSettings() {
  217. return JSON.parse(window.localStorage.getItem("settings"));
  218. }
  219. function update(lines=[]) {
  220. let log = document.getElementById("log");
  221. for (let i=0; i<lines.length; i++) {
  222. let div = document.createElement("div");
  223. div.innerHTML = lines[i];
  224. log.appendChild(div);
  225. }
  226. log.scrollTop = log.scrollHeight;
  227. updateDisplay();
  228. }
  229. function changeMode(newMode) {
  230. mode = newMode;
  231. let body = document.querySelector("body");
  232. body.className = "";
  233. switch(mode) {
  234. case "explore":
  235. case "dialog":
  236. body.classList.add("explore");
  237. break;
  238. case "combat":
  239. body.classList.add("combat");
  240. break;
  241. case "eaten":
  242. body.classList.add("eaten");
  243. break;
  244. }
  245. updateDisplay();
  246. }
  247. function startCombat(opponent) {
  248. changeMode("combat");
  249. currentFoe = opponent;
  250. update(["Oh shit it's a " + opponent.description()]);
  251. }
  252. function attackClicked(index) {
  253. update([player.attacks[index].attack(currentFoe)]);
  254. if (currentFoe.health <= 0) {
  255. update(["The " + currentFoe.description() + " falls to the ground!"]);
  256. startDialog(new FallenFoe(currentFoe));
  257. } else {
  258. let attack = pick(currentFoe.attacks);
  259. update([attack.attackPlayer(player)]);
  260. if (player.health <= 0) {
  261. update(["You fall to the ground..."]);
  262. changeMode("eaten");
  263. updateDisplay();
  264. }
  265. }
  266. }
  267. function attackHovered(index) {
  268. document.getElementById("combat-desc").innerHTML = player.attacks[index].desc;
  269. }
  270. function struggleClicked(index) {
  271. let struggle = currentFoe.struggles[index];
  272. let result = struggle.struggle(player);
  273. update([result.lines]);
  274. if (result.escape) {
  275. changeMode("explore");
  276. } else {
  277. player.health -= 20;
  278. if (player.health <= -100) {
  279. update(["You digest in the depths of the " + currentFoe.description()]);
  280. moveTo(respawnRoom,"You drift through space and time...");
  281. changeMode("explore");
  282. player.health = 100;
  283. update(["You wake back up in your bed."]);
  284. }
  285. }
  286. }
  287. function struggleHovered(index) {
  288. document.getElementById("eaten-desc").innerHTML = currentFoe.struggles[index].desc;
  289. }
  290. function startDialog(dialog) {
  291. currentDialog = dialog;
  292. changeMode("dialog");
  293. update([currentDialog.text]);
  294. currentDialog.visit();
  295. updateDisplay();
  296. }
  297. function dialogClicked(index) {
  298. currentDialog = currentDialog.choices[index].node;
  299. update([currentDialog.text]);
  300. currentDialog.visit();
  301. if (currentDialog.choices.length == 0) {
  302. changeMode("explore");
  303. updateDisplay();
  304. }
  305. }
  306. function loadDialog() {
  307. dialogButtons = Array.from( document.querySelectorAll(".dialog-button"));
  308. for (let i = 0; i < dialogButtons.length; i++) {
  309. dialogButtons[i].addEventListener("click", function() { dialogClicked(i); });
  310. }
  311. }
  312. function actionClicked(index) {
  313. actions[index].action();
  314. }
  315. function loadActions() {
  316. actionButtons = Array.from( document.querySelectorAll(".action-button"));
  317. for (let i = 0; i < actionButtons.length; i++) {
  318. actionButtons[i].addEventListener("click", function() { actionClicked(i); });
  319. }
  320. }
  321. function loadCompass() {
  322. dirButtons[NORTH_WEST] = document.getElementById("compass-north-west");
  323. dirButtons[NORTH_WEST].addEventListener("click", function() {
  324. move(NORTH_WEST);
  325. });
  326. dirButtons[NORTH] = document.getElementById("compass-north");
  327. dirButtons[NORTH].addEventListener("click", function() {
  328. move(NORTH);
  329. });
  330. dirButtons[NORTH_EAST] = document.getElementById("compass-north-east");
  331. dirButtons[NORTH_EAST].addEventListener("click", function() {
  332. move(NORTH_EAST);
  333. });
  334. dirButtons[WEST] = document.getElementById("compass-west");
  335. dirButtons[WEST].addEventListener("click", function() {
  336. move(WEST);
  337. });
  338. dirButtons[EAST] = document.getElementById("compass-east");
  339. dirButtons[EAST].addEventListener("click", function() {
  340. move(EAST);
  341. });
  342. dirButtons[SOUTH_WEST] = document.getElementById("compass-south-west");
  343. dirButtons[SOUTH_WEST].addEventListener("click", function() {
  344. move(SOUTH_WEST);
  345. });
  346. dirButtons[SOUTH] = document.getElementById("compass-south");
  347. dirButtons[SOUTH].addEventListener("click", function() {
  348. move(SOUTH);
  349. });
  350. dirButtons[SOUTH_EAST] = document.getElementById("compass-south-east");
  351. dirButtons[SOUTH_EAST].addEventListener("click", function() {
  352. move(SOUTH_EAST);
  353. });
  354. }