From a7852115feb4389366429c5a7b295c8498de3e9e Mon Sep 17 00:00:00 2001 From: Steffen Date: Thu, 15 Apr 2021 21:05:00 +0200 Subject: [PATCH] add support for custom fabled (closes #110) --- CHANGELOG.md | 5 +++ src/store/index.js | 93 +++++++++++++++++++++------------------- src/store/persistence.js | 10 +++-- src/store/socket.js | 8 ++-- 4 files changed, 66 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da9017c..b147f4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Release Notes +### Version 2.13.0 +- add support for custom Fabled characters + +--- + ### Version 2.12.0 - tweak reference sheet to better fit screen in single column layout - add warning icon overlay for setup roles on character assignment modal diff --git a/src/store/index.js b/src/store/index.js index 06a03be..bd9aee0 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -162,54 +162,61 @@ export default new Vuex.Store({ * @param roles Array of role IDs or full role definitions */ setCustomRoles(state, roles) { - state.roles = new Map( - roles - // replace numerical role object keys with matching key names - .map(role => { - if (role[0]) { - const customKeys = Object.keys(customRole); - const mappedRole = {}; - for (let prop in role) { - if (customKeys[prop]) { - mappedRole[customKeys[prop]] = role[prop]; - } + const processedRoles = roles + // replace numerical role object keys with matching key names + .map(role => { + if (role[0]) { + const customKeys = Object.keys(customRole); + const mappedRole = {}; + for (let prop in role) { + if (customKeys[prop]) { + mappedRole[customKeys[prop]] = role[prop]; } - return mappedRole; - } else { - return role; } - }) - // clean up role.id - .map(role => { - role.id = role.id.toLocaleLowerCase().replace(/[^a-z0-9]/g, ""); + return mappedRole; + } else { return role; - }) - // map existing roles to base definition or pre-populate custom roles to ensure all properties - .map( - role => - rolesJSONbyId.get(role.id) || - state.roles.get(role.id) || - Object.assign({}, customRole, role) - ) - // default empty icons and placeholders - .map(role => { - if (rolesJSONbyId.get(role.id)) return role; - role.imageAlt = // map team to generic icon - { - townsfolk: "good", - outsider: "outsider", - minion: "minion", - demon: "evil" - }[role.team] || "custom"; - return role; - }) - // filter out roles that don't match an existing role and also don't have name/ability/team - .filter(role => role.name && role.ability && role.team) - // sort by team - .sort((a, b) => b.team.localeCompare(a.team)) - // convert to Map + } + }) + // clean up role.id + .map(role => { + role.id = role.id.toLocaleLowerCase().replace(/[^a-z0-9]/g, ""); + return role; + }) + // map existing roles to base definition or pre-populate custom roles to ensure all properties + .map( + role => + rolesJSONbyId.get(role.id) || + state.roles.get(role.id) || + Object.assign({}, customRole, role) + ) + // default empty icons and placeholders + .map(role => { + if (rolesJSONbyId.get(role.id)) return role; + role.imageAlt = // map team to generic icon + { + townsfolk: "good", + outsider: "outsider", + minion: "minion", + demon: "evil" + }[role.team] || "custom"; + return role; + }) + // filter out roles that don't match an existing role and also don't have name/ability/team + .filter(role => role.name && role.ability && role.team) + // sort by team + .sort((a, b) => b.team.localeCompare(a.team)); + // convert to Map without Fabled + state.roles = new Map( + processedRoles + .filter(role => role.team !== "fabled") .map(role => [role.id, role]) ); + // update Fabled to include custom Fabled from this script + state.fabled = new Map([ + ...fabledJSON.map(role => [role.id, role]), + ...processedRoles.filter(r => r.team === "fabled").map(r => [r.id, r]) + ]); // update extraTravelers map to only show travelers not in this script state.otherTravelers = new Map( rolesJSON diff --git a/src/store/persistence.js b/src/store/persistence.js index 55c2b78..5660db7 100644 --- a/src/store/persistence.js +++ b/src/store/persistence.js @@ -39,8 +39,8 @@ module.exports = store => { } if (localStorage.fabled !== undefined) { store.commit("players/setFabled", { - fabled: JSON.parse(localStorage.fabled).map(id => - store.state.fabled.get(id) + fabled: JSON.parse(localStorage.fabled).map( + fabled => store.state.fabled.get(fabled.id) || fabled ) }); } @@ -127,7 +127,11 @@ module.exports = store => { case "players/setFabled": localStorage.setItem( "fabled", - JSON.stringify(state.players.fabled.map(({ id }) => id)) + JSON.stringify( + state.players.fabled.map(fabled => + fabled.isCustom ? fabled : { id: fabled.id } + ) + ) ); break; case "players/add": diff --git a/src/store/socket.js b/src/store/socket.js index e193a08..1537fcc 100644 --- a/src/store/socket.js +++ b/src/store/socket.js @@ -272,7 +272,7 @@ class LiveSession { votingSpeed: session.votingSpeed, lockedVote: session.lockedVote, isVoteInProgress: session.isVoteInProgress, - fabled: fabled.map(({ id }) => id), + fabled: fabled.map(f => (f.isCustom ? f : { id: f.id })), ...(session.nomination ? { votes: session.votes } : {}) }); } @@ -348,7 +348,7 @@ class LiveSession { isVoteInProgress }); this._store.commit("players/setFabled", { - fabled: fabled.map(id => this._store.state.fabled.get(id)) + fabled: fabled.map(f => this._store.state.fabled.get(f.id) || f) }); } } @@ -407,7 +407,7 @@ class LiveSession { const { fabled } = this._store.state.players; this._send( "fabled", - fabled.map(({ id }) => id) + fabled.map(f => (f.isCustom ? f : { id: f.id })) ); } @@ -419,7 +419,7 @@ class LiveSession { _updateFabled(fabled) { if (!this._isSpectator) return; this._store.commit("players/setFabled", { - fabled: fabled.map(id => this._store.state.fabled.get(id)) + fabled: fabled.map(f => this._store.state.fabled.get(f.id) || f) }); }