a munch adventure
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 

275 rindas
6.0 KiB

  1. dirs = {
  2. "up-left": "Northwest",
  3. "up": "North",
  4. "up-right": "Northeast",
  5. "left": "West",
  6. "right": "East",
  7. "down-left": "Southwest",
  8. "down": "South",
  9. "down-right": "Southeast",
  10. "ascend": "Up",
  11. "descend": "Down"
  12. }
  13. moveListeners = {
  14. }
  15. actionButtons = [
  16. ]
  17. function initWorld(story, state) {
  18. state.world = story["world"];
  19. initRoomState(state);
  20. }
  21. function initRoomState(state) {
  22. state.player.rooms = {};
  23. Object.entries(state.world).forEach(([key, val]) => {
  24. state.player.rooms[key] = {};
  25. });
  26. }
  27. function resetControls(state) {
  28. const moveHolder = document.querySelector("#move-holder");
  29. moveHolder.innerHTML = "";
  30. Object.entries(dirs).forEach(([dir, name]) => {
  31. const button = document.createElement("button");
  32. button.classList.add("move-button")
  33. button.id = "move-" + dir;
  34. button.classList.add("disabled");
  35. button.setAttribute("disabled", "true");
  36. button.textContent = dirs[dir];
  37. moveHolder.appendChild(button);
  38. moveListeners[dir] = undefined;
  39. });
  40. const actionHolder = document.querySelector("#actions");
  41. actionHolder.innerHTML = "";
  42. actionButtons = [];
  43. if (state.player.location) {
  44. state.world[state.player.location].actions.forEach(action => {
  45. actionButtons.push(undefined);
  46. });
  47. }
  48. }
  49. function showActionDescription(desc) {
  50. const descHolder = document.querySelector("#desc");
  51. descHolder.textContent = desc;
  52. }
  53. function removeActionDescription() {
  54. const descHolder = document.querySelector("#desc");
  55. descHolder.textContent = "";
  56. }
  57. function moveToRoom(src, exit, dest, state) {
  58. const from = state.world[state.player.location];
  59. const room = state.world[dest];
  60. if (exit.hooks) {
  61. for (let hook of exit.hooks) {
  62. if (!hook(room, exit, state)) {
  63. return;
  64. }
  65. }
  66. }
  67. if (room.hooks) {
  68. for (let hook of room.hooks) {
  69. if (!hook(room, state)) {
  70. return;
  71. }
  72. }
  73. }
  74. if (exit.move)
  75. exit.move(from, state);
  76. if (from && from.exit)
  77. from.exit(from, state);
  78. if (room.move)
  79. room.move(room, state);
  80. if (room.enter)
  81. room.enter(room, state);
  82. state.player.location = dest;
  83. resetControls(state);
  84. refresh();
  85. }
  86. function goToRoom(dest, state) {
  87. const from = state.world[state.player.location];
  88. const room = state.world[dest];
  89. if (room.hooks) {
  90. for (let hook of room.hooks) {
  91. if (!hook(room, state)) {
  92. return;
  93. }
  94. }
  95. }
  96. if (from && from.exit)
  97. from.exit(from, state);
  98. if (room.enter)
  99. room.enter(state.world[dest], state);
  100. state.player.location = dest;
  101. resetControls(state);
  102. refresh();
  103. }
  104. function updateRoom(state) {
  105. const name = state.player.location;
  106. const room = state.world[name];
  107. if (!state.player.rooms[room.id]) {
  108. state.player.rooms[room.id] = {};
  109. }
  110. const areaName = document.querySelector("#area-name");
  111. const areaDesc = document.querySelector("#area-desc");
  112. areaName.textContent = room.name;
  113. areaDesc.textContent = room.desc;
  114. Object.entries(dirs).forEach(([dir, name]) => {
  115. const button = document.querySelector("#move-" + dir);
  116. button.classList.add("disabled");
  117. button.setAttribute("disabled", "true");
  118. button.textContent = dirs[dir];
  119. });
  120. if (room.exits) {
  121. Object.entries(room.exits).forEach(([dir, exit]) => {
  122. const button = document.querySelector("#move-" + dir);
  123. const dest = state.world[exit.target];
  124. // don't even show an exit if this fails!
  125. if (exit.show) {
  126. if (!exit.show.every(cond => cond(room, state))) {
  127. return;
  128. }
  129. }
  130. button.textContent = dest.name;
  131. // if any condition fails, don't enable/add a listener
  132. if (exit.conditions) {
  133. if (!exit.conditions.every(cond => cond(room,state))) {
  134. return;
  135. }
  136. }
  137. button.classList.remove("disabled");
  138. button.removeAttribute("disabled");
  139. if (moveListeners[dir]) {
  140. button.removeEventListener("click", moveListeners[dir]);
  141. moveListeners[dir] = undefined;
  142. }
  143. moveFunc = () => {
  144. moveToRoom(room, exit, exit.target, state);
  145. };
  146. button.addEventListener("click", moveFunc);
  147. moveListeners[dir] = moveFunc;
  148. button.addEventListener("mouseenter", () => {
  149. showActionDescription(exit.desc);
  150. });
  151. button.addEventListener("mouseleave", () => {
  152. removeActionDescription();
  153. });
  154. });
  155. }
  156. const actionHolder = document.querySelector("#actions");
  157. const existingButtons = Array.from(document.querySelectorAll("#actions > button"));
  158. const keptButtons = [];
  159. if (room.actions) {
  160. for (index in room.actions) {
  161. const action = room.actions[index];
  162. let button;
  163. if (actionButtons[index]) {
  164. button = actionButtons[index];
  165. }
  166. else {
  167. button = document.createElement("button");
  168. button.classList.add("action-button");
  169. actionButtons[index] = button;
  170. button.textContent = action.name;
  171. button.addEventListener("click", () => {
  172. action.execute(room, state);
  173. refresh();
  174. });
  175. button.addEventListener("mouseenter", () => {
  176. showActionDescription(action.desc);
  177. });
  178. button.addEventListener("mouseleave", () => {
  179. removeActionDescription();
  180. });
  181. }
  182. if (action.show) {
  183. if (!action.show.every(cond => cond(room, state))) {
  184. continue;
  185. }
  186. }
  187. keptButtons.push(actionButtons[index]);
  188. if (action.conditions) {
  189. if (!action.conditions.every(cond => cond(room, state))) {
  190. button.classList.add("disabled");
  191. button.setAttribute("disabled", "true");
  192. }
  193. }
  194. }
  195. const removed = existingButtons.filter(button => {
  196. return !keptButtons.includes(button);
  197. });
  198. removed.forEach(button => actionHolder.removeChild(button));
  199. const added = actionButtons.filter(button => {
  200. return keptButtons.includes(button) && !existingButtons.includes(button);
  201. });
  202. added.forEach(button => actionHolder.appendChild(button));
  203. }
  204. }