statemanager.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. function getCurrentView() {
  2. var room = rooms.find(room => room.id == userData.position);
  3. displayViews(room);
  4. }
  5. function updateCargo() {
  6. let cargoContainer = document.getElementById("cargo");
  7. groupByType(userData.inCargoHold).forEach((group) => {
  8. let cargoRow = document.createElement("div");
  9. cargoRow.innerHTML = `${group[0].description} (x${group.length})`;
  10. cargoContainer.appendChild(cargoRow);
  11. })
  12. }
  13. function buildActions(room) {
  14. document.getElementById("additional-actions").innerHTML = "";
  15. if (room.actions) {
  16. room.actions.forEach(control => {
  17. let state = states.find(state => state.id == control);
  18. if (!state.show || state.show()) {
  19. let actionButton = document.createElement("button");
  20. actionButton.className = "action button";
  21. actionButton.innerHTML = state.button;
  22. actionButton.addEventListener("click", event => {
  23. trigger(state);
  24. });
  25. document.getElementById("additional-actions").appendChild(actionButton);
  26. }
  27. });
  28. }
  29. }
  30. function triggerStateById(stateId) {
  31. let state = states.find(state => state.id == stateId);
  32. trigger(state);
  33. }
  34. function buildDoors(room) {
  35. document.getElementById("destinations").innerHTML = "";
  36. if (room.doors) {
  37. room.doors.forEach(door => {
  38. let doorButton = document.createElement("button");
  39. doorButton.className = "door button";
  40. let doorText = document.createElement("span")
  41. doorText.className = "text"
  42. doorText.innerHTML = door.button;
  43. doorButton.appendChild(doorText)
  44. doorButton.addEventListener("click", event => {
  45. trigger(door);
  46. });
  47. document.getElementById("destinations").appendChild(doorButton);
  48. })
  49. }
  50. }
  51. function setDoorsActive(room) {
  52. let doorContainer = document.getElementById("destinations");
  53. for(let i = 0; i < doorContainer.children.length; i++) {
  54. let door = doorContainer.children[i];
  55. door.disabled = "";
  56. if (isFlagEnabled('solar-enabled') || isFlagEnabled('ramjet-enabled') || isFlagEnabled('ion-engine-enabled')) {
  57. door.disabled = "disabled";
  58. }
  59. }
  60. }
  61. async function displayViews(room) {
  62. let viewsContainer = document.getElementById('room-views');
  63. viewsContainer.innerHTML = "";
  64. play(room.play);
  65. await setupShipStatus(room, viewsContainer);
  66. for(let i = 0; i < room.viewable.length; i++) {
  67. let viewable = room.viewable[i];
  68. let template = await templateLoader.get(viewable.elementId);
  69. let container = document.createElement('div');
  70. container.id = viewable.elementId;
  71. container.innerHTML = template;
  72. viewsContainer.appendChild(container);
  73. setupViewable(room, viewable, container);
  74. }
  75. if(room.enter) {
  76. room.enter();
  77. }
  78. await setupChat(room, viewsContainer);
  79. }
  80. async function setupShipStatus(room, viewsContainer) {
  81. let template = await templateLoader.get("shipstatus")
  82. let container = document.createElement('div');
  83. container.id = "shipstatus";
  84. container.innerHTML = template;
  85. viewsContainer.appendChild(container);
  86. updateActivity("Idle");
  87. updateFuel();
  88. updateMoney();
  89. updateEnergy();
  90. updateCargo();
  91. }
  92. function setupViewable(room, viewable, element) {
  93. element.style.display = "block";
  94. switch (viewable.elementId) {
  95. case "put-in-inventory":
  96. putInInventory(viewable, element, viewable.data.source());
  97. break;
  98. case "get-from-inventory":
  99. getFromInventory(viewable, element, viewable.data.validator);
  100. break;
  101. case 'asteroid-field':
  102. updateSpaceDebris();
  103. break;
  104. case 'room-description':
  105. updatePosition(room.name);
  106. updateDescription(room.description);
  107. break;
  108. case 'doors':
  109. buildDoors(room);
  110. setDoorsActive(room);
  111. break;
  112. case 'actions':
  113. buildActions(room);
  114. break;
  115. }
  116. }
  117. async function setupChat(room, viewsContainer) {
  118. let template = await templateLoader.get("chat")
  119. let container = document.createElement('div');
  120. container.id = "chat";
  121. container.innerHTML = template;
  122. viewsContainer.appendChild(container);
  123. attachChat(room);
  124. }
  125. function updatePosition(newPositionText) {
  126. if (!newPositionText) {
  127. return;
  128. }
  129. document.getElementById("position").innerHTML = "Location: " + newPositionText;
  130. }
  131. function updateDescription(newDescriptionText) {
  132. if (!newDescriptionText) {
  133. return;
  134. }
  135. document.getElementById("description").innerHTML = newDescriptionText;
  136. }
  137. function putInInventory(viewable, element, gatheringSource) {
  138. let moveLeft = (event) => {
  139. let left = element.getElementsByClassName("left-inv-selector")[0];
  140. let right = element.getElementsByClassName("right-inv-selector")[0];
  141. right.removeChild(event.target);
  142. left.appendChild(event.target);
  143. let index = selectedItems.indexOf(event.target.item);
  144. if (index > -1) {
  145. selectedItems.splice(index, 1);
  146. }
  147. event.target.removeEventListener("click", moveLeft);
  148. event.target.addEventListener("click", moveRight);
  149. let topBar = element.getElementsByClassName("top-bar")[0];
  150. let cargoSize = topBar.getElementsByTagName("span")[0];
  151. cargoSize.innerHTML = `${selectedItems.length + userData.inCargoHold.length}/${userData.maxCargoCapacity}`;
  152. };
  153. let moveRight = (event) => {
  154. let left = element.getElementsByClassName("left-inv-selector")[0];
  155. let right = element.getElementsByClassName("right-inv-selector")[0];
  156. left.removeChild(event.target);
  157. right.appendChild(event.target);
  158. selectedItems.push(event.target.item);
  159. event.target.removeEventListener("click", moveRight);
  160. event.target.addEventListener("click", moveLeft);
  161. let topBar = element.getElementsByClassName("top-bar")[0];
  162. let cargoSize = topBar.getElementsByTagName("span")[0];
  163. cargoSize.innerHTML = `${selectedItems.length + userData.inCargoHold.length}/${userData.maxCargoCapacity}`;
  164. };
  165. selectedItems = [];
  166. let left = element.getElementsByClassName("left-inv-selector")[0];
  167. left.innerHTML = '';
  168. let right = element.getElementsByClassName("right-inv-selector")[0];
  169. right.innerHTML = '';
  170. gatheringSource.forEach(item => {
  171. let clickableItem = document.createElement("div");
  172. clickableItem.innerHTML = item.description;
  173. clickableItem.className = "clickable-inventory-item";
  174. clickableItem.item = item;
  175. clickableItem.addEventListener("click", moveRight);
  176. left.appendChild(clickableItem);
  177. });
  178. userData.inCargoHold.forEach(item => {
  179. let unclickableItem = document.createElement("div");
  180. unclickableItem.innerHTML = item.description;
  181. unclickableItem.className = "inventory-item";
  182. right.appendChild(unclickableItem);
  183. });
  184. let header = element.getElementsByClassName('selector-header')[0];
  185. header.innerHTML = viewable.data.button;
  186. let topBar = element.getElementsByClassName("top-bar")[0];
  187. let selectAll = topBar.getElementsByTagName("button")[0];
  188. selectAll.addEventListener("click", event => {
  189. let left = element.getElementsByClassName("left-inv-selector")[0];
  190. let selectableItems = left.getElementsByClassName("clickable-inventory-item");
  191. for (let i = selectableItems.length - 1; i >= 0; i--) {
  192. let child = selectableItems[i];
  193. child.click();
  194. };
  195. });
  196. let cargoSize = topBar.getElementsByTagName("span")[0];
  197. cargoSize.innerHTML = `${selectedItems.length + userData.inCargoHold.length}/${userData.maxCargoCapacity}`;
  198. let bottomBar = element.getElementsByClassName("bottom-bar")[0];
  199. let actionButton = bottomBar.getElementsByTagName("button")[0];
  200. actionButton.innerHTML = viewable.data.button;
  201. actionButton.addEventListener("click", () => {
  202. triggerStateById(viewable.data.action);
  203. });
  204. }
  205. function getFromInventory(viewable, element, validator = () => true) {
  206. let moveLeft = (event) => {
  207. let left = element.getElementsByClassName("left-inv-selector")[0];
  208. let right = element.getElementsByClassName("right-inv-selector")[0];
  209. right.removeChild(event.target);
  210. left.appendChild(event.target);
  211. let index = selectedItems.indexOf(event.target.item);
  212. if (index > -1) {
  213. selectedItems.splice(index, 1);
  214. }
  215. event.target.removeEventListener("click", moveLeft);
  216. event.target.addEventListener("click", moveRight);
  217. };
  218. let moveRight = (event) => {
  219. let left = element.getElementsByClassName("left-inv-selector")[0];
  220. let right = element.getElementsByClassName("right-inv-selector")[0];
  221. left.removeChild(event.target);
  222. right.appendChild(event.target);
  223. selectedItems.push(event.target.item);
  224. event.target.removeEventListener("click", moveRight);
  225. event.target.addEventListener("click", moveLeft);
  226. };
  227. selectedItems = [];
  228. let left = element.getElementsByClassName("left-inv-selector")[0];
  229. left.innerHTML = '';
  230. let right = element.getElementsByClassName("right-inv-selector")[0];
  231. right.innerHTML = '';
  232. userData.inCargoHold.forEach(item => {
  233. let clickableItem = document.createElement("div");
  234. clickableItem.innerHTML = item.description;
  235. clickableItem.className = "inventory-item";
  236. if(validator(item)) {
  237. clickableItem.className = "clickable-inventory-item";
  238. }
  239. clickableItem.item = item;
  240. clickableItem.addEventListener("click", moveRight);
  241. left.appendChild(clickableItem);
  242. });
  243. let header = element.getElementsByClassName('selector-header')[0];
  244. header.innerHTML = viewable.data.button;
  245. let topBar = element.getElementsByClassName("top-bar")[0];
  246. let selectAll = topBar.getElementsByTagName("button")[0];
  247. selectAll.addEventListener("click", event => {
  248. let left = element.getElementsByClassName("left-inv-selector")[0];
  249. let selectableItems = left.getElementsByClassName("clickable-inventory-item");
  250. for (let i = selectableItems.length - 1; i >= 0; i--) {
  251. let child = selectableItems[i];
  252. child.click();
  253. };
  254. });
  255. let bottomBar = element.getElementsByClassName("bottom-bar")[0];
  256. let actionButton = bottomBar.getElementsByTagName("button")[0];
  257. actionButton.innerHTML = viewable.data.button;
  258. actionButton.addEventListener("click", () => {
  259. if(viewable.data.action) {
  260. triggerStateById(viewable.data.action);
  261. }
  262. });
  263. }
  264. function updateSpaceDebris() {
  265. let debrisContainer = document.getElementById("asteroid-field");
  266. groupByType(userData.debrisInSpace).forEach((group) => {
  267. let debrisRow = document.createElement("div");
  268. debrisRow.innerHTML = `${group[0].description} (x${group.length})`;
  269. debrisContainer.appendChild(debrisRow);
  270. })
  271. }
  272. function trigger(control) {
  273. clearTimeout(timeoutId);
  274. document.getElementById("progress").value = 0;
  275. errorMessage = "";
  276. if (control.requires()) {
  277. // disableAction();
  278. updateActivity(control.action);
  279. startControl(control);
  280. let step = control.step || 10;
  281. if (typeof control.step == "function") {
  282. step = control.step();
  283. }
  284. let duration = control.duration;
  285. if (typeof control.duration == "function") {
  286. duration = control.duration();
  287. }
  288. if (duration > 0) {
  289. delayLoop(() => runControl(control), duration, step);
  290. } else {
  291. runControl(control);
  292. }
  293. }
  294. updateError();
  295. }
  296. function startControl(control) {
  297. if(control.start) {
  298. control.start();
  299. }
  300. }
  301. function runControl(control) {
  302. control.run();
  303. save();
  304. // enableAction();
  305. getCurrentView();
  306. }
  307. function save() {
  308. localStorage.setItem("spaceloop1-save", JSON.stringify(userData));
  309. }
  310. function load() {
  311. var gameDataString = localStorage.getItem("spaceloop1-save");
  312. if (gameDataString == null) {
  313. // No save file! let's start at the beginning.
  314. getCurrentView();
  315. return;
  316. }
  317. userData = JSON.parse(gameDataString);
  318. migrateVersion(userData);
  319. getCurrentView();
  320. }
  321. function migrateVersion(oldUserData) {
  322. //TODO: check save file version, adjust as needed
  323. }
  324. function setFlag(flag) {
  325. if (!userData.enabled.find(enabledFlag => enabledFlag == flag)) {
  326. userData.enabled.push(flag);
  327. }
  328. }
  329. function clearFlag(flag) {
  330. let index = userData.enabled.findIndex(enabledFlag => enabledFlag == flag);
  331. if (index != -1) {
  332. userData.enabled.splice(index, 1);
  333. }
  334. }
  335. function isFlagEnabled(flag) {
  336. return !!userData.enabled.find(enabledFlag => enabledFlag == flag);
  337. }