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.
 
 
 

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