refactored edition handling to support custom script metadata

This commit is contained in:
Steffen 2020-12-19 22:15:42 +01:00
parent 75a90f8f7c
commit 398fe89bb7
10 changed files with 53 additions and 94 deletions

View File

@ -1,6 +1,13 @@
<template> <template>
<ul class="info"> <ul class="info">
<li class="edition" :class="['edition-' + edition]"></li> <li
class="edition"
:class="['edition-' + edition]"
:style="{
backgroundImage: `url(${edition.logo ||
require('../assets/editions/' + edition.id + '.png')})`
}"
></li>
<li v-if="players.length - teams.traveler < 5"> <li v-if="players.length - teams.traveler < 5">
Please add more players! Please add more players!
</li> </li>
@ -73,27 +80,6 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
@import "../vars.scss"; @import "../vars.scss";
// Editions
@each $img, $skipIcons in $editions {
.edition-#{$img} {
background-image: url("../assets/editions/#{$img}.png");
}
@if $skipIcons != true {
.edition-#{$img}.townsfolk {
background-image: url("../assets/editions/#{$img}-townsfolk.png");
}
.edition-#{$img}.outsider {
background-image: url("../assets/editions/#{$img}-outsider.png");
}
.edition-#{$img}.minion {
background-image: url("../assets/editions/#{$img}-minion.png");
}
.edition-#{$img}.demon {
background-image: url("../assets/editions/#{$img}-demon.png");
}
}
}
.info { .info {
position: absolute; position: absolute;
display: flex; display: flex;

View File

@ -7,12 +7,23 @@
v-for="edition in editions" v-for="edition in editions"
class="edition" class="edition"
:class="['edition-' + edition.id]" :class="['edition-' + edition.id]"
:style="{
backgroundImage: `url(${require('../../assets/editions/' +
edition.id +
'.png')})`
}"
:key="edition.id" :key="edition.id"
@click="setEdition(edition.id)" @click="setEdition(edition)"
> >
{{ edition.name }} {{ edition.name }}
</li> </li>
<li class="edition edition-custom" @click="isCustom = true"> <li
class="edition edition-custom"
@click="isCustom = true"
:style="{
backgroundImage: `url(${require('../../assets/editions/custom.png')})`
}"
>
Custom Script / Characters Custom Script / Characters
</li> </li>
</ul> </ul>
@ -152,7 +163,7 @@ export default {
return role; return role;
}); });
this.$store.commit("setCustomRoles", customRoles); this.$store.commit("setCustomRoles", customRoles);
this.$store.commit("setEdition", "custom"); this.$store.commit("setEdition", { id: "custom" });
// check for fabled and set those too, if present // check for fabled and set those too, if present
if (customRoles.some(({ id }) => this.$store.state.fabled.has(id))) { if (customRoles.some(({ id }) => this.$store.state.fabled.has(id))) {
const fabled = []; const fabled = [];
@ -171,29 +182,6 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "../../vars";
// Editions
@each $img, $skipIcons in $editions {
.edition-#{$img} {
background-image: url("../../assets/editions/#{$img}.png");
}
@if $skipIcons != true {
.edition-#{$img}.townsfolk {
background-image: url("../../assets/editions/#{$img}-townsfolk.png");
}
.edition-#{$img}.outsider {
background-image: url("../../assets/editions/#{$img}-outsider.png");
}
.edition-#{$img}.minion {
background-image: url("../../assets/editions/#{$img}-minion.png");
}
.edition-#{$img}.demon {
background-image: url("../../assets/editions/#{$img}-demon.png");
}
}
}
ul.editions .edition { ul.editions .edition {
font-family: PiratesBay, sans-serif; font-family: PiratesBay, sans-serif;
letter-spacing: 1px; letter-spacing: 1px;

View File

@ -35,7 +35,7 @@ export default {
return JSON.stringify({ return JSON.stringify({
bluffs: this.players.bluffs.map(({ id }) => id), bluffs: this.players.bluffs.map(({ id }) => id),
edition: this.edition, edition: this.edition,
roles: this.edition !== "custom" ? "" : this.$store.getters.customRoles, roles: this.edition.isOfficial ? "" : this.$store.getters.customRoles,
fabled: this.players.fabled.map(({ id }) => id), fabled: this.players.fabled.map(({ id }) => id),
players: this.players.players.map(player => ({ players: this.players.players.map(player => ({
...player, ...player,

View File

@ -13,7 +13,7 @@
<h3> <h3>
Night Order Night Order
<font-awesome-icon icon="cloud-moon" /> <font-awesome-icon icon="cloud-moon" />
{{ editionName }} {{ edition.name || "Custom Script" }}
</h3> </h3>
<div class="night"> <div class="night">
<ul class="first"> <ul class="first">
@ -62,7 +62,6 @@
<script> <script>
import Modal from "./Modal"; import Modal from "./Modal";
import editionJSON from "./../../editions.json";
import { mapMutations, mapState } from "vuex"; import { mapMutations, mapState } from "vuex";
export default { export default {
@ -75,10 +74,6 @@ export default {
}; };
}, },
computed: { computed: {
editionName: function() {
const edition = editionJSON.find(({ id }) => id === this.edition);
return edition ? edition.name : "Custom Script";
},
rolesFirstNight: function() { rolesFirstNight: function() {
const rolesFirstNight = []; const rolesFirstNight = [];
// add minion / demon infos to night order sheet // add minion / demon infos to night order sheet

View File

@ -13,7 +13,7 @@
<h3> <h3>
Character Reference Character Reference
<font-awesome-icon icon="address-card" /> <font-awesome-icon icon="address-card" />
{{ editionName }} {{ edition.name || "Custom Script" }}
</h3> </h3>
<ul class="legend"> <ul class="legend">
<li> <li>
@ -50,7 +50,6 @@
<script> <script>
import Modal from "./Modal"; import Modal from "./Modal";
import editionJSON from "./../../editions.json";
import { mapMutations, mapState } from "vuex"; import { mapMutations, mapState } from "vuex";
export default { export default {
@ -63,10 +62,6 @@ export default {
}; };
}, },
computed: { computed: {
editionName: function() {
const edition = editionJSON.find(({ id }) => id === this.edition);
return edition ? edition.name : "Custom Script";
},
rolesGrouped: function() { rolesGrouped: function() {
const rolesGrouped = {}; const rolesGrouped = {};
this.roles.forEach(role => { this.roles.forEach(role => {

View File

@ -5,7 +5,8 @@
"hasTravelers": true, "hasTravelers": true,
"description": "Clouds roll in over Ravenswood Bluff, engulfing this sleepy town and its superstitious inhabitants in foreboding shadow. Freshly-washed clothes dance eerily on lines strung between cottages. Chimneys cough plumes of smoke into the air. Exotic scents waft through cracks in windows and under doors, as hidden cauldrons lay bubbling. An unusually warm Autumn breeze wraps around vine-covered walls and whispers ominously to those brave enough to walk the cobbled streets.\n\nAnxious mothers call their children home from play, as thunder begins to clap on the horizon. If you listen more closely, however, noises stranger still can be heard echoing from the neighbouring forest. Under the watchful eye of a looming monastery, silhouetted figures skip from doorway to doorway. Those who can read the signs know there is... Trouble Brewing.", "description": "Clouds roll in over Ravenswood Bluff, engulfing this sleepy town and its superstitious inhabitants in foreboding shadow. Freshly-washed clothes dance eerily on lines strung between cottages. Chimneys cough plumes of smoke into the air. Exotic scents waft through cracks in windows and under doors, as hidden cauldrons lay bubbling. An unusually warm Autumn breeze wraps around vine-covered walls and whispers ominously to those brave enough to walk the cobbled streets.\n\nAnxious mothers call their children home from play, as thunder begins to clap on the horizon. If you listen more closely, however, noises stranger still can be heard echoing from the neighbouring forest. Under the watchful eye of a looming monastery, silhouetted figures skip from doorway to doorway. Those who can read the signs know there is... Trouble Brewing.",
"level": "Beginner", "level": "Beginner",
"roles": [] "roles": [],
"isOfficial": true
}, },
{ {
"id": "bmr", "id": "bmr",
@ -13,7 +14,8 @@
"hasTravelers": true, "hasTravelers": true,
"description": "The sun is swallowed by a jagged horizon as another winter's day surrenders to the night. Flecks of orange and red decay into deeper browns, the forest transforming in silent anticipation of the coming snow.\n\nRavenous wolves howl from the bowels of a rocky crevasse beyond the town borders, sending birds scattering from their cozy rooks. Travelers hurry into the inn, seeking shelter from the gathering chill. They warm themselves with hot tea, sweet strains of music and hearty ale, unaware that strange and nefarious eyes stalk them from the ruins of this once great city.\n\nTonight, even the livestock know there is a... Bad Moon Rising.", "description": "The sun is swallowed by a jagged horizon as another winter's day surrenders to the night. Flecks of orange and red decay into deeper browns, the forest transforming in silent anticipation of the coming snow.\n\nRavenous wolves howl from the bowels of a rocky crevasse beyond the town borders, sending birds scattering from their cozy rooks. Travelers hurry into the inn, seeking shelter from the gathering chill. They warm themselves with hot tea, sweet strains of music and hearty ale, unaware that strange and nefarious eyes stalk them from the ruins of this once great city.\n\nTonight, even the livestock know there is a... Bad Moon Rising.",
"level": "Intermediate", "level": "Intermediate",
"roles": [] "roles": [],
"isOfficial": true
}, },
{ {
"id": "snv", "id": "snv",
@ -21,7 +23,8 @@
"hasTravelers": true, "hasTravelers": true,
"description": "Vibrant spring gives way to a warm and inviting summer. Flowers of every description blossom as far as the eye can see, tenderly nurtured in public gardens and window boxes overlooking the lavish promenade. Birds sing, artists paint and philosophers ponder life's greatest mysteries inside a bustling tavern as a circus pitches its endearingly ragged tent on the edge of town.\n\nAs the townsfolk bask in frivolity and mischief, indulging themselves in fine entertainment and even finer wine, dark and clandestine forces are assembling. Witches and cults lurk in majestic ruins on the fringes of the community, hosting secret meetings in underground caves and malevolently plotting the downfall of Ravenswood Bluff and its revelers.\n\nThe time is ripe for... Sects & Violets.", "description": "Vibrant spring gives way to a warm and inviting summer. Flowers of every description blossom as far as the eye can see, tenderly nurtured in public gardens and window boxes overlooking the lavish promenade. Birds sing, artists paint and philosophers ponder life's greatest mysteries inside a bustling tavern as a circus pitches its endearingly ragged tent on the edge of town.\n\nAs the townsfolk bask in frivolity and mischief, indulging themselves in fine entertainment and even finer wine, dark and clandestine forces are assembling. Witches and cults lurk in majestic ruins on the fringes of the community, hosting secret meetings in underground caves and malevolently plotting the downfall of Ravenswood Bluff and its revelers.\n\nThe time is ripe for... Sects & Violets.",
"level": "Intermediate", "level": "Intermediate",
"roles": [] "roles": [],
"isOfficial": true
}, },
{ {
"id": "luf", "id": "luf",
@ -29,6 +32,7 @@
"hasTravelers": false, "hasTravelers": false,
"description": "", "description": "",
"level": "Veteran", "level": "Veteran",
"roles": ["balloonist", "savant", "amnesiac", "fisherman", "artist", "cannibal", "mutant", "lunatic", "widow", "goblin", "leviathan"] "roles": ["balloonist", "savant", "amnesiac", "fisherman", "artist", "cannibal", "mutant", "lunatic", "widow", "goblin", "leviathan"],
"isOfficial": true
} }
] ]

View File

@ -10,17 +10,16 @@ import fabledJSON from "../fabled.json";
Vue.use(Vuex); Vue.use(Vuex);
const editionJSONbyId = new Map(
editionJSON.map(edition => [edition.id, edition])
);
const rolesJSONbyId = new Map(rolesJSON.map(role => [role.id, role])); const rolesJSONbyId = new Map(rolesJSON.map(role => [role.id, role]));
const fabled = new Map(fabledJSON.map(role => [role.id, role])); const fabled = new Map(fabledJSON.map(role => [role.id, role]));
const getRolesByEdition = (edition = "tb") => { const getRolesByEdition = (edition = editionJSON[0]) => {
const selectedEdition =
editionJSON.find(({ id }) => id === edition) || editionJSON[0];
return new Map( return new Map(
rolesJSON rolesJSON
.filter( .filter(r => r.edition === edition.id || edition.roles.includes(r.id))
r => r.edition === edition || selectedEdition.roles.includes(r.id)
)
.sort((a, b) => b.team.localeCompare(a.team)) .sort((a, b) => b.team.localeCompare(a.team))
.map(role => [role.id, role]) .map(role => [role.id, role])
); );
@ -70,7 +69,7 @@ export default new Vuex.Store({
roles: false, roles: false,
voteHistory: false voteHistory: false
}, },
edition: "tb", edition: editionJSONbyId.get("tb"),
roles: getRolesByEdition(), roles: getRolesByEdition(),
fabled fabled
}, },
@ -189,11 +188,13 @@ export default new Vuex.Store({
); );
}, },
setEdition(state, edition) { setEdition(state, edition) {
if (editionJSONbyId.has(edition.id)) {
state.edition = editionJSONbyId.get(edition.id);
state.roles = getRolesByEdition(state.edition);
} else {
state.edition = edition; state.edition = edition;
state.modals.edition = false;
if (edition !== "custom") {
state.roles = getRolesByEdition(edition);
} }
state.modals.edition = false;
} }
}, },
plugins: [persistence, socket] plugins: [persistence, socket]

View File

@ -9,13 +9,13 @@ module.exports = store => {
if (localStorage.isPublic !== undefined) { if (localStorage.isPublic !== undefined) {
store.commit("toggleGrimoire", JSON.parse(localStorage.isPublic)); store.commit("toggleGrimoire", JSON.parse(localStorage.isPublic));
} }
if (localStorage.edition !== undefined) {
// this will initialize state.roles!
store.commit("setEdition", localStorage.edition);
}
if (localStorage.roles !== undefined) { if (localStorage.roles !== undefined) {
store.commit("setCustomRoles", JSON.parse(localStorage.roles)); store.commit("setCustomRoles", JSON.parse(localStorage.roles));
store.commit("setEdition", "custom"); store.commit("setEdition", { id: "custom" });
}
if (localStorage.edition !== undefined) {
// this will initialize state.roles for official editions
store.commit("setEdition", JSON.parse(localStorage.edition));
} }
if (localStorage.bluffs !== undefined) { if (localStorage.bluffs !== undefined) {
JSON.parse(localStorage.bluffs).forEach((role, index) => { JSON.parse(localStorage.bluffs).forEach((role, index) => {
@ -75,10 +75,8 @@ module.exports = store => {
} }
break; break;
case "setEdition": case "setEdition":
if (payload === "custom") { localStorage.setItem("edition", JSON.stringify(payload));
localStorage.removeItem("edition"); if (state.edition.isOfficial) {
} else {
localStorage.setItem("edition", payload);
localStorage.removeItem("roles"); localStorage.removeItem("roles");
} }
break; break;

View File

@ -320,7 +320,7 @@ class LiveSession {
if (this._isSpectator) return; if (this._isSpectator) return;
const { edition } = this._store.state; const { edition } = this._store.state;
let roles; let roles;
if (edition === "custom") { if (!edition.isOfficial) {
roles = Array.from(this._store.state.roles.keys()); roles = Array.from(this._store.state.roles.keys());
} }
this._send("edition", { this._send("edition", {

View File

@ -4,11 +4,3 @@ $outsider: #46d5ff;
$minion: #ff6900; $minion: #ff6900;
$demon: #ce0100; $demon: #ce0100;
$traveler: #cc04ff; $traveler: #cc04ff;
$editions:
'tb',
'bmr',
'snv',
'luf' true,
'custom' true
;