crunch
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 

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