dirs = { "up-left": "Northwest", "up": "North", "up-right": "Northeast", "left": "West", "right": "East", "down-left": "Southwest", "down": "South", "down-right": "Southeast", "ascend": "Up", "descend": "Down" } function initWorld(story, state) { state.world = story["world"]; initRoomState(state); } function initRoomState(state) { state.player.rooms = {}; Object.entries(state.world).forEach(([key, val]) => { state.player.rooms[key] = {}; }); } function showActionDescription(desc) { const descHolder = document.querySelector("#desc"); descHolder.textContent = desc; } function removeActionDescription() { const descHolder = document.querySelector("#desc"); descHolder.textContent = ""; } function moveToRoom(src, exit, dest, state) { const from = state.world[state.player.location]; const room = state.world[dest]; if (exit.hooks) { for (let hook of exit.hooks) { if (!hook(room, exit, state)) { return; } } } if (room.hooks) { for (let hook of room.hooks) { if (!hook(room, state)) { return; } } } if (exit.move) exit.move(from, state); if (from && from.exit) from.exit(from, state); if (room.move) room.move(room, state); if (room.enter) room.enter(room, state); state.player.location = dest; refresh(); } function goToRoom(dest, state) { const from = state.world[state.player.location]; const room = state.world[dest]; if (room.hooks) { for (let hook of room.hooks) { if (!hook(room, state)) { return; } } } if (from && from.exit) from.exit(from, state); if (room.enter) room.enter(state.world[dest], state); state.player.location = dest; refresh(); } function updateRoom(state) { const name = state.player.location; const room = state.world[name]; if (!state.player.rooms[room.id]) { state.player.rooms[room.id] = {}; } const areaName = document.querySelector("#area-name"); const areaDesc = document.querySelector("#area-desc"); areaName.textContent = room.name; areaDesc.textContent = room.desc; const moveHolder = document.querySelector("#move-holder"); moveHolder.innerHTML = ""; Object.entries(dirs).forEach(([dir, name]) => { const button = document.createElement("button"); button.classList.add("move-button") button.id = "move-" + dir; button.classList.add("disabled"); button.setAttribute("disabled", "true"); button.textContent = dirs[dir]; moveHolder.appendChild(button); }); if (room.exits) { Object.entries(room.exits).forEach(([dir, exit]) => { const button = document.querySelector("#move-" + dir); const dest = state.world[exit.target]; // don't even show an exit if this fails! if (exit.show) { if (!exit.show.every(cond => cond(room, state))) { return; } } button.textContent = dest.name; // if any condition fails, don't enable/add a listener if (exit.conditions) { if (!exit.conditions.every(cond => cond(room,state))) { return; } } button.classList.remove("disabled"); button.removeAttribute("disabled"); button.addEventListener("click", () => { // todo: log moveToRoom(room, exit, exit.target, state); }) button.addEventListener("mouseenter", () => { showActionDescription(exit.desc); }); button.addEventListener("mouseleave", () => { removeActionDescription(); }); }); } const actionHolder = document.querySelector("#actions"); actionHolder.innerHTML = ""; if (room.actions) { room.actions.forEach(action => { const button = document.createElement("button"); button.classList.add("action-button"); if (action.show) { if (!action.show.every(cond => cond(room, state))) { return; } } button.textContent = action.name; actionHolder.appendChild(button); if (action.conditions) { if (!action.conditions.every(cond => cond(room, state))) { button.classList.add("disabled"); button.setAttribute("disabled", "true"); return; } } button.addEventListener("click", () => { action.execute(room, state); refresh(); }); button.addEventListener("mouseenter", () => { showActionDescription(action.desc); }); button.addEventListener("mouseleave", () => { removeActionDescription(); }); }); } }