a munch adventure
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

241 lines
5.1 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. actionListeners = {
  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. }
  41. function showActionDescription(desc) {
  42. const descHolder = document.querySelector("#desc");
  43. descHolder.textContent = desc;
  44. }
  45. function removeActionDescription() {
  46. const descHolder = document.querySelector("#desc");
  47. descHolder.textContent = "";
  48. }
  49. function moveToRoom(src, exit, dest, state) {
  50. const from = state.world[state.player.location];
  51. const room = state.world[dest];
  52. if (exit.hooks) {
  53. for (let hook of exit.hooks) {
  54. if (!hook(room, exit, state)) {
  55. return;
  56. }
  57. }
  58. }
  59. if (room.hooks) {
  60. for (let hook of room.hooks) {
  61. if (!hook(room, state)) {
  62. return;
  63. }
  64. }
  65. }
  66. if (exit.move)
  67. exit.move(from, state);
  68. if (from && from.exit)
  69. from.exit(from, state);
  70. if (room.move)
  71. room.move(room, state);
  72. if (room.enter)
  73. room.enter(room, state);
  74. state.player.location = dest;
  75. resetControls();
  76. refresh();
  77. }
  78. function goToRoom(dest, state) {
  79. const from = state.world[state.player.location];
  80. const room = state.world[dest];
  81. if (room.hooks) {
  82. for (let hook of room.hooks) {
  83. if (!hook(room, state)) {
  84. return;
  85. }
  86. }
  87. }
  88. if (from && from.exit)
  89. from.exit(from, state);
  90. if (room.enter)
  91. room.enter(state.world[dest], state);
  92. state.player.location = dest;
  93. resetControls();
  94. refresh();
  95. }
  96. function updateRoom(state) {
  97. const name = state.player.location;
  98. const room = state.world[name];
  99. if (!state.player.rooms[room.id]) {
  100. state.player.rooms[room.id] = {};
  101. }
  102. const areaName = document.querySelector("#area-name");
  103. const areaDesc = document.querySelector("#area-desc");
  104. areaName.textContent = room.name;
  105. areaDesc.textContent = room.desc;
  106. Object.entries(dirs).forEach(([dir, name]) => {
  107. const button = document.querySelector("#move-" + dir);
  108. button.classList.add("disabled");
  109. button.setAttribute("disabled", "true");
  110. button.textContent = dirs[dir];
  111. });
  112. if (room.exits) {
  113. Object.entries(room.exits).forEach(([dir, exit]) => {
  114. const button = document.querySelector("#move-" + dir);
  115. const dest = state.world[exit.target];
  116. // don't even show an exit if this fails!
  117. if (exit.show) {
  118. if (!exit.show.every(cond => cond(room, state))) {
  119. return;
  120. }
  121. }
  122. button.textContent = dest.name;
  123. // if any condition fails, don't enable/add a listener
  124. if (exit.conditions) {
  125. if (!exit.conditions.every(cond => cond(room,state))) {
  126. return;
  127. }
  128. }
  129. button.classList.remove("disabled");
  130. button.removeAttribute("disabled");
  131. if (moveListeners[dir]) {
  132. button.removeEventListener("click", moveListeners[dir]);
  133. moveListeners[dir] = undefined;
  134. }
  135. moveFunc = () => {
  136. moveToRoom(room, exit, exit.target, state);
  137. };
  138. button.addEventListener("click", moveFunc);
  139. moveListeners[dir] = moveFunc;
  140. button.addEventListener("mouseenter", () => {
  141. showActionDescription(exit.desc);
  142. });
  143. button.addEventListener("mouseleave", () => {
  144. removeActionDescription();
  145. });
  146. });
  147. }
  148. const actionHolder = document.querySelector("#actions");
  149. actionHolder.innerHTML = "";
  150. if (room.actions) {
  151. room.actions.forEach(action => {
  152. const button = document.createElement("button");
  153. button.classList.add("action-button");
  154. if (action.show) {
  155. if (!action.show.every(cond => cond(room, state))) {
  156. return;
  157. }
  158. }
  159. button.textContent = action.name;
  160. actionHolder.appendChild(button);
  161. if (action.conditions) {
  162. if (!action.conditions.every(cond => cond(room, state))) {
  163. button.classList.add("disabled");
  164. button.setAttribute("disabled", "true");
  165. return;
  166. }
  167. }
  168. button.addEventListener("click", () => {
  169. action.execute(room, state);
  170. refresh();
  171. });
  172. button.addEventListener("mouseenter", () => {
  173. showActionDescription(action.desc);
  174. });
  175. button.addEventListener("mouseleave", () => {
  176. removeActionDescription();
  177. });
  178. });
  179. }
  180. }