From d88b02d19908cee8499367afc421a7272391dd14 Mon Sep 17 00:00:00 2001 From: lilserf Date: Mon, 4 Jan 2021 10:50:15 -0500 Subject: [PATCH 01/62] Add V hotkey for the vote history modal --- src/App.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/App.vue b/src/App.vue index 0b6fac6..a053447 100644 --- a/src/App.vue +++ b/src/App.vue @@ -102,6 +102,9 @@ export default { if (this.session.isSpectator) return; this.$store.commit("toggleModal", "roles"); break; + case "v": + this.$store.commit("toggleModal", "voteHistory"); + break; case "escape": this.$store.commit("toggleModal"); } From 0b78848d03a9d2d50fb2fdaeba795ecaf367cccb Mon Sep 17 00:00:00 2001 From: lilserf Date: Mon, 4 Jan 2021 10:51:52 -0500 Subject: [PATCH 02/62] Add V hotkey for vote history --- src/components/Menu.vue | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/Menu.vue b/src/components/Menu.vue index 6eb4d34..c6519f4 100644 --- a/src/components/Menu.vue +++ b/src/components/Menu.vue @@ -114,8 +114,7 @@ v-if="session.voteHistory.length" @click="toggleModal('voteHistory')" > - Nomination history - + Nomination history[V]
  • Leave Session From 2717b69ea24ff36d2eb324237e20295e9d5c68f3 Mon Sep 17 00:00:00 2001 From: Jul Gvoz Date: Mon, 4 Jan 2021 19:00:24 +0200 Subject: [PATCH 03/62] voting, majority & passed clarified (closes #82) --- src/components/modals/VoteHistoryModal.vue | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/components/modals/VoteHistoryModal.vue b/src/components/modals/VoteHistoryModal.vue index a8f08f0..df43c1d 100644 --- a/src/components/modals/VoteHistoryModal.vue +++ b/src/components/modals/VoteHistoryModal.vue @@ -18,8 +18,9 @@ Nominator Nominee Type - Majority + Votes Hand up + Passed @@ -27,12 +28,14 @@ {{ vote.nominator }} {{ vote.nominee }} {{ vote.type }} - {{ vote.majority }} + {{ vote.votes.length }} / {{ vote.majority }} - {{ vote.votes.length }} {{ vote.votes.join(", ") }} + + + @@ -98,5 +101,8 @@ tbody { td:nth-child(4) { text-align: center; } + td:nth-child(6) { + text-align: center; + } } From 7019ebf9814578f78c38781f898a2b8641aa0e2f Mon Sep 17 00:00:00 2001 From: Steffen Date: Mon, 4 Jan 2021 20:26:58 +0100 Subject: [PATCH 04/62] Update linter.yml --- .github/workflows/linter.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index c797ec5..26becfe 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -18,6 +18,9 @@ on: push: branches-ignore: - 'gh-pages' + pull_request: + # The branches below must be a subset of the branches above + branches: [ main ] ############### # Set the Job # From d52d704e978089dc0b3d90748983c7529cecc3ad Mon Sep 17 00:00:00 2001 From: lilserf Date: Mon, 4 Jan 2021 15:33:51 -0500 Subject: [PATCH 05/62] Apply suggestions from code review Co-authored-by: Steffen --- src/App.vue | 4 +++- src/components/Menu.vue | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/App.vue b/src/App.vue index a053447..63c5772 100644 --- a/src/App.vue +++ b/src/App.vue @@ -103,7 +103,9 @@ export default { this.$store.commit("toggleModal", "roles"); break; case "v": - this.$store.commit("toggleModal", "voteHistory"); + if (this.session.voteHistory.length) { + this.$store.commit("toggleModal", "voteHistory"); + } break; case "escape": this.$store.commit("toggleModal"); diff --git a/src/components/Menu.vue b/src/components/Menu.vue index c6519f4..dcb53cc 100644 --- a/src/components/Menu.vue +++ b/src/components/Menu.vue @@ -114,7 +114,7 @@ v-if="session.voteHistory.length" @click="toggleModal('voteHistory')" > - Nomination history[V] + Nomination history[V]
  • Leave Session From 1a75db214c9894aba759b2c94824614036643321 Mon Sep 17 00:00:00 2001 From: Steffen Date: Wed, 6 Jan 2021 20:28:57 +0100 Subject: [PATCH 06/62] updates roles.json night order --- src/roles.json | 88 +++++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/roles.json b/src/roles.json index b1eafac..7bc7d95 100644 --- a/src/roles.json +++ b/src/roles.json @@ -67,7 +67,7 @@ "team": "townsfolk", "firstNight": 23, "firstNightReminder": ":eye: Show the finger signal (0, 1, 2) for the number of evil alive neighbours of the Empath. :eye-slash:", - "otherNight": 38, + "otherNight": 42, "otherNightReminder": ":eye: Show the finger signal (0, 1, 2) for the number of evil neighbours. :eye-slash:", "reminders": [], "setup": false, @@ -80,7 +80,7 @@ "team": "townsfolk", "firstNight": 24, "firstNightReminder": ":eye: The Fortune Teller points to two players. Give the head signal (nod yes, shake no) for whether one of those players is the Demon. :eye-slash:", - "otherNight": 39, + "otherNight": 43, "otherNightReminder": ":eye: The Fortune Teller points to two players. Show the head signal (nod “yes”, shake “no”) for whether one of those players is the Demon. :eye-slash:", "reminders": [ "Decoy" @@ -95,7 +95,7 @@ "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", - "otherNight": 40, + "otherNight": 45, "otherNightReminder": ":question-circle: If a player was executed today: :eye: Show that player’s character token. :eye-slash:", "reminders": [ "Executed" @@ -125,7 +125,7 @@ "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", - "otherNight": 37, + "otherNight": 40, "otherNightReminder": ":question-circle: If the Ravenkeeper died tonight: :eye: The Ravenkeeper points to a player. Show that player’s character token. :eye-slash:", "reminders": [], "setup": false, @@ -194,7 +194,7 @@ "team": "outsider", "firstNight": 25, "firstNightReminder": ":eye: The Butler points to a player. :eye-slash: Mark that player as “Master”. :plus-circle:", - "otherNight": 50, + "otherNight": 44, "otherNightReminder": ":eye: The Butler points to a player. :eye-slash: Mark that player as “Master”. :plus-circle:", "reminders": [ "Master" @@ -264,7 +264,7 @@ "team": "minion", "firstNight": 9, "firstNightReminder": ":eye: The Poisoner points to a player. :eye-slash: That player is poisoned. :plus-circle:", - "otherNight": 6, + "otherNight": 5, "otherNightReminder": "The previously poisoned player is no longer poisoned. :plus-circle: :eye: The Poisoner points to a player. :eye-slash: That player is poisoned. :plus-circle:", "reminders": [ "Poisoned" @@ -279,7 +279,7 @@ "team": "minion", "firstNight": 33, "firstNightReminder": ":eye: Show the Grimoire to the Spy for as long as they need. :eye-slash:", - "otherNight": 51, + "otherNight": 55, "otherNightReminder": ":eye: Show the Grimoire to the Spy for as long as they need. :eye-slash:", "reminders": [], "setup": false, @@ -320,7 +320,7 @@ "edition": "bmr", "firstNight": 26, "firstNightReminder": "Show the marked character token. Point to the marked player.", - "otherNight": 31, + "otherNight": 38, "otherNightReminder": "If the Grandmother’s grandchild was killed by the Demon tonight: • The Grandmother dies.", "reminders": [ "Grandchild" @@ -333,7 +333,7 @@ { "id": "sailor", "edition": "bmr", - "firstNight": 4, + "firstNight": 5, "firstNightReminder": "The Sailor points to a living player. Either the Sailor, or the chosen player, is drunk.", "otherNight": 2, "otherNightReminder": "The previously drunk player is no longer drunk. The Sailor points to a living player. Either the Sailor, or the chosen player, is drunk.", @@ -348,9 +348,9 @@ { "id": "chambermaid", "edition": "bmr", - "firstNight": 35, + "firstNight": 36, "firstNightReminder": "The Chambermaid points to two players. Show the number signal (0, 1, 2, …) for how many of those players wake tonight for their ability.", - "otherNight": 53, + "otherNight": 58, "otherNightReminder": "The Chambermaid points to two players. Show the number signal (0, 1, 2) for how many of those players wake tonight for their ability.", "reminders": [], "setup": false, @@ -378,7 +378,7 @@ "edition": "bmr", "firstNight": 0, "firstNightReminder": "", - "otherNight": 3, + "otherNight": 6, "otherNightReminder": "The previously protected and drunk players lose those markers. The Innkeeper points to two players. Those players are protected. One is drunk.", "reminders": [ "Protected", @@ -409,7 +409,7 @@ "edition": "bmr", "firstNight": 0, "firstNightReminder": "", - "otherNight": 30, + "otherNight": 35, "otherNightReminder": "If the Gossip’s public statement was true: • Choose a player not protected from dying tonight. That player dies.", "reminders": [ "Die" @@ -442,7 +442,7 @@ "edition": "bmr", "firstNight": 0, "firstNightReminder": "", - "otherNight": 35, + "otherNight": 34, "otherNightReminder": "If the Professor has not used their ability: • The Professor either shows the “no” head signal, or points to a player. • If that player is a Townsfolk, they are now alive.", "reminders": [ "Alive", @@ -516,7 +516,7 @@ "edition": "bmr", "firstNight": 0, "firstNightReminder": "", - "otherNight": 29, + "otherNight": 36, "otherNightReminder": "The Tinker might die.", "reminders": [ "Die" @@ -531,7 +531,7 @@ "edition": "bmr", "firstNight": 0, "firstNightReminder": "", - "otherNight": 36, + "otherNight": 37, "otherNightReminder": "If the Moonchild used their ability to target a player today: • If that player is good, they die.", "reminders": [ "Die" @@ -559,7 +559,7 @@ { "id": "lunatic", "edition": "bmr", - "firstNight": 2, + "firstNight": 3, "firstNightReminder": "If 7 or more players: Show the Lunatic a number of arbitrary “Minion“, players equal to the number of Minions in play. Show 3 character tokens of arbitrary Good characters. If the token received by the Lunatic is a Demon that would wake tonight: • Allow the Lunatic to do the Demon actions. Place their “attack” markers. Wake the Demon. Show the Demon’s real character token. Show them the Lunatic player. • If the Lunatic attacked players: Show the real demon each marked player. Remove any Lunatic “attack” markers.", "otherNight": 16, "otherNightReminder": "Allow the Lunatic to do the actions of the Demon. Place their “attack” markers. If the Lunatic selected players: Wake the Demon. Show the “attack” marker, then point to each marked player. Remove any Lunatic “attack” markers.", @@ -579,7 +579,7 @@ "edition": "bmr", "firstNight": 13, "firstNightReminder": "Show each of the Outsider tokens in play.", - "otherNight": 29, + "otherNight": 30, "otherNightReminder": "If an Outsider died today: • The Godfather points to a player. That player dies.", "reminders": [ "Died today", @@ -610,7 +610,7 @@ "edition": "bmr", "firstNight": 0, "firstNightReminder": "", - "otherNight": 28, + "otherNight": 29, "otherNightReminder": "If the Assassin has not yet used their ability: • The Assassin either shows the “no” head signal, or points to a player. That player dies.", "reminders": [ "Die", @@ -639,7 +639,7 @@ "edition": "bmr", "firstNight": 0, "firstNightReminder": "", - "otherNight": 22, + "otherNight": 23, "otherNightReminder": "If the Po chose no-one previously: The Po points to three players. Otherwise: The Po either shows the “no” head signal, or points to a player. The marked players (if any) die.", "reminders": [ "Die 1", @@ -689,7 +689,7 @@ "edition": "bmr", "firstNight": 0, "firstNightReminder": "", - "otherNight": 21, + "otherNight": 22, "otherNightReminder": "One player that the Shabaloth chose the previous night might come alive. The Shabaloth points to two players. Those players die.", "reminders": [ "Die 1", @@ -719,7 +719,7 @@ "edition": "snv", "firstNight": 28, "firstNightReminder": "The Dreamer points to a player. Show two character tokens, one of which is that player’s character, the other of which is of opposite alignment to that character.", - "otherNight": 41, + "otherNight": 46, "otherNightReminder": "The Dreamer points to a player. Show 1 good and 1 evil character token; one of these is correct.", "reminders": [], "setup": false, @@ -745,9 +745,9 @@ { "id": "mathematician", "edition": "snv", - "firstNight": 36, + "firstNight": 35, "firstNightReminder": "Show the hand signal for the number (0, 1, 2, etc.) of “Abnormal Effect” markers. Remove markers", - "otherNight": 54, + "otherNight": 57, "otherNightReminder": "Show the hand signal for the number (0, 1, 2, etc.) of “Abnormal Effect” markers. Remove markers.", "reminders": [ "Abnormal effect" @@ -762,7 +762,7 @@ "edition": "snv", "firstNight": 0, "firstNightReminder": "Place the “Demon did not vote” marker.", - "otherNight": 42, + "otherNight": 47, "otherNightReminder": "Show the head signal (nod “yes”, shake “no”) for whether the Demon voted today. Place the “Demon did not vote” marker (remove “Demon voted”, if any).", "reminders": [ "Demon did vote", @@ -778,7 +778,7 @@ "edition": "snv", "firstNight": 0, "firstNightReminder": "Place the “Minions did not nominate” marker.", - "otherNight": 43, + "otherNight": 48, "otherNightReminder": "Show the head signal (nod “yes”, shake “no”) for whether any Minion nominated today. Place the “Minions did not nominate” marker (remove “Minion nominated”, if any).", "reminders": [ "No Minion nominated", @@ -794,7 +794,7 @@ "edition": "snv", "firstNight": 0, "firstNightReminder": "", - "otherNight": 44, + "otherNight": 49, "otherNightReminder": "Show the hand signal for the number (0, 1, 2, etc.) of dead evil players.", "reminders": [], "setup": false, @@ -820,7 +820,7 @@ "edition": "snv", "firstNight": 29, "firstNightReminder": "The Seamstress either shows a “no” head signal, or points to two other players. If the Seamstress chose two players, nod “yes” or shake “no” for whether they are of same alignment.", - "otherNight": 45, + "otherNight": 50, "otherNightReminder": "If the Seamstress has not yet used their ability: • The Seamstress either shows a “no” head signal, or points to two other players. • If the Seamstress chose players, nod “yes” or shake “no” for whether they are of same alignment.", "reminders": [ "Used" @@ -866,7 +866,7 @@ "edition": "snv", "firstNight": 0, "firstNightReminder": "", - "otherNight": 46, + "otherNight": 51, "otherNightReminder": "If today was the Juggler’s first day: • Show the hand signal for the number (0, 1, 2, etc.) of “Correct” markers. Remove markers.", "reminders": [ "Correct" @@ -881,7 +881,7 @@ "edition": "snv", "firstNight": 0, "firstNightReminder": "", - "otherNight": 34, + "otherNight": 33, "otherNightReminder": "If the Sage was killed by a Demon: • Point to two players, one of which is that Demon.", "reminders": [], "setup": false, @@ -907,7 +907,7 @@ "edition": "snv", "firstNight": 0, "firstNightReminder": "", - "otherNight": 33, + "otherNight": 32, "otherNightReminder": "", "reminders": [ "Drunk" @@ -922,7 +922,7 @@ "edition": "snv", "firstNight": 0, "firstNightReminder": "", - "otherNight": 32, + "otherNight": 31, "otherNightReminder": "If the Barber died today or tonight: • Wake the Demon. Show the “This character selected you” card, then Barber token. • The Demon either shows a “no” head signal, or points to 2 non-Demon players. If they chose players: ◦ Swap the character tokens. Wake each player. Show “You are”, then their character token.", "reminders": [ "Swap" @@ -988,7 +988,7 @@ "setup": false, "name": "Cerenovus", "team": "minion", - "ability": "Each night, choose a player and a good character: they are \"mad\" they are this character tomorrow, or might be executed." + "ability": "Each night, choose a player and a good character: they are \"mad\", they are this character tomorrow, or might be executed." }, { "id": "pithag", @@ -1008,7 +1008,7 @@ "edition": "snv", "firstNight": 0, "firstNightReminder": "", - "otherNight": 23, + "otherNight": 24, "otherNightReminder": "The Fang Gu points to a player. That player dies. If that player was an Outsider: • The Fang Gu dies instead of the chosen player. The chosen player is now an evil Fang Gu. • Wake the new Fang Gu. Show the “You are” card, then the Fang Gu token. Show the “You are” card, then the thumb-down “evil” hand sign.", "reminders": [ "Die" @@ -1023,7 +1023,7 @@ "edition": "snv", "firstNight": 0, "firstNightReminder": "", - "otherNight": 26, + "otherNight": 27, "otherNightReminder": "The Vigormortis points to a player. That player dies. If a Minion, they keep their ability and one of their Townsfolk neighbours is poisoned.", "reminders": [ "Die", @@ -1040,7 +1040,7 @@ "edition": "snv", "firstNight": 0, "firstNightReminder": "", - "otherNight": 24, + "otherNight": 25, "otherNightReminder": "The No Dashii points to a player. That player dies.", "reminders": [ "Die", @@ -1056,7 +1056,7 @@ "edition": "snv", "firstNight": 0, "firstNightReminder": "", - "otherNight": 25, + "otherNight": 26, "otherNightReminder": "The Vortox points to a player. That player dies.", "reminders": [ "Die" @@ -1303,7 +1303,7 @@ "edition": "", "firstNight": 6, "firstNightReminder": "Decide the Amnesiac's entire ability. If the Amnesiac's ability causes them to wake tonight: Wake the Amnesiac and run their ability.", - "otherNight": 4, + "otherNight": 3, "otherNightReminder": "If the Amnesiac's ability causes them to wake tonight: Wake the Amnesiac and run their ability.", "reminders": [], "setup": false, @@ -1376,7 +1376,7 @@ { "id": "leviathan", "edition": "", - "firstNight": 100, + "firstNight": 38, "firstNightReminder": "Place the Leviathan “Day 1” marker. Announce “The Leviathan is in play; this is Day 1.”.", "otherNight": 100, "otherNightReminder": "Place the next Leviathan “Day n” marker, where “n” is the day number. Announce “The Leviathan is in play; this is Day n.”.", @@ -1398,7 +1398,7 @@ "edition": "", "firstNight": 0, "firstNightReminder": "", - "otherNight": 31, + "otherNight": 21, "otherNightReminder": "If either good living neighbor is drunk or poisoned, the Acrobat dies.", "reminders": [ "Die" @@ -1413,7 +1413,7 @@ "edition": "", "firstNight": 31, "firstNightReminder": "Point to a player that is evil.", - "otherNight": 48, + "otherNight": 53, "otherNightReminder": "If the evil player that was known by the Bounty Hunter died since the previous night: Point to another player that is evil.", "reminders": [ "Known" @@ -1428,7 +1428,7 @@ "edition": "", "firstNight": 32, "firstNightReminder": "The Cult Leader becomes the alignment of an alive neighbor: Show the “You are” card. Show the hand signal (thumb-up “good”, thumb-down “evil”) for the Cult Leader's current alignment.", - "otherNight": 49, + "otherNight": 54, "otherNightReminder": "The Cult Leader becomes the alignment of an alive neighbor: Show the “You are” card. Show the hand signal (thumb-up “good”, thumb-down “evil”) for the Cult Leader's current alignment.", "reminders": [], "setup": false, @@ -1441,7 +1441,7 @@ "edition": "", "firstNight": 7, "firstNightReminder": "The Preacher points to a player. If that player is a Minion: Wake the Minion. Show the Preacher token. The Minion now does not have an ability anymore.", - "otherNight": 5, + "otherNight": 4, "otherNightReminder": "The Preacher points to a player. If that player is a Minion: Wake the Minion. Show the Preacher token. The Minion now does not have an ability anymore.", "reminders": [ "No ability" @@ -1486,7 +1486,7 @@ "edition": "", "firstNight": 34, "firstNightReminder": "Show the hand signal (thumb-up “good”, thumb-down “evil”, thumb-sideways “neither”) for the alignment that you believe is winning.", - "otherNight": 52, + "otherNight": 56, "otherNightReminder": "Show the hand signal (thumb-up “good”, thumb-down “evil”, thumb-sideways “neither”) for the alignment that you believe is winning.", "reminders": [], "remindersGlobal": [], From ed6301a81215bb2ab91ed6d46596d3c31a4eaa87 Mon Sep 17 00:00:00 2001 From: Steffen Date: Wed, 6 Jan 2021 20:34:51 +0100 Subject: [PATCH 07/62] changelod --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e120e03..7b9dd69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Release Notes +## Version 2.2.0 +- added [V] hotkey to open nomination history (thanks @lilserf) +- updated roles according to official Wiki changes +- adjusted roles night order + +--- + ## Version 2.1.1 - show vote results at the end of a vote - fixed global reminders not showing up anymore when the associated role is assigned to a player From bc5aca1a8cc267e400a1cba7431c5ee989270220 Mon Sep 17 00:00:00 2001 From: Steffen Date: Wed, 6 Jan 2021 20:35:00 +0100 Subject: [PATCH 08/62] 2.2.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index c16b7ad..1bf46c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "townsquare", - "version": "2.1.1", + "version": "2.2.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0e3fc85..6e62d11 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "townsquare", - "version": "2.1.1", + "version": "2.2.0", "description": "Blood on the Clocktower Town Square", "author": "Steffen Baumgart", "scripts": { From 9c3632e2ae943b2c5f262b8207608ab3211aa15b Mon Sep 17 00:00:00 2001 From: Steffen Date: Wed, 6 Jan 2021 21:44:56 +0100 Subject: [PATCH 09/62] fix list of locked votes showing unlocked votes sometimes --- src/components/Vote.vue | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/Vote.vue b/src/components/Vote.vue index 3a41e35..905b43b 100644 --- a/src/components/Vote.vue +++ b/src/components/Vote.vue @@ -161,11 +161,13 @@ export default { }, voters: function() { const nomination = this.session.nomination[1]; - const voters = this.session.votes.map((vote, index) => - vote ? this.players[index].name : "" - ); + const voters = Array(this.players.length) + .fill("") + .map((x, index) => + this.session.votes[index] ? this.players[index].name : "" + ); const reorder = [ - ...voters.slice(nomination + 1, this.players.length), + ...voters.slice(nomination + 1), ...voters.slice(0, nomination + 1) ]; return reorder.slice(0, this.session.lockedVote - 1).filter(n => !!n); From 1f4a37ab5cecbfac372b4a2f344555942b25171b Mon Sep 17 00:00:00 2001 From: Steffen Date: Wed, 6 Jan 2021 21:58:08 +0100 Subject: [PATCH 10/62] clear Fabled when clearing players or roles --- CHANGELOG.md | 6 ++++++ src/store/modules/players.js | 2 ++ 2 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b9dd69..f54c923 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Release Notes +## Version 2.2.1 +- clearing players / roles now also clears Fabled (closes #85) +- fix list of locked votes showing unlocked votes sometimes + +--- + ## Version 2.2.0 - added [V] hotkey to open nomination history (thanks @lilserf) - updated roles according to official Wiki changes diff --git a/src/store/modules/players.js b/src/store/modules/players.js index d1be026..ffec7c3 100644 --- a/src/store/modules/players.js +++ b/src/store/modules/players.js @@ -84,6 +84,7 @@ const actions = { name, id })); + commit("setFabled", { fabled: [] }); } commit("set", players); commit("setBluff"); @@ -94,6 +95,7 @@ const mutations = { clear(state) { state.players = []; state.bluffs = []; + state.fabled = []; }, set(state, players = []) { state.players = players; From 7b1a264498308253e9c9a84a750f820459aa0165 Mon Sep 17 00:00:00 2001 From: Steffen Date: Wed, 6 Jan 2021 22:37:04 +0100 Subject: [PATCH 11/62] 2.2.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1bf46c4..ec3e314 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "townsquare", - "version": "2.2.0", + "version": "2.2.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 6e62d11..117ffff 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "townsquare", - "version": "2.2.0", + "version": "2.2.1", "description": "Blood on the Clocktower Town Square", "author": "Steffen Baumgart", "scripts": { From c3fda872b5d06e57dae4518118c511eb14634a1c Mon Sep 17 00:00:00 2001 From: eddgabriel <70332435+eddgabriel@users.noreply.github.com> Date: Thu, 7 Jan 2021 14:20:09 +0000 Subject: [PATCH 12/62] Update roles.json --- src/roles.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/roles.json b/src/roles.json index 7bc7d95..078e33b 100644 --- a/src/roles.json +++ b/src/roles.json @@ -1,6 +1,6 @@ [ { - "id": "washerwoman", + "id": "pending", "name": "Washerwoman", "edition": "tb", "team": "townsfolk", From 873083b8d1a6decc5e6256a844a85a8e9c5da650 Mon Sep 17 00:00:00 2001 From: Steffen Date: Thu, 7 Jan 2021 20:12:38 +0100 Subject: [PATCH 13/62] clarity --- src/components/modals/VoteHistoryModal.vue | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/modals/VoteHistoryModal.vue b/src/components/modals/VoteHistoryModal.vue index df43c1d..e9ba001 100644 --- a/src/components/modals/VoteHistoryModal.vue +++ b/src/components/modals/VoteHistoryModal.vue @@ -20,7 +20,7 @@ Type Votes Hand up - Passed + Majority @@ -28,13 +28,17 @@ {{ vote.nominator }} {{ vote.nominee }} {{ vote.type }} - {{ vote.votes.length }} / {{ vote.majority }} + {{ vote.votes.length }} {{ vote.votes.join(", ") }} - + {{ vote.majority }} + From be89d51ae639e8910083eab6748735eab1ba7549 Mon Sep 17 00:00:00 2001 From: Steffen Date: Thu, 7 Jan 2021 20:25:12 +0100 Subject: [PATCH 14/62] added vote time --- src/components/modals/VoteHistoryModal.vue | 29 +++++++++++++++------- src/store/modules/session.js | 2 +- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/components/modals/VoteHistoryModal.vue b/src/components/modals/VoteHistoryModal.vue index e9ba001..4af0360 100644 --- a/src/components/modals/VoteHistoryModal.vue +++ b/src/components/modals/VoteHistoryModal.vue @@ -15,31 +15,42 @@ + - + + - +
    Time Nominator Nominee Type Votes Hand up Majority + + Voters +
    + {{ vote.timestamp.getHours() }}:{{ vote.timestamp.getMinutes() }} + {{ vote.nominator }} {{ vote.nominee }} {{ vote.type }}{{ vote.votes.length }} - - {{ vote.votes.join(", ") }} + {{ vote.votes.length }} + {{ vote.majority }} + {{ vote.votes.join(", ") }} +
    @@ -96,13 +107,13 @@ thead td { } tbody { - td:nth-child(1) { + td:nth-child(2) { color: $townsfolk; } - td:nth-child(2) { + td:nth-child(3) { color: $demon; } - td:nth-child(4) { + td:nth-child(5) { text-align: center; } td:nth-child(6) { diff --git a/src/store/modules/session.js b/src/store/modules/session.js index 152eba6..62dda3c 100644 --- a/src/store/modules/session.js +++ b/src/store/modules/session.js @@ -72,8 +72,8 @@ const mutations = { addHistory(state, players) { if (!state.nomination || state.lockedVote <= players.length) return; const isBanishment = players[state.nomination[1]].role.team === "traveler"; - console.log(isBanishment); state.voteHistory.push({ + timestamp: new Date(), nominator: players[state.nomination[0]].name, nominee: players[state.nomination[1]].name, type: isBanishment ? "Banishment" : "Execution", From 072cd4cb77384d12774eb46f070e3555182ef61f Mon Sep 17 00:00:00 2001 From: Steffen Date: Thu, 7 Jan 2021 20:25:12 +0100 Subject: [PATCH 15/62] added vote time (closes #81) --- src/components/modals/VoteHistoryModal.vue | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/modals/VoteHistoryModal.vue b/src/components/modals/VoteHistoryModal.vue index 4af0360..7550e3f 100644 --- a/src/components/modals/VoteHistoryModal.vue +++ b/src/components/modals/VoteHistoryModal.vue @@ -30,7 +30,9 @@ - {{ vote.timestamp.getHours() }}:{{ vote.timestamp.getMinutes() }} + {{ vote.timestamp.getHours().padStart(2, "0") }}:{{ + vote.timestamp.getMinutes().padStart(2, "0") + }} {{ vote.nominator }} {{ vote.nominee }} From 5d932780cf9acd4e075bd856d99ad1e52f24af9d Mon Sep 17 00:00:00 2001 From: Steffen Date: Thu, 7 Jan 2021 20:37:50 +0100 Subject: [PATCH 16/62] bugfix --- src/components/modals/VoteHistoryModal.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/modals/VoteHistoryModal.vue b/src/components/modals/VoteHistoryModal.vue index 7550e3f..8295ea6 100644 --- a/src/components/modals/VoteHistoryModal.vue +++ b/src/components/modals/VoteHistoryModal.vue @@ -30,8 +30,8 @@ - {{ vote.timestamp.getHours().padStart(2, "0") }}:{{ - vote.timestamp.getMinutes().padStart(2, "0") + {{ vote.timestamp.getHours().toString().padStart(2, "0") }}:{{ + vote.timestamp.getMinutes().toString().padStart(2, "0") }} {{ vote.nominator }} From 84f73ceb017456456f4875701fc698be443ca235 Mon Sep 17 00:00:00 2001 From: Steffen Date: Thu, 7 Jan 2021 20:50:59 +0100 Subject: [PATCH 17/62] fix copy to clipboard not working in firefox --- src/components/Menu.vue | 13 +++---------- src/components/modals/GameStateModal.vue | 9 +-------- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/components/Menu.vue b/src/components/Menu.vue index dcb53cc..3e02702 100644 --- a/src/components/Menu.vue +++ b/src/components/Menu.vue @@ -238,16 +238,9 @@ export default { } }, copySessionUrl() { - // check for clipboard permissions - navigator.permissions - .query({ name: "clipboard-write" }) - .then(({ state }) => { - if (state === "granted" || state === "prompt") { - const url = window.location.href.split("#")[0]; - const link = url + "#" + this.session.sessionId; - navigator.clipboard.writeText(link); - } - }); + const url = window.location.href.split("#")[0]; + const link = url + "#" + this.session.sessionId; + navigator.clipboard.writeText(link); }, distributeRoles() { if (this.session.isSpectator) return; diff --git a/src/components/modals/GameStateModal.vue b/src/components/modals/GameStateModal.vue index 7cfa494..2e3d0dc 100644 --- a/src/components/modals/GameStateModal.vue +++ b/src/components/modals/GameStateModal.vue @@ -54,14 +54,7 @@ export default { }, methods: { copy: function() { - // check for clipboard permissions - navigator.permissions - .query({ name: "clipboard-write" }) - .then(({ state }) => { - if (state === "granted" || state === "prompt") { - navigator.clipboard.writeText(this.input || this.gamestate); - } - }); + navigator.clipboard.writeText(this.input || this.gamestate); }, load: function() { if (this.session.isSpectator) return; From e3b195d3e20c9ab0e83152d0dd0c0a2d4f93e232 Mon Sep 17 00:00:00 2001 From: Steffen Date: Thu, 7 Jan 2021 21:42:28 +0100 Subject: [PATCH 18/62] fix race condition causing audible countdown --- src/components/Vote.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Vote.vue b/src/components/Vote.vue index 905b43b..0c91994 100644 --- a/src/components/Vote.vue +++ b/src/components/Vote.vue @@ -180,15 +180,15 @@ export default { }, methods: { countdown() { - this.$store.commit("session/setVoteInProgress", true); this.$store.commit("session/lockVote", 0); + this.$store.commit("session/setVoteInProgress", true); this.voteTimer = setInterval(() => { this.start(); }, 4000); }, start() { - this.$store.commit("session/setVoteInProgress", true); this.$store.commit("session/lockVote", 1); + this.$store.commit("session/setVoteInProgress", true); clearInterval(this.voteTimer); this.voteTimer = setInterval(() => { this.$store.commit("session/lockVote"); From 7b7ff15cf603f53152c9f546e938f643b3886e43 Mon Sep 17 00:00:00 2001 From: eddgabriel <70332435+eddgabriel@users.noreply.github.com> Date: Thu, 7 Jan 2021 21:59:18 +0000 Subject: [PATCH 19/62] Add lycanthrope --- src/assets/icons/lycanthrope.png | Bin 0 -> 34096 bytes src/roles.json | 1505 ++++++++++++++---------------- 2 files changed, 687 insertions(+), 818 deletions(-) create mode 100644 src/assets/icons/lycanthrope.png diff --git a/src/assets/icons/lycanthrope.png b/src/assets/icons/lycanthrope.png new file mode 100644 index 0000000000000000000000000000000000000000..e72f8b618802f6c6c921b4ac0c1e031116bd51c1 GIT binary patch literal 34096 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

    5zd_9>Zw^SjB1T>?{+u7`Tj@&V$!`TwB zQxtTIUOVszF(-zN3z!m%-&;LxmVFBnll0S=TUkcWPB%3y3R?(T6lg-E@bTGQp)Pz2 z?#f{4r{~6_N;$Qxr01wH<7{xLckpHXkidQreqV5DU&PTBL~HUsM+eO32pbAtr$d7&(^=%Zyc2bItWxTZb7HmEio-y= zekVxl=Tp*jVxZ-g;*=lz{pinjw$z7i)d)?Xy2=oN7#2eIdp#Uy3akO-`ga(Stk6ot zNdone%2F2F|<(*}^&DM_d(0nMEb2XQgscyad?LIv@|y^iu| z+~4#?5{)n$fSGMUkl*KgkB1Kik%A@Y{}>mua$ggC7_VIN9@fz1xp*=cllLGawNojR z+@-oXEm6eP7KsJv$tRzme66eFr@mYzb;)R-I-K@BT-}S=iyBLwn(4-$Bz21kXHv4u{PVGplufB-%xjD{G@<79QfTF~7Eb zV!mhWubapJ!O3)F13oYP$7{q5gKd7mXBH2_dqo0E4n(aL=)zVaQqwSUu2ui}Dc3HE z&bmCf-4*_8RouL)BlemnZj9_j2u&ecQ)o90YvFRvvjt0Ie-3`b7N!{D=T z47ZA@#u9%GXyAxat)Cvt{0_3z)J{?BKVfG*CXRzOmd}&DbN!k)j9^T0M(s%qqCwQX zY*fogaEu}dKZ-kA+oW|1W6!P$KMUugLvM;yOI^b7UtDB55WjEq{A~5d%%hy2uV6Gi zC8zQ&E^DGRYwRQIJ2!`h9c!780p7kHm$8^qYrw8xe5D+8#2?4@2}exU-yPMP+ir(Y zr=Eq2RDO=A#zuspEnV^e!Ci-lJz#M1;nU!vm(ed@e(L4>kJ~Gn&m1sbMukK66zn6i zF+P}T#8Br(xgNfdgs{b>%cKLk|~T~X9n_dI|f z3ZRU1j-WJ*0161Ry4{PZ#Fa)kBP>TlXZlgXCsCeFaV^^;Iw<`qlJ*T%MPGcoX-%EA zDe$FFz=1?jek+7jcM*)&lk@@j!#<1gjtHg!*vy7^bo(|~Jv^ATk#ybdL+U!bbVU3# z{G1f<%3<$`0_@bcB+-xB)b-TqRJJ9-@WZuPMtDhohLz(v%k3GM5-JDptUa zda@rHi84_5BYv47(*{&Df)=_)caIHgQXFF+Qa+zg))687cZ1t)dd5{L&d3SE;@TeA z7#q>#<-W$$G`#We4-6 zAPn;b23f@Lgbu&1Ftp?(5};~boGQQaD^ ziL738wgC%#(k0Z8P!fXwtQAvfR2P9^9GXmkh>ZiZjrdK1gxLA1YehbpLs0`ZBXS+=32A zlSv!6jLZ1ds?HjC`cBLzaM@y(bmrDNf$QOqV6~)~LT1GPnajO~OGJ*UO6X@MP)-;) z3)O%ina{krLpSc!Ul~V}N<28x=J>PCM@b~81?lExc-911qox0Vh#LQ37fLp%v4)5{ z947Ju%MRUkjc+cUi!S0|=Pe$S%lFf6B+jK)X`vFlK3)%+X)+%gfx?;O1qFZ?d#cxA z<7@256_rAUqWNyi8t%^xy^2Ipc#PsJW|m;AXJ3zMponWjCvzk+h~ba4S7oE@d1XI_ z9<$OlU-@NV???XXpoSP7mqG`^k2I$`0V6pn4S>!2{yvX{cgQd$NIX(@M?tO8Dr9CJ z&f)t26B;bA|7~P-$i+W+0gs%V{6~qHo!yTrmtVc1-K?F+=4;Wq5IR3I66px>wTR{i z1NyTf%gt7271zz6``CSh(=T6;9K6CG)L$f%&n|tpsdxiF#T-z@W{M7S#Ej`!rRi=> zC{emrD=GQPgD#B1nqzSVJTu0@9~lSZ@uwDfFTDWB9ed?ruai_&{@2YaRZ&MK%Nos06tU0z*Q$4yt{ew-GA6Rb@)-Dj< z;EphhsSuXzcC>$G1|WJ8i3LMEy2SJ43Oz_afg1Fu9I-!>AT-D%ltd&9`Q47+g&prS zN+i3HCEFOtIZYwl0Fx%a(YMR0wD&SwUCYk)_POSGa-Lj?;u)$tS zZf7MWMkB)_j*?OB_ZA_GlTVPBd%gLJ%|Gwfl=OTV{EfWT2ItIFGJKEVyXB|r0igLiE zTUXw-shm~%Q%(Za(9K;fcQiE$P?)5SvKwYDR5nclt|b=}iiL$Y_svI>1xrM>O;{*V zvH?bN69ot3*>`LoHO-ut5jn1~3m}pIm^B|>5x*R6PO9)fFbs!PhI_5Z&rVbX-twgJ zJlPkPE+yf|6!@@T)xxgvFGS#&Bh#|g2P>gob$!L+ixpKyliI~fuIJsSrIG%KteQlc zGV%;poJ$Pk600hzKx?a{C=H-hsFCQNzo?$+3j*lWdpk zd~YiZj14R_O9=t_BZk;SU>*VStPU?wX9qq3MEqy1y~r9AXX9NP(=SFTxigv*jT)u; z7P=80-H>|f@UHY(&l9sOY{$8b^dn94UH=hNTPU1ndx8rHd1gO@QuL)|mHB?-fD!f$ z&Lo$I!iJF<<5;F|hz|d zGtZtE+Lj3h%u11^dk_4FZ)i@EwUI`yWD|vE*>6O7Jlv6KiuCzg^W8^_Zh^(l0=?`( zRMRW4QqRC^n-SenJ@24c>X3eQp#v*4{A_os>#etY@3PWLxbx34tO@q{{bC$Hp?W@@|@qCt#zm+bos#8-$lsmA#q3D&OsP}u6Bl97*K zqFoOBo=z!n3Z^#j3sh;MT;H3qp9bd|N;um%}l z8x8;uHHkT*1nNc@{$G>?N_2@Be#n*4yb|1QC>PeLmmJpO;68WaC5@J-W{z#*in`9@ zto+*xy~rwV86=br+Tp$Gfd&H>eb^EHV5`*5wr>+rC+Jv_InU*jZ7qcQSM;#>=a4bN z84DWBwf`GXhm+1iW|ry!p{7c}RcV_2_K?BL4HSe;zS@mE0~S5J;Pb~ukn-~yo)1vF z2sQ#ov=&^3EK`rk4$zbA8nqFM}Ba0le$X7W22b(aj z-Y{Bz@t?ZFM_^wMnh~pf5UcJP>kmX545H-ap(5NdE`}PRxO4d#d8KnlB!KA>euLT9 zq!SY$?U`;g@wbOX$|GwCV_NQ!g-aU^6~bXa-@uXeUmoGi&B?zu@;qW~)=^m_ zD_bI^_X6Q7^^Iy?i)=V-$9VphJpH|`;t+~7Muj@&n+yoTN3tVVTVv1kfErrwsFw>6 z60{%XipC{%h_4>V6o2_P%9k4%EE_Bmvp4edC7j@uUNM-_ZvU-nN0FOHxFxspXjH(e z`<;?ug1B#?y@TW!+aN=mo?|IcGk7TJV7Qg7U9)j5ThfPAvK5BrrVT6!?YDRnNlod) zOxZ?d^dJKL%~{`l$8yNe=o>9s#0T^G-s3P5WN5qd3w^K)=X*t$-RO9AGylM$6=j~Q zrhRk5#{QAP{8KpRuVkgw-S%|vgRWMW3->6uzJVN3Xko5#fjLoPJ@153;m`&TSJg68 zH;bW9dd`Q4;Lt0aF5z-PLjG9cx^SK?yutM&wfIZv4%t|&`qQ62qZWLWw)G^NmyF3O zw#g9~5nk=dORi4z?wj}$lA@kO1P<9(Le(+VTIjHX;b3JG%q=(1Q*L!<(z01CCau2A z706kW*qCNYhRB6We=~`1|&OE+EwI}1FeY{n*HF75qiN$XaAflRvXPd9ayBl&lWc@QV&3&;G1SwOme5w2gZwX-_M<@b zupMXBpzQd=+ePT@CgPDhG>N%e6&+c!Vc%KVN%47X_+&e!tSEcpQC-EBNzz^bw)G)*`g2d5XmP?V5Z`FG0H-9v;@NG2h;8DR>5SCle$=9`xk>$G+E*FWj%J+!zR3s<^2EiC1om(9utHel3sg`ic}ePgrS&R5(1< zm<{NsBoMi6DBI0rF(sUwocOCzH&@9>6`$63=}upr`tCgpDnm9!&_|e6010K7tN|ot z(g#xI-LnFf0a!8o0n6CJ>h2J^zN_0JOtsoFXrl4N_7BJ><0q9iTVI;Jam-;J<;{c}YfSbD#3zZ)b_3U2 zIJnlodK0{#EsOr1#s?0XxnxdpJ+yP3Q^e&8*4mS2ryGrbntdPv1a=(+69Q)N#|!s> z8ps9ATAL#S6`KAte6a0k`~1VLLWJe+(>if@9v(FP0%2}5;toqqjV#)b$1t{NuR@8( zBFkVR(?&CW%h!~FLg~U9+t_=~QyzxqH}~#mbC2#FUs3RuQ`4V2r!9mr=QqQ$^;=Ju zJBqQI_$QyrS(2~8WbP~9r&Ddt5)E-bw6P`ikW$xCVA@>#;tcsRQ#ZyrgiRT>mwRr2pXuW{d zOu*#})9!_d+{`ClL{dT+gfE}C%1e(AlEF6F+!)q7drnJ}_S3#y4Lx5G;1xo8_brKSzP=H-q1 z{t(&52fMTtx*!=cEyDak>Lis^xD62K<6e6S z95kyUo+bqT00EEseO4kmUI@IN5Clf@f98qga&Osc^idx;Cm7wfmgqA!GUB zdv=y@&mFZItzV%ZqJAlEHac3*QM<1m?Zp|kc@+=@b^Nq^4jE^tI4M8qJH|4ej^AF* z_e*)KE7(jArze9wOf_t7J9 z?h6VSwwPoY0C|(1+DBoBcj63e%SSEH1KZF6@n{GT@D8}kot$nv@@iL1`@om|N+ilt z+;c<85siBaue1feqjQoqegI1~NuIt${jAsWpwPjQXSXvR5RZUys>J@zcsFoLXeI_h z8@C=6hsA44ZqwPWq^C2r;fx{^Gv7H`C>SXsnTs3GY%Pq0$lwKBj$7kzd?-KdoJu+s z92<~op2^bH95Jb>WO6Ry)}cU|`j<|+Q;Z6OJFhxU`5Z0R!vN6`}k^sv|RuqVz<;3YF;_2(e>jb)WP6Dm(c*5zh^iNv3#T-ZnXvLwJ)f+$cMgJ zerE${*s7uFNDlMSxa2F)j>PjZt;Xh-}^GKn6X5_L%LrezZSy-nLj0<}t7i(%&}uK<2ns-iGbY*K zHviO31A(T>nU7KfBtl#e3zc_#(UScvybCY?#pY{;>@H;QF_6FY9fRLiGt&zHu1kD6 z_tjGae$Du>gw|!~!X;Q~!m5Nd`;uF_J-6=oVE6{+HwumfxyzL=Cck)&C8Z_Aq@zlS9Ex2>Mw zc6}SEX~pk*4F3Bv+SR{I_WZL*hU=W9X;5M+igJk~`BxHy6%9C3a{z> zXs4|w?q%Oc%B3Ujuk!Dks7`78Ejk~st}9ahX0-SQ`Z%8cH62bW(x@q=72&60DZuP* zF+Li?EzLIHgd6jtCeMQ#1u|;P98?}%8`Z^tZUUOhG`n55(?gFQ2&Es}ALC(f3BX9# zLZq=Ssmb6^m1HqvRx^869M-J+xLy@C=6D6+o3g(6a4V;Vg z!%n;@uekw;!Pd(=GE2buDFjGMm;*9CQAKJfE2^bL-p6qRpC56h_+!8>pO~O|AAwzJ z?Ql;XV+;f;*)uIsP$Ee+f8K5Pk6&(47BTMs{)W#!2L5Txd7Q*Q;CvQb-ggjdy)M$? zC@s26R9NL zhKAQWKUnY0-o!VL-}X-+rZ*WOv7_x zzvhnw-7SF2Ul{qko}$2m9c1GU*mo~hl*p~I zrQCo1pu(}&cN`xmM~KZ;*&m2L7^EIngXCvoEWTTyOw8yk{%v&Zx*daBCRa8{dFuor zMKN`^TY$)l3aT1_t>AA)pYD1+cc@COnfwQ*hdUOhXTPFpc5a>s!-g`^NU3LPiYz;eCT;iHX0ti!xFj@@pg#wK&BuUQnovKs^;lxRR`KP&(E^*M8LW*zY! zA9y@ntS&;`SjARj=)pgz2HQO2zs+pGo$Y?OyFQ$Qd^j^`?^&sJeVXv~`7H_v#UUkB zXwUy}No2QmhWz5@7%@!OpD9r#g$P}(6~1o&@^no4k41j-dF@XK1(F)!e+K^BE9UgS zG#pfjJ5%w*iap5-`DAD&nJ0#>Q4X`c|=D)9T z@uEFw?Lg_#U|d(Hhk0`++y~`rhl(xg%Gcm5d@XqHDcuirFp^i8Jpc(SFNE%o4H>^l z2xp3OiqySdpZL>D=v86ChsU zFi#}b)6do#+LIxr@S@Xu8s$NL`+dlzNv+^h_&2-7r-5!L;!(5(EAX>soOAk_ORni= zhH6>DpOLfs>)l-qyc^SyATtA6)%0TJg|chMfWL`)mWO>?#eR_-0bTdv5BYcs^wr`R zy6ajYJ|#bOa+M`;FMy-|+|6BaV@l`}9sN9~ccdeiU2K z^QH$|BeVB28F`bu?+kqOvNfK!NZE^=hERV;h0q?XU2jHBy+&(*IBhR%wgglq312;cnXCN0NS+RUpaF3E8;+$bFXeX1o!qOP8wFM}!VT8(;yT}sk= zn4L7lnQQ0<@o_Zz*2&+TCKFSN#Sz)q4Z2HpChD~$UJOWZFQUQh=D#~79zs_90W;X2 zREzpJe4d1x?XjsCz#naO_R+%#kwhGGn#moBE?<36Kn-j^rxio;Sz;|and@UK9C|p7 zFut#Ix&64^Sf9FjG*nZ?F|>wNKC81S_EgG5XY(Je4X%1E?g&dfm6UuY_rpA)@es10 zHzUg>i`Nv^9hTSr?zB&sHHFV;+cO=C7JOs5KlBFU9S^=rB>o{*W!NpMIeOnYd6ku$ z%UD1a{E3$!q#u3onZAI^#NOy?1=G+=&W(>ha9E(=8B*N6k&pEko^|AU5Cda}d1@qM z&nczc$w7=D!IrJ(a^?KVY^KCf+q+D4mLq#6^2&bt3ClA~Id)b2{0(u0BxBfT8MD!O z<5YdRToY0?>K47F3xkhf;-;JtD8fwViAd#&1h+z+F@m2z*Yq#FrI;QSGjt4V^6}jK zeok`>?UNH@A)lJW7=e1rhpoZ=l=?IFf05iBC$FRH zFP!ru;y>+g=>}I0bZ|J%0&BJg?!#}|gW#VXWebdQ+DR*gV7!`H`P60^m`IsyKrTYt z;<$6CgjI+{+#lr2R|cl~NXq?P243UP``3sy`05RW`@;WL_rug~GzH51%Lk1SRAV)^ z$m>DZeV`KgjHJbJnS4D0l{6eWAmOFUr-tr*8x;XhphWn@iGfb+cE2cI-Vj^e3N14E zH*<7vBEl$Puf6Tlxi~()nL+Jnha#HU+IjbW0^V%VD@y!48K_NdZp4u97JsfI(s`Ci zX^|QY;o;4LQRU1Cx`um9>J#i8#*VwdH@m1g+Im}!$PNaHau&GD?={GnMZFScMj>*N{^- zWf;>fT^1cPykDV{Q8h|^aV-LkqTA__4_At)4ytFzJKVcj^Iva67sC*3K8P{lb1T=@Wk{eLBK z@>DE(b9>eubxb4+)Ewoqk+6BKzSbLD-B-2iq~!=*PJ4V$5P8oMWahnA@n-v5{E1i8 z_d>HZ5|x}=RIJU%8&HMi%2rZb@ul)wm193Aty+moi}8#)i1zp>1i(}I693b{wF%@N zsb&T3S2UY+93f41*CZM0F#7c zipbOcCFd0GQbv6+4=US;D@)V@-f)pBPiYelTi4pud99&E8y&c6Bbm{@*^kMWhfW1` z!$|eXC^K`{oNf}C%B^D)Yr{q$$u(Bo0NQOaiTu~c(7z)YP8$(Yf0+T>w2F$KBlK#h zSxLmSy&dnryt!M!e;>AInB|s<1}2i8^f8JBIj>d;bqE^;uk6AALd1?uoem)r^Gu|oHcu%8A&emSeu$7J9 zf zclWlN0zbi-{;2Ye4us{Nk>xGpHyF7wrX<)R!3o(zt?EwEnm<-QGRS>9Lp@+0gGCmm zfwP?#3HSskA1F}4_pkh?In>`)Ck4}gQdpq&@msxbQM|PkA2-R=k;2oIL}CmdkT2gM zt07_kJgm|>`!31BC&bpFz3Be+t@SLs)%x-}reFGvNTaRnM+F|tO;JpbhZy#?P{@~7SiJYalDpu&Px8xc z?!7B4QhvObo1or_+MeY{!Q26W50<)ntr{0Wko9kn@1$DLC`;tWGl4OoQKG#k4^+m&JCGt^BHBYY zp;mZ5JgnZ)$SdnE_)XFjbk%Ls2oKV8&T{s|Ssmd+n&XovcF zIU1SOpLeR)SCee@J49E2iMf;YAy+|DR$lizhgN@4W$2oMhIG~GEL1W2a0dRz(NzYt z)%9T9iVk-M!`+K*IAb`&DK^}TyTj1IaMulYFYYqj8BpBahr`$R``^=>o12r9oaA{@ z7~^DH0`ZqYSS(wrm<=w(yru+!ps7Ydt(*RSiyR`t#-6f5Zd4jA7t{vxqe$=9`E@Uku{@9yO$&W)Oa#LvmDP47^ZJ`O#l$(5r!xM@CrBtjLRw zdOAb>;%TC6vzx0|3n4L}nrl&1{m;T{C5!NSyjFESt_Wx({}akTjzHzRj#snd?FuhZ zj*L$cQOTcTg>Bd4IL%Z0$&0-1FH$9bJBT%Q&3nH0_|C50cC`)Ef05Pry{;wv#L@hS zfCTQ?rN#9act~0I*!8iWu%9Ln2;f~fG-70UD*xR4YA}EKHGZ7)XCKXZH9TfDt6MsE~ zlc_ObE+hPJOt6bt0(a!fgGP@N8b!TMYitnmd5fym4@r(JAZGibbZEKC3WnwvPjozOo5$Tq^fPygKS2|`@(*qMyQ2}0IjnW=!jRV5^{oVdS5 z6B{qiub0LU`L+ma0*~<<==-d0SPcq~Nkqpr;Ye~sLAh-4vB4n4GlN_7#WKS4>P?2* zOmb|8S}uQ+>T=x(hFzm4k%yqd?oZUEj;y>UhgK)k7_JD`WI`quw?S!=Ngw?GT%RBx zn7~sT=SVeCA-bRtBgp*9GUqnp%Yivfml~9)ie4t8j zW`)X9SlX^-g757yt>c?!Qss;I(S-aS7TCB)yzUNb!SH1H z#LOGZOk-Cp)`MDt=Dy1FpGjha<~GBUPtFI|7A1|X8r!4i{T8Qy4^(m6KLIB7E@f6-ROu7VrYrvR(`Q4s!P)+PcVC$YapHVGr7|$2 z38<^3@MYlw)s5?kJSimteSGe*zPMzPS)T`29~ zTc9o{vjeZIXwHP3PfIA&OsF{`VEK(S7RZVNUU{a&xN|54yh2lw$bL!*Cx@z~GT3%f zy#ATCDtYSIhdtbRl{vl_4!ha-=M0VddEjtv!9*@mzrk4cgn`T9<0xHKNKx4ey_%H@ zB?ROm@9CF8_Jmyzd9Bp_u<*dM@!%Wk(pnI*;rhN3GwW-;qKNGT*m8|wF#B#0ghHID zKrErRhAXUVV65R~Ra-*>HN|3?>*wLP?6`t^wp0yTpy}5R6zrj_z&}SG6agdtXPr?N z1U#K^gow>L?);w{l0$ehHW7^vhjgWJ-q znqJ2xUv4woQgIqOfiDPWKb<?cgp$|IyLoM<~Qg_Ts?vl$Ve1)=K zN_}QqZ#YMhy=~pm)76JdQ##ntt;ne%IWqq9O%V#8Z<w)&k#&ins!-&;>O4k`t?rw0~JzbF4<}>nK+QIjU+BVO@jol?}E4i*V5Y& zWlaTl?bw(ON&+X1IY2}RM{s(!j`L=9^9z->n+VpX z+V0LZU(4C)yno-k$FAHRFI*pU3`mNOHah=K{)&~)sW|);2QR3Df(y#xUqlHKo{)FS z(z`~ve*8dDw;bOfCZ_a!oBA0fxEsS|9t|RkYU9q$U&ygo=!AE0jV1Ss_3@+1Y7X*D z?qghg`$bKK4n&wioMABUujp;b4&HZ^czpTkxlA=FT5e>}z09Yi3zWZF+^1}Bg z9P*ycIg25-h6SyvcN#%kmUcZ-qb2%g7B^~Q{8}H@N_%T1aWSTf`j-DQXa#ZeB@l{9 z0jUr&^TiJ1|1PN?#uSHpn&4oxGQOqq0^Q^!?km>Pv)kR0&uHFHD0opSoc;C1(xo@} zv(W7Cxgdr1rjjJDK9am6rO$O{efAGDXcNH?E@G-6RIv^78 z0inJg%u!o>bFMv962?JzW8ghKS6F?(2Cg@U{aFk9%F|Ek;s$!kKeuos*f2uFesaxM zA4!$Y8JCgyhp72`J)!kQ&rEyWqP6~_CGsV^&Zs%d#oZ6wM263ARR*xi-!Nud3$%?8 z{0nSqxJcYp!KU#`cf*xCY45SmS8B#*{Lk*!;FQ1xWOPJj=Z4JWI$Z9naBnFqbv0;L ze&f#kb{bh@oc7z)N8a!t;W|x~+5TccXAPscoe^T~GXt>Y97EriI`k+s&_Y;n=^feu z#;ouVT-EfZUOjN3RAdbufp0sVJ4IwQc#_RoJ1_c`TQvN9qzgXwE>q*!k!UbyzXc*H zw|5dhIS%b7Tw~bStEJAAU#x2}4BP8QR}s}<7-$aT=wyz1b^}%mwu}?gRF!X>`0vluUO0Xn<5RQ1^p4N}KuMx=XV|}itX2Eqj)TTKV25@TR zera2I@P*h349d0S#e=^L=EV2=7>1=@4l;$jIczSkI;y%~ekyU^r8W&?6<7mPD zI{7A>%>8kz1d6QdpGx>A4ZjXWsms~5k0vD;<_(QVZ?M_knNCz=fM~wg&l)bdl<(QQ zz@o4XIS{Rc8&2LL#jy1d0l?@bzd#CPW(=Ho&XikVelxX~X> zb4(9(kJooG1YUDo4{&eZ#EDmQqH^5H&Frt!GXy9=o*}cohn1B9GrDOy;GJacGaHHQ z%qKFTw?cM*l}7;`t%Ueq^Ph$Qnn+t!iL7AnUjvb!l4-kN*H zZW4s@ZrmG%xcFugFExh=I`Y_dBJO(!o1H;epj%ND4Mm(?`2lwxcYQ*u!P?ork@n=a zLxbhtO?<;QFMk&_AqT5Q?({*_F%=qS@IBHK*7qdyx>D;N?by`NjjC90AkAz4it~1n4?NMF?V}* zNMbGfW9|3bPUMHHr6s--JRfJ3Wpk!zGk6rYyxS4^Be!g7SX;B^9DkrPx_==&#Oe9- zq7vNJHI`w^%II%-{zPQ{z_me+(3MB1{Y4RCt8FDY}X0{Ita9lX`tyuI_bhGtB_D#*EFF zX|({UBtClrv#fQWnm}*+50cAwP!K%3C8Bl92GgH>ey3QHarqAt4I;hx@x=sM0}BqLcQQ{roLZcHwg3<@U}Q(9S4wuGu0%l3T^|2UTEl8JoPvlkX{^GnToY(k*=1&O3B*N)*A_0XvsTOv@=)|ir0 zIBw?BTOlv<8JjO`+Uxo4Lv4VQPwbudjqij6g7Uppv#%0f=}JN@nf8Phk5KUjMdcrD zrB(`Zs9C+}nSjh8$1E!%WEDT3Q7*66C_7xZP!*Y&&4jWj%bm8d6TM8-%VM}_a(so( z3`M%hh&iBvA}H3Q5yGVoY(v(=$PHeYcgcz5v?9XMXFh)UK;7W$F>o0?Bk8YjoV{DG zZfSY6G=f7z{fbO(^l*KakQ1W!?TotT(hxOA0&#h(d)0ZY44HFg90-|Pm%<^UMWZQ@ zE5_ErWR6r~tWMJ#BKpE*Q2H1giEI$Xk$xPjMWQ&}K^Ab& zP^NGt{YQ8EY93`8<17+Ho=?Jc~n zD6fG!cw_J2w>Nrbd^ZweW@m?<^L?Cuo$Fa(`x~$sP*Cza)rDP>P&htkZC(L{zkGkc zK0m?&pzrj#?+$#Z#AzP*Qt7qn=5U4I_;1(I)5dV6({~dUf_Io*nnlG1^JmyR3v0k_ z@Th*tklW&eyQQ7|2dfqt@e&Z?9g_B1;0Gj2L87s1EN#OxdRWrlC#u4KcUZ>woK<{- zWOasYG0tMfh9w!}hpYYAj1pP5x#EX{66w^J#uwu(r3;x5+?rCL>N9a|+XdVm9xarq zZYw|>s0RJl{x;rx#n9IUULk_cNjFcJzs*oTiRuHN8#mk?rI~&%N*Gu@%*g@) zJ?~_l@*OCYHE{KtwoygtZbw;D44{bh(WHckMnBJ4cLk1Vdg<@v*+y!qRI8=_0`Kr? zGJr04!~u*SJYon!!C1*3m5l+=K$`YN6KC(uE?FAWNQAb*u{)Og>d#{cHUj(}orHws+C%wnsz&jl4 z!(z#I52`y>3_GNw(9g&=qoUY79Ec0q9UiDZ{6B^)BS5QAQf+x4 zVPz(_boxGv-bm>FNPW{3***+z|HOF>VK{BP65vXz?G4B)jCyfkYDc0~q;IdmU&q8` z;0?N0N%WJ6z-BW-xh5eC1aWoy0haGRIu#QYh zY!&?6*a`hp1BZ5N-Y;5cZVE{=!8}k(_rSyEj1K;}!x-Q%m#r)vo(@5Tkk9zR`%!u< zrG2I0z^4m$Mv656mrY(<+HChtQ(l3iv#Gdew8f~|gN-ZtsQj?wf6>@2P+D|CaYWqH zDc<({l!eY8{YnqMum>+zsb{S=q(2#$OlF(Tx zrDVXckYkFSiphtJp&!6BF7DQAGCS!7IQu1)t!pMAR%~Y(Ry6*+r$32wCRm|!Jx8=g zZr|ayu<0&cal#txfm%MnW{UKX6HFe2I%;2ww)?GzXfL?Nzc7o|P&o??8UedMMCxy@ zH#UgOjw~tC7~_?zMJJ` zs22hbU-vs)GCVWUZI`169*%tbsB&_!kWIwX)95U!J( zjN$aOwDr8u&hk+oVyqYOydDL3mq=GrMt@`XlHaSsQio7Fe1Jb;hI-yNp}+Ci9weA% zY>v?6cihH#S6eR@HA++J{J0>V1mtN-u=I}T9pw;HM0#_EL^(3Yp7`1@JF6EqnVr)N z(jMQ+H@)V(1WvHYZy3Q;CSK^B1;uM!wuorCxtcz0Le_rKL)l#AIe1%mrj>%wA@9)> zp6|nkH0JHc;t98yTbY)F`|KqiF)%Tc+;oL&#UwxpV>Q3OQK<3Mxyek(3_y}sK1373 z{q4t1w%1|ZY?)Oji|g@y^RO?spdS!ciiK4rr1CrYE3)g~t_@fQ79R*IE#Px1%MmDH2?Ap>v;@Si7=7jzhlsb*Tp9unnJ+-!2FhKFtWL<52;xttO+M3)T1e-Ov4~IoqHfdwxdpDxs!+@4 z*lfCYq^6(Qs-my9mo!x>uTFjAAgSoj)#@mtfd^*;JmSPl^yy-v`H<|7uTL0w)Lfuf z4JxctUY@lj_M)3k&FmK~gEu@!sARV4oc6>Ub9*buK=@XLBrfXwxn9NKgbMGT3+C;S zYvLL{uDNFMjH1n*j9IF#Nb!OL`zwfvV_({+ip#kH-~036lF!#YTAM8_EV~A||D#%Z z*LTxHT`FcIMrE&`85cFK*3Po^TYf7lb-v7U^{0^LA4r+HTItROim%c4D>5Pm zPIKu5Jvn2fV@_gQPgAaTUc4nDyO^-%Bry+&eqdZ#E~+|@4(iSW-N>o;l5oi4oPRy4 zECO%!9$qO6PXGf4g-3`uQq0BDjP5T58sycj(AoN~DH;$M`$#NS+o1Z}6xklJnKmID z!Up{7kEf^B5A}BhDli@)jo zlvQfAH6cJGlvLmE?o$YoLwv*i;%#XWr^g-|^qqM=8We$sM&+frT06~Y#^?5Kb25H+ z)8Gv*tMH1aZ2SG4l4mU_DLPpPgnuhp*>W#-p;T?B*LLw#uE-bH`FtWqvNcQicL@d` zGx0{ymcm!kv@{F-tl8f_K7h-bRg+~G^!Ll;jv=m?L>L)Lwpr*k$;TXV?^p@Sf{oGc zrLC4^BY-zxON#W2Oj#_IrX3O!GwXRYcR+BQa~2<4aQ}@R=}QA1LSPyE77>xp|2J@#My5*lNrmW!pzE#G)cut#`+a3ZaJQm(JlGewMV3QXILY^1Bv=XZdC4i<`+LGI634o>C})|9Yu6->^Y zH$*G(u92$=RtV$r>iRk6H|L*IVhW5qMNOJKhULP?M;TXm3Ij-pPV=A>IC?u*vxXHs zD*gDA?*}g6YE|o?UxjSJa1+X(|yvOa*Osz~u^#6j|o0kGG5~^O|aFObZ{D>K7TZ;TA8_SY#`lDnHGA zdJ}cXoO=sv3oQ2We+?ze)+syu?u#^I9-y~$!z){+LR8jCNCB=is$D-VUn%bNV(PTL@012CEkEvZCk)aDI_G~=A@S!iJb~_G~_2e$(w51Gi zbj+<2Q8K%-h>h77-a6P_Kj-iN%mULA7|xK_lh#5#R` z%8{DhqmbFj5lV1a=Ro7EM?UzHVOH+QWot-n==;=#FywXU({(3AF%BMjc&L7LN)o_d zuF?o6^#~TOZOm(c^_KVZa7#)zP-5(qm^dfyU#6M*4uf@3Z@;GShOO5B{DRR1ur0q* zuotvfiyG~EDtsk6u$^kmJ?O-!Tk&bT6AU4c0^|4wN-4l&Utum9{Nuo{(%D=v9)<7k z2Zi2%ia0*?WEuWU$@o;`!>6|i8z1DXc&UTIQ^76%BfYz zp+RXAM*wO@@Q@8_@vDfv_3`|Ao0RfSo@KpDXby#t9;@d_C`r1r^4E9#RJCggL-Ta1 z;;boAr%Bgj?wr6u7U0bUz9FkwJ7E?>!;RC4fwoSyS-a0q<;86=gL8DASPXbVSr60z z-OqZX*^6UBTpa^sE)2;Cctbl47H)!JBO6Dg&*^$ zIP2#ptk{2+m~mZZ(!0bl75?0*^XZ~xemrqyD!XNMB8it8=e96L^SCx99Gs82&m)V1 zmVb1@G;F#|r1?^0e|2pkMPnuRZ5)e-tGz!5(|UB(Jr%B*8GA&RSato0?9edszcUKN z`iOJ3lX=^mp(+7ATlJ)H^hw)*C0^D-g>q90{aextiLdUu>7yNV6@fuo2MdHR`4M!7awO%7bR{pq(&`Y71-RxKz~40fX$_C6y&hWAdlASukGEv2f|{&)+izpGOj8Rj|IDG_hnU zkzRin@}r_k@r=*jQO*rycyzLPj&qXnOFu6Bul;W2ovxA1Cc*xWFM}PucdYlam8RgE zpPa5(^l@(Rd2l}}-gigPq#HyQd^t$#;%UTPtSp#6?=G9RMZiB$jxZr{@ciRTleaau zuAUJ0Bc&2HWvfE-EftldcAwn$M~nT+rgw~!UIx$fjoF{#>gGQs$sGHr7hfkG@T*iv zFb1V}P%lVT_u)k)vzGK-wk}zlM|mWjJr}agRO1(SDK&_>o9)M+z596#|1AvpsWjl? zv4441|IWhZ#xmp20cSOT)3cr)=|i%z+kJ6E#fhN$DN?b>R%wYu6J9@etl!_&si!J& z8n6N^ZAYZ=dk`Ey60J>YM%m1W4p?&mKPgV=S$^^BFG)+YtekUk12t-SYPvI%?|Z_xBrHd>EKS%3$Nd z=60>x;a8VukR#+*#z1!Rf06Ce98!jK*93^p%I;=I*oP(~W0@~SDo z0lS!k7`hYvvzmj;mZ*h$ba(s{+O9+gpmy!c3&w#rJ9a|thPM(q^enh$Nyd8SdTd9* zx^o%B;cns*oRZnrKQ^{FPj4E3Xc)SJm9~qDr5tB*6<36`D0H*3tW=e?BxTZ5EmBRU3Sld@Wf6~+==w) znO)q`k?iD`x59hV>oqK4=@%z?ZWldd+~{pGw|BsEgJ<1a#%p8XTpOI9pXBJDf~Kcr zej9Mktb##E+3i3*na98NSE;S3W_QkS>kIsVuS~^gA?Jj|%_M8~E1dG?sZO*1ft!Eq z$gTo=W|4E3yX~D`@T=9>AoHjRZe9 zslLVUt1@A5=&2t=OvzG@E#y2Ld{8wS$;PHQRdCC3iwUZ@W~#v&#=@G^fwk-)zQ&5% z(Id4xp~I;V2v^2zhEBh6Ae zIMIf~2MJOhP2IYOHRRel2qh-ZmcDllAC-9JVMh-lo4sN?zEH0BEP|F%BE$YVo0g!c ztv`tPEsqvdxK`${BJq3KuElo&zxB`X5hKmKZR}uXo+p=FDBCAEtcAJ;9VR4WG1ZdN zMJ2Eb?ijkowL)*^dEfzuQ)UNBtl+1|x15hg{_d2p1Uq-c)hkps(Fa=A=yRPFHS#+tu0wfy^JxzRN?W}E zP8(pqmZUxUh+MoTPeMam=XMq2@dTbF@)^h;Fuq#lfQ|`-Ampi84N;<{$CP1i-9^b@a#O;Qh~PT(Fut8|5tM)MbP!zJ-|TZm=)jGB zXFZRY1&rRrc6@qZ0#Y1HT!+lwacNwNiwXrR*C%l*YY82fxoX^Vi38>+zi7Q-m9@L8 z6vwand+fss4P)UKzgV%ah=7+V;oBsPr2YEjhJTl>ST&kG;@u1`x*vNAKO`2~`%ZIi z{wULHtFz`L=q7m{-!_*0z3tCSAVWZ%x=SU*x_09Hca>yR&)b0 zI5-(TKMO}__(&bqCZ;Hx`nS;c%6ihOk-z;`kgbrAlHWp=f+Bv30)>S2S{mF!{e$O$ zi{6JG(@`ggiL6wldV3~Gt@Wxp?K*pNVktm@k2~PjCjfn-8Cq>;z#Ml+s23MOsS7G? z8M!yjsWlmy6R_gp-^e5b^V5|mhg}9{4IOHfpuZl1a zl>;FK@A8NJ%)FVsH1)nk2V+cnj(`2Q16f95k5#f3<YDUcD=9%53(A*E2Nl48ib+4}D9xol4+o|4J}Zp_$t1 z#Ts#Du>a*14N5-cRrHlR8>E*u*J8{OH6)%?YN;LsCt?%bOOB}Yab{=EUD{?Q@?UW0 zX{P|_Fe-3GFS_pG+@Xl~spDXv(4+eNke_jTF#@Xdy`D{g`o5rr;}V=*3R(XbC= z)WmwA>Xv%W8*hW%LP2tK*CtOg)k`Yx@!9q1Og5Yp!{>_Qx}d%l$c84aCnySEdi}t8 z$htfg!aKo!4dcCHJyY@DC$0%2gbcyEGKs_5ta#Hxn^{( zhQ0_&7Imgq{&hpKp$}sJuk}!P)$f))*~aZ#1O5-ujMBl6>|6G-()vAa@|d1G$;aX{s!>}G0H}{qV_E)^yGszjz zCxcDBY{zH8u3*-Hu=1_4KqD;>NzQCpek2*PO#FbJ=z zTXUkLx0N``qa^4Y%UpQ-)8G29|IR#5NkBLX8B+*&NyD1tng%!h)qAWy0n`66@%mDW z!y=ZDh&#SpuitFs^O9nF8dnr(XI~+vm3IZ$$e>NphF4*LgzGtb+Meoz{JGPtN()vm zHdKH7VuzXT*O0T?s(`5CmRP23^Ykw6U$ju3JMqoKu^u|#QZX{_zB^%se`d*%q)dM& ztsI4qRxELgB^DIranA=?U zh+N6yQxP+D=p3bg35%q3HU_#ifk?Zd+-D@!-EL74rtv0xcMrQ0nd8w955G9q_XL!K zBw*(+YM8Dhx%-cL9jz=z)1(Wf*gupxmnLXsS!Ocro819Z@8Cu4dwxlL~8%L`9qAxS^w_4MlOjA>#I)-bmreU^4fd{hiuIL{LtF2y-Y(d+En?==v4nJ|YT7j4c2i)nz- z=!hw-5}QB8Lj*nhj$q)}%n4t?X%6KvqylTW=VB+2(H;Um}(W z%W+4uLhylu@1yO9Z4#r&v>Ff=IaQp3{5!n#-@cqR?_vBPwFepbHkGYuAFztI7}-@| zK&)+iJ&hdkN|{sw>AN2IhE!qZcO@Wl8IYGiIkw;Tk`cP!Oij0KS>E9&0=N>Mg1Ghd zMy9;HM*Cyh-!U{v>!cknlN_Bv(if03dsBpv@h4VQ*LK*XLSrHy{`aYP&rn(mxyG(Evu{7Yqa+crUT z5xykG#hX)90hIq_UH-glnh}Vzypx{g46=6uDHj}k&*?-ZcJ1)=qD0;-q@4zxHHfaU zGn1CJ7Q_P9Q{UH^p!K%l!Ky+3;myit@+;oO3FSADN3{_Rx9&o`H8&)RPn^3kh=P-+ zHSlEg(c_v(3|AC8ebeGo4KaG#f?%uR)3QYrVbv3hjQIYqdX3UCsv~lg+qIU8x7YyD zjil8Mn(Ca(*8Ok&>ij3ARum+<7QFdvj!eA+%W!NOjAjP?c#&j@DT~cO(o-&;Nhv)}l6EJSl&UwyiY+l71p47bfP$iYJ5|uhJlGuEOom;Sn+* zCKKZAio)hGh?*q(&(?eBY`_->L372ylU|Wq3sAGQ-IFJ?L;lJvJ`qh}zY` zi(ItJ7CH@I0Yb==f_K0Gxy;YMQH15yLhl zvJjkvj<8VFR;a?&hQq7fn#^R5q$i<@r{KxrOv+tv{n0EI3&xQKZ&BCUEjyG-A75ru zNan7NNzM`84hK)PI-n=T?BfZUNsWucrZ$^*(WU3fa8>*pbe7(Q!+#dml@+URPzb7dw)gtwvjtg=#0Y>pyu}nXEgYs9)X7wvRetf zRCsdVm_Rcj*Nq)_h&YUX^0(MNR7}nN66T7gWgWvYhm*#~ACXWJXxb5@iz$D#BuffS z8AH@H*+8l%1Ry?Wi`Yd?FpPIEg5#RX8KsbaUw%NhNXHPb-sLG|l@bio`iGn?@q2DE z8T8V*P*bV?OS~gpWDeaJdTgxmglZ zqtgGq9%7LA1{F+Vaox0>ybN?%nK9u|Tks4Cnj;c+`TT#FC8lpNsU-2Q-tWJ3DCDGm9VT@HcDA8Cm?FXq9C51a zbG|fk73v-i=DXMEjjrwu*yBQQr3JxsYop|3l52isBrv2Y3PMn~7z3IkY}zE$^grvS zc-|kKdSSf)hZq2~QT6vCe{u@I`1k}7{Km165O9!SpC+S0gqZ-m=H|t-!?3O{@gze$Wq`{5v1MFbbyx2^znBTCuQfkv} z!iyb#i5UYhk&mxE&O9k02u2RC< zdzY0}R3=fHMK)k+FwT%FrISa%PTlXnj#1N7m2|6yB2&p;^!|cM<`JQ`J(GeBE$J1RQp7uahsyq?FP*idIm6p>q&fKJqwfZPS3xT-TP!q8+!vdr zf*)UiblvQa0_Ubi=9yDa&2j((6Jk^Yx@63bz^3Z2_=#y915`4Y1+6Y3a_vMD3Z#-E~lFa$v06My>6Bh z7P!KS9z;4h93IZOSi9vYPc#T2N-!_5cM}GUZbG)djTMSh`jR#DJ+5aQN!-UtQE(5d zIRE|c+SN9*5N(3Zl^6{j}Kh_H!9d3h56~`*r0m&a8t2-$a7gZD=~(4x7r9;H9i0D z3sO@30ss)%{nnX}|gt~##p&Xjz{`Hu-WioGcOjRXSj{hHO zVS?}R_DKJ|f_f&fk9V|m+zA;K+=iS~RTFn7C2OR{eBFe(=Emg23^6>#JXWqiw?q5y z*J+;GajmrGYwXUJoRaDK#uJ8TXUItKRkYu`LsXjM7GZ!Rp3N&>7XclrU=Nj_=EFGpc(RAZ*6kend z|HX&wMUO2bf5Xz~bs)VSjOX(AkirY~paY{tK{s`W8f@h_hB&@Q_dWoCImBVa_EYm! zOc%z}T}=da@P>vKw+Rgo!82!dbKa4P)FIE8yHmRj|3xhCyBR***8aKTQ&=9!sE20o z&K%A59(nDJG*U?R_~5pb(XzAZS!T>+Y|jvU`j^B(C~EXR92>d0tp~O^2%@v90X7Fn z+(gj~ylW=Q%wk>5Mw49f+3++v4)fOLGUdf~NNsyYh&7wCj_=hsXO#9*HJ19%D?4rV zQn|R6>86e4CYOrzDP5A)KTxi{XjPyb#@Uu`4$+ZNpMK2*|5$~ zb^pG0oZ5_bLe`_4E5`@%9ZUgEB*c=rPS8e|Z*CY$lY~dyK&9-{vyV{xRhmv5Dqv{L zO2L3ZD~o-tx9d@$7{WvTox3q2Omk8aVnWge9abFVMX70jx>)TlvrDXA8|MyjO3tu2 z`^uxv1S8JB7q;hXZHYE}YZ5(3CKbzVwclFy4-C=2XXNHgdSA2oU(6?eREm1(7V{J% zj7Ejn)A`XZ+3*F|6E1HdMIrdzku$i1a#LSOIpd&%@^2uLO2hj@@1_0MZ9%z~Z%*OE zlU5vz0L=$}*10sTc`<{{!j4PaUFsk#@k7_kPy1rOuvs*Ue-+$fS=TER7(5%Y8@21; zUY$*+;+TQWLsnMv{!6h+hsQ8xIYeuj8H=#O_>fVvwnq;0Wmmgzh+CT>NF}o|Q^7*( zDg8ToB2xyz4uTrRiGOr+#@Ay8su5cL?E0nUPHMej*IF;6WSA7?;E-H@91^qqG8pr(g5jDC2CDtR^yX$j@buu;y^juagUnKv70X(8W z!VxVEAPL%3q`A2n` zyD|#B8<8_iBnM=8%Mc*Sm)`Jdpv zSZ-2hz26uy=U@klAx;?ZZn;D_V^kL=ZTu)&yS_s`=EaDmMk0$7ys+A+CtB-!K&9#g zJSohhlctZu9V`ZD`VC^VRO3!_$m#T5S`GV*Fk7zL zu1~_ByLcZv`5(J9F8Xuxm9`1OdX^z4L~gPn97G$hJV1dkGTN|Te4@=vWA~&D;k%ak z7KblCP!PWLKXBGl- zg6XKV(?a-$TR8Xfdv%j!E>YYbPybfEOdW2mrkN8bOgFgfOzrn!_7`1f)X6sw1d|J=ZP;SzULQ(DI- z@m%O4HxkI++}?<2bb}7#8&sN1n8!jifQvym%`{Z(y;f(_ z=swyU{|x+z%NWhgqsM#cbS$u^RWIi8D2&2AST8;T{forGgwhPm0TaAHqe(PNrkM+N zq%cy`;rtg=BMDOJs$7i1&mNhmyMSgzLHG^%yR1tUAbY!$EMKRV7TcKD=h)~CZ;@WJ zp;Ef&3s20CuJ1<{V{P|{hqO7Xx0GigcZPSFh&Twxqe?+o!Nt5rLhp7(%YcMpTco)* z48JD57zBvRUPGnu3S8e+eQb^qR0XxeNwCNiv0A*m&gd5r{8d+#(DGLD1vJH`D9?Y> z7FXeNvWFK%xx;XQwlO^0ZzL1q8Y=ls2TwM(3{eV58)nGF=jV`lfa9hX@it8?f(I~^elps)>gMEX!!zcS! zyIOkXz{50sxOwTS?y<;yxEYJXC${K!ps{c z`n|fkQ|exoN{v(wPNW_`7;Df|Adkosf2V5pPbE!i?srI^F~tfBNf7s+fUTb{+?M?^^JL}<2p z98f8=HOxK(@XFc>CRJ*wizmJvI?|MM5d^8gN^@CM4#PMcMyZ49o&{}+KW*K$k;&V^S%q5nv4139&*nzL?AG*Sy>)d zRE_+Sy5VRiuaBs_xTi>*y6N=eX^WO(7A4*w1aX2j&oQktGwwSFLJyhfg^uLBjVwl56XRTw7;N;BDLz3ON+7*ET`@(d?=jy|B=X)DEB0V-ZJDMr(j$~qniUuE1;n`bP zq9)yFJyh_w1TxY6zcC$J?iF5{yhq&1-!Z}{GwS)w($h}m&wzKHYMN?4FuUDz$%lKV zTdU5B#kq%m*9W_4gFx47x2t(`kr<$o2)>j8b1BcmhUt75#| ze`+kJ_F?Uc;LZ~b?xl!)YLy|SV+R+Zx zQ8y*#Xy-ZZi|DZoG_Sk;qDIpMctY>XyBfR2_4r$UB$%I6z(o2=XEu!~QeQ_oz0g9W&p3pivjN)3h}C@^jL^PiDX^VL47@|p7(fWXt$&t;uc GLK6T5D|jCO literal 0 HcmV?d00001 diff --git a/src/roles.json b/src/roles.json index 078e33b..ff723f1 100644 --- a/src/roles.json +++ b/src/roles.json @@ -1,19 +1,17 @@ [ { - "id": "pending", + "id": "washerwoman", "name": "Washerwoman", "edition": "tb", "team": "townsfolk", "firstNight": 19, - "firstNightReminder": ":eye: Show the character token of a Townsfolk in play. Point to two players, one of which is that character. :eye-slash:", + "firstNightReminder": "Show the character token of a Townsfolk in play. Point to two players, one of which is that character.", "otherNight": 0, "otherNightReminder": "", - "reminders": [ - "Townsfolk", - "Decoy" - ], + "reminders": ["Townsfolk", + "Wrong"], "setup": false, - "ability": "You start knowing 1 of 2 players is a particular Townsfolk." + "ability": "You start knowing that 1 of 2 players is a particular Townsfolk." }, { "id": "librarian", @@ -21,15 +19,13 @@ "edition": "tb", "team": "townsfolk", "firstNight": 20, - "firstNightReminder": ":eye: Show the character token of a Outsider in play. Point to two players, one of which is that character. :eye-slash:", + "firstNightReminder": "Show the character token of an Outsider in play. Point to two players, one of which is that character.", "otherNight": 0, "otherNightReminder": "", - "reminders": [ - "Outsider", - "Decoy" - ], + "reminders": ["Outsider", + "Wrong"], "setup": false, - "ability": "You start knowing that 1 of 2 players is a particular Outsider. (Or that zero are in play)" + "ability": "You start knowing that 1 of 2 players is a particular Outsider. (Or that zero are in play.)" }, { "id": "investigator", @@ -37,15 +33,13 @@ "edition": "tb", "team": "townsfolk", "firstNight": 21, - "firstNightReminder": ":eye: Show the character token of a Minion in play. Point to two players, one of which is that character. :eye-slash:", + "firstNightReminder": "Show the character token of a Minion in play. Point to two players, one of which is that character.", "otherNight": 0, "otherNightReminder": "", - "reminders": [ - "Minion", - "Decoy" - ], + "reminders": ["Minion", + "Wrong"], "setup": false, - "ability": "You start knowing 1 of 2 players is a particular Minion." + "ability": "You start knowing that 1 of 2 players is a particular Minion." }, { "id": "chef", @@ -53,7 +47,7 @@ "edition": "tb", "team": "townsfolk", "firstNight": 22, - "firstNightReminder": ":eye: Show the finger signal (0, 1, 2, …) for the number of pairs of neighbouring evil players. :eye-slash:", + "firstNightReminder": "Show the finger signal (0, 1, 2, \u2026) for the number of pairs of neighbouring evil players.", "otherNight": 0, "otherNightReminder": "", "reminders": [], @@ -66,9 +60,9 @@ "edition": "tb", "team": "townsfolk", "firstNight": 23, - "firstNightReminder": ":eye: Show the finger signal (0, 1, 2) for the number of evil alive neighbours of the Empath. :eye-slash:", - "otherNight": 42, - "otherNightReminder": ":eye: Show the finger signal (0, 1, 2) for the number of evil neighbours. :eye-slash:", + "firstNightReminder": "Show the finger signal (0, 1, 2) for the number of evil alive neighbours of the Empath.", + "otherNight": 43, + "otherNightReminder": "Show the finger signal (0, 1, 2) for the number of evil neighbours.", "reminders": [], "setup": false, "ability": "Each night, you learn how many of your 2 alive neighbours are evil." @@ -79,12 +73,10 @@ "edition": "tb", "team": "townsfolk", "firstNight": 24, - "firstNightReminder": ":eye: The Fortune Teller points to two players. Give the head signal (nod yes, shake no) for whether one of those players is the Demon. :eye-slash:", - "otherNight": 43, - "otherNightReminder": ":eye: The Fortune Teller points to two players. Show the head signal (nod “yes”, shake “no”) for whether one of those players is the Demon. :eye-slash:", - "reminders": [ - "Decoy" - ], + "firstNightReminder": "The Fortune Teller points to two players. Give the head signal (nod yes, shake no) for whether one of those players is the Demon. ", + "otherNight": 44, + "otherNightReminder": "The Fortune Teller points to two players. Show the head signal (nod 'yes', shake 'no') for whether one of those players is the Demon.", + "reminders": ["Red herring"], "setup": false, "ability": "Each night, choose 2 players: you learn if either is a Demon. There is a good player that registers as a Demon to you." }, @@ -95,11 +87,9 @@ "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", - "otherNight": 45, - "otherNightReminder": ":question-circle: If a player was executed today: :eye: Show that player’s character token. :eye-slash:", - "reminders": [ - "Executed" - ], + "otherNight": 46, + "otherNightReminder": "If a player was executed today: Show that player\u2019s character token.", + "reminders": ["Executed"], "setup": false, "ability": "Each night*, you learn which character died by execution today." }, @@ -111,10 +101,8 @@ "firstNight": 0, "firstNightReminder": "", "otherNight": 10, - "otherNightReminder": "The previously protected player is no longer protected. :plus-circle: :eye: The Monk points to a player not themself. :eye-slash: Mark that player “Protected”. :plus-circle:", - "reminders": [ - "Protected" - ], + "otherNightReminder": "The previously protected player is no longer protected. The Monk points to a player not themself. Mark that player 'Protected'.", + "reminders": ["Protected"], "setup": false, "ability": "Each night*, choose a player (not yourself): they are safe from the Demon tonight." }, @@ -125,24 +113,24 @@ "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", - "otherNight": 40, - "otherNightReminder": ":question-circle: If the Ravenkeeper died tonight: :eye: The Ravenkeeper points to a player. Show that player’s character token. :eye-slash:", + "otherNight": 41, + "otherNightReminder": "If the Ravenkeeper died tonight: The Ravenkeeper points to a player. Show that player\u2019s character token.", "reminders": [], "setup": false, "ability": "If you die at night, you are woken to choose a player: you learn their character." }, { - "id": "mayor", - "name": "Mayor", + "id": "virgin", + "name": "Virgin", "edition": "tb", "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", - "reminders": [], + "reminders": ["No ability"], "setup": false, - "ability": "If only 3 players live and no execution occurs, your team wins. If you die at night, another player might die instead." + "ability": "The 1st time you are nominated, if the nominator is a Townsfolk, they are executed immediately." }, { "id": "slayer", @@ -153,9 +141,7 @@ "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", - "reminders": [ - "Used" - ], + "reminders": ["No ability"], "setup": false, "ability": "Once per game, during the day, publicly choose a player: if they are the Demon, they die." }, @@ -173,19 +159,17 @@ "ability": "You are safe from the Demon." }, { - "id": "virgin", - "name": "Virgin", + "id": "mayor", + "name": "Mayor", "edition": "tb", "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", - "reminders": [ - "Used" - ], + "reminders": [], "setup": false, - "ability": "The first time you are nominated, if the nominator is a Townsfolk, they are executed immediately." + "ability": "If only 3 players live & no execution occurs, your team wins. If you die at night, another player might die instead." }, { "id": "butler", @@ -193,12 +177,10 @@ "edition": "tb", "team": "outsider", "firstNight": 25, - "firstNightReminder": ":eye: The Butler points to a player. :eye-slash: Mark that player as “Master”. :plus-circle:", - "otherNight": 44, - "otherNightReminder": ":eye: The Butler points to a player. :eye-slash: Mark that player as “Master”. :plus-circle:", - "reminders": [ - "Master" - ], + "firstNightReminder": "The Butler points to a player. Mark that player as 'Master'.", + "otherNight": 45, + "otherNightReminder": "The Butler points to a player. Mark that player as 'Master'.", + "reminders": ["Master"], "setup": false, "ability": "Each night, choose a player (not yourself): tomorrow, you may only vote if they are voting too." }, @@ -212,11 +194,9 @@ "otherNight": 0, "otherNightReminder": "", "reminders": [], - "remindersGlobal": [ - "Drunk" - ], + "remindersGlobal": ["Drunk"], "setup": true, - "ability": "You do not know you are the Drunk. You think you are a Townsfolk, but you are not." + "ability": "You do not know you are the Drunk. You think you are a Townsfolk character, but you are not." }, { "id": "recluse", @@ -229,7 +209,7 @@ "otherNightReminder": "", "reminders": [], "setup": false, - "ability": "You might register as evil and as a Minion or Demon, even if dead." + "ability": "You might register as evil & as a Minion or Demon, even if dead." }, { "id": "saint", @@ -242,7 +222,46 @@ "otherNightReminder": "", "reminders": [], "setup": false, - "ability": "If you die by execution, your team loses." + "ability": "If you are executed, your team loses." + }, + { + "id": "poisoner", + "name": "Poisoner", + "edition": "tb", + "team": "minion", + "firstNight": 9, + "firstNightReminder": "The Poisoner points to a player. That player is poisoned.", + "otherNight": 5, + "otherNightReminder": "The previously poisoned player is no longer poisoned. The Poisoner points to a player. That player is poisoned.", + "reminders": ["Poisoned"], + "setup": false, + "ability": "Each night, choose a player: they are poisoned tonight and tomorrow day" + }, + { + "id": "spy", + "name": "Spy", + "edition": "tb", + "team": "minion", + "firstNight": 33, + "firstNightReminder": "Show the Grimoire to the Spy for as long as they need.", + "otherNight": 56, + "otherNightReminder": "Show the Grimoire to the Spy for as long as they need.", + "reminders": [], + "setup": false, + "ability": "Each night, you see the Grimoire. You might register as good & as a Townsfolk or Outsider, even if dead." + }, + { + "id": "scarletwoman", + "name": "Scarlet Woman", + "edition": "tb", + "team": "minion", + "firstNight": 0, + "firstNightReminder": "", + "otherNight": 15, + "otherNightReminder": "If the Scarlet Woman became the Demon today: Show the 'You are' card, then the demon token.", + "reminders": ["Demon"], + "setup": false, + "ability": "If there are 5 or more players alive & the Demon dies, you become the Demon. (Travellers don\u2019t count)" }, { "id": "baron", @@ -257,49 +276,6 @@ "setup": true, "ability": "There are extra Outsiders in play. [+2 Outsiders]" }, - { - "id": "poisoner", - "name": "Poisoner", - "edition": "tb", - "team": "minion", - "firstNight": 9, - "firstNightReminder": ":eye: The Poisoner points to a player. :eye-slash: That player is poisoned. :plus-circle:", - "otherNight": 5, - "otherNightReminder": "The previously poisoned player is no longer poisoned. :plus-circle: :eye: The Poisoner points to a player. :eye-slash: That player is poisoned. :plus-circle:", - "reminders": [ - "Poisoned" - ], - "setup": false, - "ability": "Each night, choose a player: they are poisoned tonight and tomorrow day." - }, - { - "id": "spy", - "name": "Spy", - "edition": "tb", - "team": "minion", - "firstNight": 33, - "firstNightReminder": ":eye: Show the Grimoire to the Spy for as long as they need. :eye-slash:", - "otherNight": 55, - "otherNightReminder": ":eye: Show the Grimoire to the Spy for as long as they need. :eye-slash:", - "reminders": [], - "setup": false, - "ability": "Each night, you see the Grimoire. You might register as good and as a Townsfolk or Outsider, even if dead." - }, - { - "id": "scarletwoman", - "name": "Scarlet Woman", - "edition": "tb", - "team": "minion", - "firstNight": 0, - "firstNightReminder": "", - "otherNight": 15, - "otherNightReminder": ":question-circle: If the Scarlet Woman became the Demon today: :eye: Show the “You are” card, then the demon token. :eye-slash:", - "reminders": [ - "Demon" - ], - "setup": false, - "ability": "If there are 5 or more players alive (Travelers don't count) and the Demon dies, you become the Demon." - }, { "id": "imp", "name": "Imp", @@ -307,1192 +283,1085 @@ "team": "demon", "firstNight": 0, "firstNightReminder": "", - "otherNight": 18, - "otherNightReminder": ":eye: The Imp points to a player. :eye-slash: That player dies. :plus-circle: If the Imp chose themself: • Replace the character of 1 alive minion with a spare Imp token. :plus-circle: • :eye: Wake the new Imp. Show the “You are” card, then the Imp token. :eye-slash:", - "reminders": [ - "Die" - ], + "otherNight": 19, + "otherNightReminder": "The Imp points to a player. That player dies. If the Imp chose themselves: Replace the character of 1 alive minion with a spare Imp token. Show the 'You are' card, then the Imp token.", + "reminders": ["Dead"], "setup": false, "ability": "Each night*, choose a player: they die. If you kill yourself this way, a Minion becomes the Imp." }, + { + "id": "thief", + "name": "Thief", + "edition": "tb", + "team": "traveler", + "firstNight": 0, + "firstNightReminder": "The Thief points to a player. Put the Thief's 'Negative vote' reminder by the chosen player's character token.", + "otherNight": 0, + "otherNightReminder": "The Thief points to a player. Put the Thief's 'Negative vote' reminder by the chosen player's character token.", + "reminders": ["Negative vote"], + "setup": false, + "ability": "Each night, choose a player (not yourself): their vote counts negatively tomorrow." + }, + { + "id": "bureaucrat", + "name": "Bureaucrat", + "edition": "tb", + "team": "traveler", + "firstNight": 0, + "firstNightReminder": "The Bureaucrat points to a player. Put the Bureaucrat's '3 votes' reminder by the chosen player's character token.", + "otherNight": 0, + "otherNightReminder": "The Bureaucrat points to a player. Put the Bureaucrat's '3 votes' reminder by the chosen player's character token.", + "reminders": ["3 votes"], + "setup": false, + "ability": "Each night, choose a player (not yourself): their vote counts as 3 votes tomorrow." + }, + { + "id": "gunslinger", + "name": "Gunslinger", + "edition": "tb", + "team": "traveler", + "firstNight": 0, + "firstNightReminder": "", + "otherNight": 0, + "otherNightReminder": "", + "reminders": [], + "setup": false, + "ability": "Each day, after the 1st vote has been tallied, you may choose a player that voted: they die." + }, + { + "id": "scapegoat", + "name": "Scapegoat", + "edition": "tb", + "team": "traveler", + "firstNight": 0, + "firstNightReminder": "", + "otherNight": 0, + "otherNightReminder": "", + "reminders": [], + "setup": false, + "ability": "If a player of your alignment is executed, you might be executed instead." + }, + { + "id": "beggar", + "name": "Beggar", + "edition": "tb", + "team": "traveler", + "firstNight": 0, + "firstNightReminder": "", + "otherNight": 0, + "otherNightReminder": "", + "reminders": [], + "setup": false, + "ability": "You must use a vote token to vote. Dead players may choose to give you theirs. If so, you learn their alignment." + }, { "id": "grandmother", + "name": "Grandmother", "edition": "bmr", + "team": "townsfolk", "firstNight": 26, "firstNightReminder": "Show the marked character token. Point to the marked player.", - "otherNight": 38, - "otherNightReminder": "If the Grandmother’s grandchild was killed by the Demon tonight: • The Grandmother dies.", - "reminders": [ - "Grandchild" - ], + "otherNight": 39, + "otherNightReminder": "If the Grandmother\u2019s grandchild was killed by the Demon tonight: The Grandmother dies.", + "reminders": ["Grandchild"], "setup": false, - "name": "Grandmother", - "team": "townsfolk", - "ability": "You start knowing a good player and character. If the Demon kills them, you die too." + "ability": "You start knowing a good player & character. If the Demon kills them, you die too." }, { "id": "sailor", + "name": "Sailor", "edition": "bmr", + "team": "townsfolk", "firstNight": 5, "firstNightReminder": "The Sailor points to a living player. Either the Sailor, or the chosen player, is drunk.", "otherNight": 2, "otherNightReminder": "The previously drunk player is no longer drunk. The Sailor points to a living player. Either the Sailor, or the chosen player, is drunk.", - "reminders": [ - "Drunk" - ], + "reminders": ["Drunk"], "setup": false, - "name": "Sailor", - "team": "townsfolk", - "ability": "Each night, choose a player: either you or they are drunk until dusk. You can not die." + "ability": "Each night, choose an alive player: either you or they are drunk until dusk. You can't die." }, { "id": "chambermaid", + "name": "Chambermaid", "edition": "bmr", + "team": "townsfolk", "firstNight": 36, - "firstNightReminder": "The Chambermaid points to two players. Show the number signal (0, 1, 2, …) for how many of those players wake tonight for their ability.", - "otherNight": 58, - "otherNightReminder": "The Chambermaid points to two players. Show the number signal (0, 1, 2) for how many of those players wake tonight for their ability.", + "firstNightReminder": "The Chambermaid points to two players. Show the number signal (0, 1, 2, \u2026) for how many of those players wake tonight for their ability.", + "otherNight": 59, + "otherNightReminder": "The Chambermaid points to two players. Show the number signal (0, 1, 2, \u2026) for how many of those players wake tonight for their ability.", "reminders": [], "setup": false, - "name": "Chambermaid", - "team": "townsfolk", "ability": "Each night, choose 2 alive players (not yourself): you learn how many woke tonight due to their ability." }, { "id": "exorcist", + "name": "Exorcist", "edition": "bmr", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", - "otherNight": 17, - "otherNightReminder": "The Exorcist points to a player, different from the previous night. If that player is the Demon: • Wake the Demon. Show the Exorcist token. Point to the Exorcist. • The Demon does not act tonight.", - "reminders": [ - "Chosen" - ], + "otherNight": 18, + "otherNightReminder": "The Exorcist points to a player, different from the previous night. If that player is the Demon: Wake the Demon. Show the Exorcist token. Point to the Exorcist. The Demon does not act tonight.", + "reminders": ["Chosen"], "setup": false, - "name": "Exorcist", - "team": "townsfolk", "ability": "Each night*, choose a player (different to last night): the Demon, if chosen, learns who you are then doesn't wake tonight." }, { "id": "innkeeper", + "name": "Innkeeper", "edition": "bmr", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", "otherNight": 6, "otherNightReminder": "The previously protected and drunk players lose those markers. The Innkeeper points to two players. Those players are protected. One is drunk.", - "reminders": [ - "Protected", - "Drunk" - ], + "reminders": ["Protected", + "Drunk"], "setup": false, - "name": "Innkeeper", - "team": "townsfolk", - "ability": "Each night*, choose 2 players: they cannot die tonight, but 1 is drunk until dusk." + "ability": "Each night*, choose 2 players: they can't die tonight, but 1 is drunk until dusk." }, { "id": "gambler", + "name": "Gambler", "edition": "bmr", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", "otherNight": 8, "otherNightReminder": "The Gambler points to a player, and a character on their sheet. If incorrect, the Gambler dies.", - "reminders": [ - "Die" - ], + "reminders": ["Dead"], "setup": false, - "name": "Gambler", - "team": "townsfolk", - "ability": "Each night*, choose a player and guess their character: if you guess wrong, you die." + "ability": "Each night*, choose a player & guess their character: if you guess wrong, you die." }, { "id": "gossip", + "name": "Gossip", "edition": "bmr", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", - "otherNight": 35, - "otherNightReminder": "If the Gossip’s public statement was true: • Choose a player not protected from dying tonight. That player dies.", - "reminders": [ - "Die" - ], + "otherNight": 36, + "otherNightReminder": "If the Gossip\u2019s public statement was true: Choose a player not protected from dying tonight. That player dies.", + "reminders": ["Dead"], "setup": false, - "name": "Gossip", - "team": "townsfolk", "ability": "Each day, you may make a public statement. Tonight, if it was true, a player dies." }, { "id": "courtier", - "edition": "bmr", - "firstNight": 11, - "firstNightReminder": "The Courier either shows a “no” head signal, or points to a character on the sheet. If the Courtier used their ability : If that character is in play, that player is drunk.", - "otherNight": 7, - "otherNightReminder": "Reduce the remaining number of days the marked player is poisoned. If the Courtier has not yet used their ability: • The Courier either shows a “no” head signal, or points to a character on the sheet. • If the Courtier used their ability : If that character is in play, that player is drunk.", - "reminders": [ - "Drunk 1", - "Drunk 2", - "Drunk 3", - "Used" - ], - "setup": false, "name": "Courtier", + "edition": "bmr", "team": "townsfolk", - "ability": "Once per game, at night, choose a character: they are drunk for 3 nights and 3 days." + "firstNight": 11, + "firstNightReminder": "The Courtier either shows a 'no' head signal, or points to a character on the sheet. If the Courtier used their ability : If that character is in play, that player is drunk.", + "otherNight": 7, + "otherNightReminder": "Reduce the remaining number of days the marked player is poisoned. If the Courtier has not yet used their ability: The Courtier either shows a 'no' head signal, or points to a character on the sheet. If the Courtier used their ability: If that character is in play, that player is drunk.", + "reminders": ["Drunk 3", + "Drunk 2", + "Drunk 1", + "No ability"], + "setup": false, + "ability": "Once per game, at night, choose a character: they are drunk for 3 nights & 3 days." }, { "id": "professor", + "name": "Professor", "edition": "bmr", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", - "otherNight": 34, - "otherNightReminder": "If the Professor has not used their ability: • The Professor either shows the “no” head signal, or points to a player. • If that player is a Townsfolk, they are now alive.", - "reminders": [ - "Alive", - "Used" - ], + "otherNight": 35, + "otherNightReminder": "If the Professor has not used their ability: The Professor either shakes their head no, or points to a player. If that player is a Townsfolk, they are now alive.", + "reminders": ["Alive", + "No ability"], "setup": false, - "name": "Professor", - "team": "townsfolk", - "ability": "Once per game, at night*, choose a dead player. If they are a Townsfolk, they are resurrected." + "ability": "Once per game, at night*, choose a dead player: if they are a Townsfolk, they are resurrected." }, { "id": "minstrel", + "name": "Minstrel", "edition": "bmr", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", - "otherNight": 1, - "otherNightReminder": "Remove the “Everyone drunk” marker. If a Minion died by execution today: All players but the Minstrel are drunk. Place the “Everyone drunk” marker.", - "reminders": [ - "Everyone drunk" - ], + "otherNight": 0, + "otherNightReminder": "Remove the 'Everyone drunk' marker. If a Minion died today: All players but the Minstrel are drunk. Place the 'Everyone drunk' marker.", + "reminders": ["Everyone drunk"], "setup": false, - "name": "Minstrel", - "team": "townsfolk", - "ability": "When a Minion dies by execution, all other players (except Travelers) are drunk until dusk tomorrow." + "ability": "When a Minion dies by execution, all other players (except Travellers) are drunk until dusk tomorrow." }, { "id": "tealady", + "name": "Tea Lady", "edition": "bmr", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", - "reminders": [ - "Protected" - ], + "reminders": ["Can not die"], "setup": false, - "name": "Tea Lady", - "team": "townsfolk", - "ability": "If both your alive neighbors are good, they can't die." + "ability": "If both your alive neighbours are good, they can't die." }, { "id": "pacifist", + "name": "Pacifist", "edition": "bmr", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", "reminders": [], "setup": false, - "name": "Pacifist", - "team": "townsfolk", "ability": "Executed good players might not die." }, { "id": "fool", + "name": "Fool", "edition": "bmr", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", - "reminders": [ - "Used" - ], + "reminders": ["No ability"], "setup": false, - "name": "Fool", - "team": "townsfolk", "ability": "The first time you die, you don't." }, { "id": "tinker", - "edition": "bmr", - "firstNight": 0, - "firstNightReminder": "", - "otherNight": 36, - "otherNightReminder": "The Tinker might die.", - "reminders": [ - "Die" - ], - "setup": false, "name": "Tinker", + "edition": "bmr", "team": "outsider", + "firstNight": 0, + "firstNightReminder": "The Tinker might die.", + "otherNight": 37, + "otherNightReminder": "The Tinker might die.", + "reminders": ["Dead"], + "setup": false, "ability": "You might die at any time." }, { "id": "moonchild", + "name": "Moonchild", "edition": "bmr", + "team": "outsider", "firstNight": 0, "firstNightReminder": "", - "otherNight": 37, - "otherNightReminder": "If the Moonchild used their ability to target a player today: • If that player is good, they die.", - "reminders": [ - "Die" - ], + "otherNight": 38, + "otherNightReminder": "If the Moonchild used their ability to target a player today: If that player is good, they die.", + "reminders": ["Dead"], "setup": false, - "name": "Moonchild", - "team": "outsider", "ability": "When you learn that you died, publicly choose 1 alive player. Tonight, if it was a good player, they die." }, { "id": "goon", - "edition": "bmr", - "firstNight": 100, - "firstNightReminder": "If a player used their character ability to choose the Goon: • The Goon becomes that player’s alignment. • Show the “You are” card. Show the hand signal (thumb-up “good”, thumb-down “evil”) for the Goon’s current alignment.", - "otherNight": 100, - "otherNightReminder": "If a player used their character ability to choose the Goon: • The Goon becomes that player’s alignment. • Show the “You are” card, then the hand signal (thumb-up “good”, thumb-down “evil”) for the Goon’s current alignment.", - "reminders": [ - "Drunk" - ], - "setup": false, "name": "Goon", + "edition": "bmr", "team": "outsider", + "firstNight": 0, + "firstNightReminder": "If a player used their character ability to choose the Goon: The ability does not work. Place the Drunk token on that player. The Goon becomes that player\u2019s alignment. Show 'You are' card. Show thumbs-up good, thumbs-down 'evil' for the Goon\u2019s current alignment.", + "otherNight": 0, + "otherNightReminder": "If a player used their character ability to choose the Goon: The Goon becomes that player\u2019s alignment. Show the 'You are' card. Show the hand signal (thumbs-up 'good', thumbs-down 'evil') for the Goon\u2019s current alignment.", + "reminders": ["Drunk"], + "setup": false, "ability": "Each night, the 1st player to choose you with their ability is drunk until dusk. You become their alignment." }, { "id": "lunatic", - "edition": "bmr", - "firstNight": 3, - "firstNightReminder": "If 7 or more players: Show the Lunatic a number of arbitrary “Minion“, players equal to the number of Minions in play. Show 3 character tokens of arbitrary Good characters. If the token received by the Lunatic is a Demon that would wake tonight: • Allow the Lunatic to do the Demon actions. Place their “attack” markers. Wake the Demon. Show the Demon’s real character token. Show them the Lunatic player. • If the Lunatic attacked players: Show the real demon each marked player. Remove any Lunatic “attack” markers.", - "otherNight": 16, - "otherNightReminder": "Allow the Lunatic to do the actions of the Demon. Place their “attack” markers. If the Lunatic selected players: Wake the Demon. Show the “attack” marker, then point to each marked player. Remove any Lunatic “attack” markers.", - "reminders": [ - "Attack 1", - "Attack 2", - "Attack 3", - "Decoy" - ], - "setup": false, "name": "Lunatic", + "edition": "bmr", "team": "outsider", + "firstNight": 3, + "firstNightReminder": "If 7 or more players: Show the Lunatic a number of arbitrary 'Minions', players equal to the number of Minions in play. Show 3 character tokens of arbitrary good characters. If the token received by the Lunatic is a Demon that would wake tonight: Allow the Lunatic to do the Demon actions. Place their 'attack' markers. Wake the Demon. Show the Demon\u2019s real character token. Show them the Lunatic player. If the Lunatic attacked players: Show the real demon each marked player. Remove any Lunatic 'attack' markers.", + "otherNight": 17, + "otherNightReminder": "Allow the Lunatic to do the actions of the Demon. Place their 'attack' markers. If the Lunatic selected players: Wake the Demon. Show the 'attack' marker, then point to each marked player. Remove any Lunatic 'attack' markers.", + "reminders": ["Attack 1", + "Attack 2", + "Attack 3"], + "setup": false, "ability": "You think you are a Demon, but you are not. The Demon knows who you are & who you choose at night." }, { "id": "godfather", + "name": "Godfather", "edition": "bmr", + "team": "minion", "firstNight": 13, "firstNightReminder": "Show each of the Outsider tokens in play.", - "otherNight": 30, - "otherNightReminder": "If an Outsider died today: • The Godfather points to a player. That player dies.", - "reminders": [ - "Died today", - "Die" - ], + "otherNight": 31, + "otherNightReminder": "If an Outsider died today: The Godfather points to a player. That player dies.", + "reminders": ["Died today", + "Dead"], "setup": true, - "name": "Godfather", - "team": "minion", - "ability": "You start knowing which Outsiders are in-play. If 1 died today, choose a player tonight: they die. [-1 or +1 Outsider]" + "ability": "You start knowing which Outsiders are in play. If 1 died today, choose a player tonight: they die. [\u22121 or +1 Outsider]" }, { "id": "devilsadvocate", - "edition": "bmr", - "firstNight": 14, - "firstNightReminder": "The Devil’s Advocate points to a living player. That player survives execution tomorrow.", - "otherNight": 11, - "otherNightReminder": "The Devil’s Advocate points to a living player, different from the previous night. That player survives execution tomorrow.", - "reminders": [ - "Survives execution" - ], - "setup": false, "name": "Devil's Advocate", + "edition": "bmr", "team": "minion", + "firstNight": 14, + "firstNightReminder": "The Devil\u2019s Advocate points to a living player. That player survives execution tomorrow.", + "otherNight": 11, + "otherNightReminder": "The Devil\u2019s Advocate points to a living player, different from the previous night. That player survives execution tomorrow.", + "reminders": ["Survives execution"], + "setup": false, "ability": "Each night, choose a living player (different to last night): if executed tomorrow, they don't die." }, { "id": "assassin", + "name": "Assassin", "edition": "bmr", + "team": "minion", "firstNight": 0, "firstNightReminder": "", - "otherNight": 29, - "otherNightReminder": "If the Assassin has not yet used their ability: • The Assassin either shows the “no” head signal, or points to a player. That player dies.", - "reminders": [ - "Die", - "Used" - ], + "otherNight": 30, + "otherNightReminder": "If the Assassin has not yet used their ability: The Assassin either shows the 'no' head signal, or points to a player. That player dies.", + "reminders": ["Dead", + "No ability"], "setup": false, - "name": "Assassin", - "team": "minion", "ability": "Once per game, at night*, choose a player: they die, even if for some reason they could not." }, { "id": "mastermind", + "name": "Mastermind", "edition": "bmr", + "team": "minion", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", "reminders": [], "setup": false, - "name": "Mastermind", - "team": "minion", - "ability": "If the Demon dies by execution (ending the game), play for 1 more day. If a player is then executed, their team loses." - }, - { - "id": "po", - "edition": "bmr", - "firstNight": 0, - "firstNightReminder": "", - "otherNight": 23, - "otherNightReminder": "If the Po chose no-one previously: The Po points to three players. Otherwise: The Po either shows the “no” head signal, or points to a player. The marked players (if any) die.", - "reminders": [ - "Die 1", - "Die 2", - "Die 3", - "Attack x3" - ], - "setup": false, - "name": "Po", - "team": "demon", - "ability": "Each night*, you may choose a player: they die. If your last choice was no-one, choose 3 players tonight." + "ability": "If the Demon dies by execution (ending the game), play for one more day. If a player is then executed, their team loses." }, { "id": "zombuul", + "name": "Zombuul", "edition": "bmr", + "team": "demon", "firstNight": 0, "firstNightReminder": "", - "otherNight": 19, - "otherNightReminder": "If no-one died during the day: • The Zombuul points to a player. That player dies.", - "reminders": [ - "No death today", - "Die" - ], + "otherNight": 20, + "otherNightReminder": "If no-one died during the day: The Zombuul points to a player. That player dies.", + "reminders": ["Died today", + "Dead"], "setup": false, - "name": "Zombuul", - "team": "demon", "ability": "Each night*, if no-one died today, choose a player: they die. The 1st time you die, you live but register as dead." }, { "id": "pukka", + "name": "Pukka", "edition": "bmr", + "team": "demon", "firstNight": 18, "firstNightReminder": "The Pukka points to a player. That player is poisoned.", - "otherNight": 20, + "otherNight": 21, "otherNightReminder": "The poisoned player dies. The Pukka points to a player. That player is poisoned.", - "reminders": [ - "Poisoned", - "Die" - ], + "reminders": ["Poisoned", + "Dead"], "setup": false, - "name": "Pukka", - "team": "demon", "ability": "Each night, choose a player: they are poisoned. The previously poisoned player dies then becomes healthy." }, { "id": "shabaloth", + "name": "Shabaloth", "edition": "bmr", + "team": "demon", "firstNight": 0, "firstNightReminder": "", - "otherNight": 22, - "otherNightReminder": "One player that the Shabaloth chose the previous night might come alive. The Shabaloth points to two players. Those players die.", - "reminders": [ - "Die 1", - "Die 2", - "Alive" - ], + "otherNight": 23, + "otherNightReminder": "One player that the Shabaloth chose the previous night might be resurrected. The Shabaloth points to two players. Those players die.", + "reminders": ["Dead", + "Alive"], "setup": false, - "name": "Shabaloth", - "team": "demon", "ability": "Each night*, choose 2 players: they die. A dead player you chose last night might be regurgitated." }, + { + "id": "po", + "name": "Po", + "edition": "bmr", + "team": "demon", + "firstNight": 0, + "firstNightReminder": "", + "otherNight": 24, + "otherNightReminder": "If the Po chose no-one the previous night: The Po points to three players. Otherwise: The Po either shows the 'no' head signal , or points to a player. Chosen players die", + "reminders": ["Dead", + "3 attacks"], + "setup": false, + "ability": "Each night*, you may choose a player: they die. If your last choice was no-one, choose 3 players tonight." + }, + { + "id": "apprentice", + "name": "Apprentice", + "edition": "bmr", + "team": "traveler", + "firstNight": 0, + "firstNightReminder": "Show the Apprentice the 'You are' card, then a Townsfolk or Minion token. In the Grimoire, replace the Apprentice token with that character token, and put the Apprentice's 'Is the Apprentice' reminder by that character token.", + "otherNight": 0, + "otherNightReminder": "", + "reminders": ["Is the Apprentice"], + "setup": false, + "ability": "On your 1st night, you gain a Townsfolk ability (if good), or a Minion ability (if evil)." + }, + { + "id": "matron", + "name": "Matron", + "edition": "bmr", + "team": "traveler", + "firstNight": 0, + "firstNightReminder": "", + "otherNight": 0, + "otherNightReminder": "", + "reminders": [], + "setup": false, + "ability": "Each day, you may choose up to 3 pairs of players to swap seats. Players may not leave their seats to talk in private." + }, + { + "id": "judge", + "name": "Judge", + "edition": "bmr", + "team": "traveler", + "firstNight": 0, + "firstNightReminder": "", + "otherNight": 0, + "otherNightReminder": "", + "reminders": ["No ability"], + "setup": false, + "ability": "Once per game, if another player nominated, you may choose to force the current execution to pass or fail." + }, + { + "id": "bishop", + "name": "Bishop", + "edition": "bmr", + "team": "traveler", + "firstNight": 0, + "firstNightReminder": "", + "otherNight": 0, + "otherNightReminder": "", + "reminders": ["Nominate good", + "Nominate evil"], + "setup": false, + "ability": "Only the Storyteller can nominate. At least 1 opposite player must be nominated each day." + }, + { + "id": "voudon", + "name": "Voudon", + "edition": "bmr", + "team": "traveler", + "firstNight": 0, + "firstNightReminder": "", + "otherNight": 0, + "otherNightReminder": "", + "reminders": [], + "setup": false, + "ability": "Only you and the dead can vote. They don't need a vote token to do so. A 50% majority is not required." + }, { "id": "clockmaker", + "name": "Clockmaker", "edition": "snv", + "team": "townsfolk", "firstNight": 27, "firstNightReminder": "Show the hand signal for the number (1, 2, 3, etc.) of places from Demon to closest Minion.", "otherNight": 0, "otherNightReminder": "", "reminders": [], "setup": false, - "name": "Clockmaker", - "team": "townsfolk", "ability": "You start knowing how many steps from the Demon to its nearest Minion." }, { "id": "dreamer", + "name": "Dreamer", "edition": "snv", + "team": "townsfolk", "firstNight": 28, - "firstNightReminder": "The Dreamer points to a player. Show two character tokens, one of which is that player’s character, the other of which is of opposite alignment to that character.", - "otherNight": 46, + "firstNightReminder": "The Dreamer points to a player. Show 1 good and 1 evil character token; one of these is correct.", + "otherNight": 47, "otherNightReminder": "The Dreamer points to a player. Show 1 good and 1 evil character token; one of these is correct.", "reminders": [], "setup": false, - "name": "Dreamer", - "team": "townsfolk", - "ability": "Each night, choose a player (not yourself, not Travellers); you learn 1 good character & 1 evil character, 1 of which is correct." + "ability": "Each night, choose a player (not yourself, not Travellers): you learn 1 good and 1 evil character, 1 of which is correct." }, { "id": "snakecharmer", - "edition": "snv", - "firstNight": 12, - "firstNightReminder": "The Snake Charmer points to a player. If that player is the Demon: • Swap the Snake Charmer and Demon character tokens. • Wake the new Demon. Show the “You are” card, then the thumb-down “evil” sign. Show the “You are” card, then the Demon token. • The new Snake Charmer is poisoned. Wake the new Snake Charmer. Show the “You are” card, then the thumb-up “good” sign. Show the “You are” card, then the Snake Charmer token.", - "otherNight": 9, - "otherNightReminder": "The Snake Charmer points to a player. If that player is the Demon: • Swap the Snake Charmer and Demon character tokens. Wake the new Demon. Show the “You are” card, then the thumb-down “evil” sign. Show the “You are” card, then the Demon token. • The new Snake Charmer is poisoned. Wake the new Snake Charmer. Show the “You are” card, then the thumb-up “good” sign. Show the “You are” card, then the Snake Charmer token.", - "reminders": [ - "Poisoned" - ], - "setup": false, "name": "Snake Charmer", + "edition": "snv", "team": "townsfolk", - "ability": "Each night, choose an alive player: a chosen Demon swaps characters and alignments with you and is then poisoned." + "firstNight": 12, + "firstNightReminder": "The Snake Charmer points to a player. If that player is the Demon: swap the Demon and Snake Charmer character and alignments. Wake each player to inform them of their new role and alignment. The new Snake Charmer is poisoned.", + "otherNight": 9, + "otherNightReminder": "The Snake Charmer points to a player. If that player is the Demon: swap the Demon and Snake Charmer character and alignments. Wake each player to inform them of their new role and alignment. The new Snake Charmer is poisoned.", + "reminders": ["Poisoned"], + "setup": false, + "ability": "Each night, choose an alive player: a chosen Demon swaps characters & alignments with you & is then poisoned." }, { "id": "mathematician", - "edition": "snv", - "firstNight": 35, - "firstNightReminder": "Show the hand signal for the number (0, 1, 2, etc.) of “Abnormal Effect” markers. Remove markers", - "otherNight": 57, - "otherNightReminder": "Show the hand signal for the number (0, 1, 2, etc.) of “Abnormal Effect” markers. Remove markers.", - "reminders": [ - "Abnormal effect" - ], - "setup": false, "name": "Mathematician", + "edition": "snv", "team": "townsfolk", - "ability": "Each night, you learn how many players' abilities worked abnormally (since dawn) due to another character's ability." + "firstNight": 35, + "firstNightReminder": "Show the hand signal for the number (0, 1, 2, etc.) of players whose ability malfunctioned due to other abilities.", + "otherNight": 58, + "otherNightReminder": "Show the hand signal for the number (0, 1, 2, etc.) of players whose ability malfunctioned due to other abilities.", + "reminders": ["Abnormal"], + "setup": false, + "ability": "Each night, you learn how many players\u2019 abilities worked abnormally (since dawn) due to another character's ability." }, { "id": "flowergirl", - "edition": "snv", - "firstNight": 0, - "firstNightReminder": "Place the “Demon did not vote” marker.", - "otherNight": 47, - "otherNightReminder": "Show the head signal (nod “yes”, shake “no”) for whether the Demon voted today. Place the “Demon did not vote” marker (remove “Demon voted”, if any).", - "reminders": [ - "Demon did vote", - "Demon did not vote" - ], - "setup": false, "name": "Flowergirl", + "edition": "snv", "team": "townsfolk", - "ability": "Each night*, you learn if the Demon voted today." + "firstNight": 0, + "firstNightReminder": "Place the 'Demon not voted' marker.", + "otherNight": 48, + "otherNightReminder": "Nod 'yes' or shake head 'no' for whether the Demon voted today. Place the 'Demon not voted' marker (remove 'Demon voted', if any).", + "reminders": ["Demon voted", + "Demon not voted"], + "setup": false, + "ability": "Each night*, you learn if a Demon voted today." }, { "id": "towncrier", - "edition": "snv", - "firstNight": 0, - "firstNightReminder": "Place the “Minions did not nominate” marker.", - "otherNight": 48, - "otherNightReminder": "Show the head signal (nod “yes”, shake “no”) for whether any Minion nominated today. Place the “Minions did not nominate” marker (remove “Minion nominated”, if any).", - "reminders": [ - "No Minion nominated", - "Minion nominated" - ], - "setup": false, "name": "Town Crier", + "edition": "snv", "team": "townsfolk", - "ability": "Each night*, you learn if a Minion nominated today." + "firstNight": 0, + "firstNightReminder": "Place the 'Minions not nominated' marker.", + "otherNight": 49, + "otherNightReminder": "Nod 'yes' or shake head 'no' for whether a Minion nominated today. Place the 'Minion not nominated' marker (remove 'Minion nominated', if any).", + "reminders": ["Minions not nominated", + "Minion nominated"], + "setup": false, + "ability": "Each night*, you learn if a Minion nominated today" }, { "id": "oracle", + "name": "Oracle", "edition": "snv", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", - "otherNight": 49, + "otherNight": 50, "otherNightReminder": "Show the hand signal for the number (0, 1, 2, etc.) of dead evil players.", "reminders": [], "setup": false, - "name": "Oracle", - "team": "townsfolk", "ability": "Each night*, you learn how many dead players are evil." }, { "id": "savant", + "name": "Savant", "edition": "snv", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", "reminders": [], "setup": false, - "name": "Savant", - "team": "townsfolk", - "ability": "Each day, you may visit the Storyteller to learn 2 things in private: 1 is true and 1 is false." + "ability": "Each day, you may visit the Storyteller to learn 2 things in private: 1 is true & 1 is false." }, { "id": "seamstress", - "edition": "snv", - "firstNight": 29, - "firstNightReminder": "The Seamstress either shows a “no” head signal, or points to two other players. If the Seamstress chose two players, nod “yes” or shake “no” for whether they are of same alignment.", - "otherNight": 50, - "otherNightReminder": "If the Seamstress has not yet used their ability: • The Seamstress either shows a “no” head signal, or points to two other players. • If the Seamstress chose players, nod “yes” or shake “no” for whether they are of same alignment.", - "reminders": [ - "Used" - ], - "setup": false, "name": "Seamstress", + "edition": "snv", "team": "townsfolk", + "firstNight": 29, + "firstNightReminder": "The Seamstress either shows a 'no' head signal, or points to two other players. If the Seamstress chose players , nod 'yes' or shake 'no' for whether they are of same alignment.", + "otherNight": 51, + "otherNightReminder": "If the Seamstress has not yet used their ability: the Seamstress either shows a 'no' head signal, or points to two other players. If the Seamstress chose players , nod 'yes' or shake 'no' for whether they are of same alignment.", + "reminders": ["No ability"], + "setup": false, "ability": "Once per game, at night, choose 2 players (not yourself): you learn if they are the same alignment." }, { "id": "philosopher", - "edition": "snv", - "firstNight": 1, - "firstNightReminder": "The Philosopher either shows a “no” head signal, or points to a good character on their sheet. If they chose a character: they now have that character's ability. If the character is in play, that player is now drunk.", - "otherNight": 1, - "otherNightReminder": "If the Philosopher has not yet used their ability: • The Philosopher either shows a “no” head signal, or points to a good character on their sheet. • If they chose a character: they now have that character's ability. If the character is in play, that player is now drunk.", - "reminders": [ - "Used", - "Drunk" - ], - "setup": false, "name": "Philosopher", + "edition": "snv", "team": "townsfolk", + "firstNight": 1, + "firstNightReminder": "The Philosopher either shows a 'no' head signal, or points to a good character on their sheet. If they chose a character: Swap the out-of-play character token with the Philosopher token. Or, if the character is in play, place the drunk marker by that player and the Not the Philosopher token by the Philosopher.", + "otherNight": 1, + "otherNightReminder": "If the Philosopher has not used their ability: the Philosopher either shows a 'no' head signal, or points to a good character on their sheet. If they chose a character: Swap the out-of-play character token with the Philosopher token. Or, if the character is in play, place the drunk marker by that player and the Not the Philosopher token by the Philosopher.", + "reminders": ["Drunk", + "Is not the Philosopher"], + "setup": false, "ability": "Once per game, at night, choose a good character: gain that ability. If this character is in play, they are drunk." }, { "id": "artist", + "name": "Artist", "edition": "snv", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", - "reminders": [ - "Used" - ], + "reminders": ["No ability"], "setup": false, - "name": "Artist", - "team": "townsfolk", "ability": "Once per game, during the day, privately ask the Storyteller any yes/no question." }, { "id": "juggler", + "name": "Juggler", "edition": "snv", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", - "otherNight": 51, - "otherNightReminder": "If today was the Juggler’s first day: • Show the hand signal for the number (0, 1, 2, etc.) of “Correct” markers. Remove markers.", - "reminders": [ - "Correct" - ], + "otherNight": 52, + "otherNightReminder": "If today was the Juggler\u2019s first day: Show the hand signal for the number (0, 1, 2, etc.) of 'Correct' markers. Remove markers.", + "reminders": ["Correct"], "setup": false, - "name": "Juggler", - "team": "townsfolk", - "ability": "On your 1st day, publicly guess up to 5 player's characters. That night, you learn how many you got correct." + "ability": "On your 1st day, publicly guess up to 5 players' characters. That night, you learn how many you got correct." }, { "id": "sage", + "name": "Sage", "edition": "snv", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", - "otherNight": 33, - "otherNightReminder": "If the Sage was killed by a Demon: • Point to two players, one of which is that Demon.", + "otherNight": 34, + "otherNightReminder": "If the Sage was killed by a Demon: Point to two players, one of which is that Demon.", "reminders": [], "setup": false, - "name": "Sage", - "team": "townsfolk", "ability": "If the Demon kills you, you learn that it is 1 of 2 players." }, { "id": "mutant", + "name": "Mutant", "edition": "snv", + "team": "outsider", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", "reminders": [], "setup": false, - "name": "Mutant", - "team": "outsider", - "ability": "If you are \"mad\" about being an Outsider, you might be executed." + "ability": "If you are \u201Cmad\u201D about being an Outsider, you might be executed." }, { "id": "sweetheart", + "name": "Sweetheart", "edition": "snv", + "team": "outsider", "firstNight": 0, "firstNightReminder": "", - "otherNight": 32, - "otherNightReminder": "", - "reminders": [ - "Drunk" - ], + "otherNight": 33, + "otherNightReminder": "Choose a player that is drunk.", + "reminders": ["Drunk"], "setup": false, - "name": "Sweetheart", - "team": "outsider", - "ability": "If you die, 1 player is drunk from now on." + "ability": "When you die, 1 player is drunk from now on." }, { "id": "barber", + "name": "Barber", "edition": "snv", + "team": "outsider", "firstNight": 0, "firstNightReminder": "", - "otherNight": 31, - "otherNightReminder": "If the Barber died today or tonight: • Wake the Demon. Show the “This character selected you” card, then Barber token. • The Demon either shows a “no” head signal, or points to 2 non-Demon players. If they chose players: ◦ Swap the character tokens. Wake each player. Show “You are”, then their character token.", - "reminders": [ - "Swap" - ], + "otherNight": 32, + "otherNightReminder": "If the Barber died today: Wake the Demon. Show the 'This character selected you' card, then Barber token. The Demon either shows a 'no' head signal, or points to 2 players. If they chose players: Swap the character tokens. Wake each player. Show 'You are', then their new character token.", + "reminders": ["Haircuts tonight"], "setup": false, - "name": "Barber", - "team": "outsider", "ability": "If you died today or tonight, the Demon may choose 2 players (not another Demon) to swap characters." }, { "id": "klutz", + "name": "Klutz", "edition": "snv", + "team": "outsider", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", "reminders": [], "setup": false, - "name": "Klutz", - "team": "outsider", - "ability": "When you learn that you died, publicly choose 1 alive player: if they are evil, your team loses." + "ability": "When you learn that you died, publicly choose an alive good player or you lose." }, { "id": "eviltwin", + "name": "Evil Twin", "edition": "snv", + "team": "minion", "firstNight": 15, "firstNightReminder": "Wake the Evil Twin and their twin. Confirm that they have acknowledged each other. Point to the Evil Twin. Show their Evil Twin token to the twin player. Point to the twin. Show their character token to the Evil Twin player.", "otherNight": 0, "otherNightReminder": "", - "reminders": [ - "Twin" - ], + "reminders": ["Twin"], "setup": false, - "name": "Evil Twin", - "team": "minion", - "ability": "You and an opposing player know each other. If the good player is executed, evil wins. Good can't win if you both live." + "ability": "You & an opposing player know each other. If the good player is executed, evil wins. Good can't win if you both live." }, { "id": "witch", - "edition": "snv", - "firstNight": 16, - "firstNightReminder": "The Witch points to a player. That player is cursed for the next day.", - "otherNight": 12, - "otherNightReminder": "The Witch points to a player. That player is cursed for the next day.", - "reminders": [ - "Cursed" - ], - "setup": false, "name": "Witch", + "edition": "snv", "team": "minion", + "firstNight": 16, + "firstNightReminder": "The Witch points to a player. If that player nominates tomorrow they die immediately.", + "otherNight": 12, + "otherNightReminder": "If there are 4 or more players alive: The Witch points to a player. If that player nominates tomorrow they die immediately.", + "reminders": ["Cursed"], + "setup": false, "ability": "Each night, choose a player: if they nominate tomorrow, they die. If just 3 players live, you lose this ability." }, { "id": "cerenovus", - "edition": "snv", - "firstNight": 17, - "firstNightReminder": "The Cerenovus points to a player, then to a character on their sheet. That player should “be mad about” being that character. Wake that player. Show the “This character selected you” card, then the Cerenovus token. Show the “mad about being” marker, then that character token.", - "otherNight": 13, - "otherNightReminder": "The Cerenovus points to a player, then to a character on their sheet. That player should “be mad about” being that character. Wake that player. Show the “This character selected you” card, then the Cerenovus token. Show the “mad about being” marker, then that character token.", - "reminders": [ - "Mad" - ], - "setup": false, "name": "Cerenovus", + "edition": "snv", "team": "minion", - "ability": "Each night, choose a player and a good character: they are \"mad\", they are this character tomorrow, or might be executed." + "firstNight": 17, + "firstNightReminder": "The Cerenovus points to a player, then to a character on their sheet. Wake that player. Show the 'This character selected you' card, then the Cerenovus token. Show the selected character token. If the player is not mad about being that character tomorrow, they can be executed.", + "otherNight": 13, + "otherNightReminder": "The Cerenovus points to a player, then to a character on their sheet. Wake that player. Show the 'This character selected you' card, then the Cerenovus token. Show the selected character token. If the player is not mad about being that character tomorrow, they can be executed.", + "reminders": ["Mad"], + "setup": false, + "ability": "Each night, choose a player & a good character: they are \u201Cmad\u201D they are this character tomorrow, or might be executed." }, { "id": "pithag", + "name": "Pit-Hag", "edition": "snv", + "team": "minion", "firstNight": 0, "firstNightReminder": "", "otherNight": 14, - "otherNightReminder": "", + "otherNightReminder": "The Pit-Hag points to a player and a character on the sheet. If this character is not in play, wake that player and show them the 'You are' card and the relevant character token. If the character is in play, nothing happens.", "reminders": [], "setup": false, - "name": "Pit-Hag", - "team": "minion", - "ability": "Each night*, choose a player and a character they become (if not-in-play). If a Demon is made, deaths tonight are arbitrary." + "ability": "Each night*, choose a player & a character they become (if not-in-play). If a Demon is made, deaths tonight are arbitrary." }, { "id": "fanggu", + "name": "Fang Gu", "edition": "snv", + "team": "demon", "firstNight": 0, "firstNightReminder": "", - "otherNight": 24, - "otherNightReminder": "The Fang Gu points to a player. That player dies. If that player was an Outsider: • The Fang Gu dies instead of the chosen player. The chosen player is now an evil Fang Gu. • Wake the new Fang Gu. Show the “You are” card, then the Fang Gu token. Show the “You are” card, then the thumb-down “evil” hand sign.", - "reminders": [ - "Die" - ], + "otherNight": 25, + "otherNightReminder": "The Fang Gu points to a player. That player dies. Or, if that player was an Outsider and there are no other Fang Gu in play: The Fang Gu dies instead of the chosen player. The chosen player is now an evil Fang Gu. Wake the new Fang Gu. Show the 'You are' card, then the Fang Gu token. Show the 'You are' card, then the thumb-down 'evil' hand sign.", + "reminders": ["Dead"], "setup": true, - "name": "Fang Gu", - "team": "demon", "ability": "Each night*, choose a player: they die. The 1st Outsider this kills becomes an evil Fang Gu & you die instead. [+1 Outsider]" }, { "id": "vigormortis", + "name": "Vigormortis", "edition": "snv", + "team": "demon", "firstNight": 0, "firstNightReminder": "", - "otherNight": 27, + "otherNight": 28, "otherNightReminder": "The Vigormortis points to a player. That player dies. If a Minion, they keep their ability and one of their Townsfolk neighbours is poisoned.", - "reminders": [ - "Die", - "Poisoned", - "Ability active" - ], + "reminders": ["Dead", + "Has ability", + "Poisoned"], "setup": true, - "name": "Vigormortis", - "team": "demon", - "ability": "Each night*, choose a player: they die. Minions you kill keep their ability and poison 1 Townsfolk neighbor. [-1 Outsider]." + "ability": "Each night*, choose a player: they die. Minions you kill keep their ability & poison 1 Townsfolk neighbour. [\u22121 Outsider]" }, { "id": "nodashii", - "edition": "snv", - "firstNight": 0, - "firstNightReminder": "", - "otherNight": 25, - "otherNightReminder": "The No Dashii points to a player. That player dies.", - "reminders": [ - "Die", - "Poisoned" - ], - "setup": false, "name": "No Dashii", - "team": "demon", - "ability": "Each night*, choose a player: they die. Your 2 Townsfolk neighbors are poisoned." - }, - { - "id": "vortox", "edition": "snv", + "team": "demon", "firstNight": 0, "firstNightReminder": "", "otherNight": 26, - "otherNightReminder": "The Vortox points to a player. That player dies.", - "reminders": [ - "Die" - ], + "otherNightReminder": "The No Dashii points to a player. That player dies.", + "reminders": ["Dead", + "Poisoned"], "setup": false, + "ability": "Each night*, choose a player: they die. Your 2 Townsfolk neighbours are poisoned." + }, + { + "id": "vortox", "name": "Vortox", + "edition": "snv", "team": "demon", - "ability": "Each night*, choose a player; they die. Townsfolk abilities yield false info. Each day, if no-one was executed, evil wins." + "firstNight": 0, + "firstNightReminder": "", + "otherNight": 27, + "otherNightReminder": "The Vortox points to a player. That player dies.", + "reminders": ["Dead"], + "setup": false, + "ability": "Each night*, choose a player; they die. Townsfolk abilities yield false info. Each day, if no-one is executed, evil wins." }, { - "id": "scapegoat", - "edition": "tb", + "id": "barista", + "name": "Barista", + "edition": "snv", + "team": "traveler", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", - "reminders": [], + "reminders": ["Sober & Healthy", + "Ability twice"], "setup": false, - "name": "Scapegoat", - "team": "traveler", - "ability": "If a player of your alignment is executed, you might be executed instead." + "ability": "Each night, until dusk, 1) a player becomes sober, healthy and gets true info, or 2) their ability works twice. They learn which." }, { - "id": "gunslinger", - "edition": "tb", + "id": "harlot", + "name": "Harlot", + "edition": "snv", + "team": "traveler", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, - "otherNightReminder": "", - "reminders": [], + "otherNightReminder": "The Harlot points at any player. Then, put the Harlot to sleep. Wake the chosen player, show them the 'This character selected you' token, then the Harlot token. That player either nods their head yes or shakes their head no. If they nodded their head yes, wake the Harlot and show them the chosen player's character token. Then, you may decide that both players die.", + "reminders": ["Dead"], "setup": false, - "name": "Gunslinger", - "team": "traveler", - "ability": "Each day, after the 1st vote has been tallied, you may choose a player that voted: they die." - }, - { - "id": "beggar", - "edition": "tb", - "firstNight": 0, - "firstNightReminder": "", - "otherNight": 0, - "otherNightReminder": "", - "reminders": [], - "setup": false, - "name": "Beggar", - "team": "traveler", - "ability": "You must use a vote token to vote. Dead players may choose to give you theirs. If so, you learn their alignment." - }, - { - "id": "bureaucrat", - "edition": "tb", - "firstNight": 1, - "firstNightReminder": "The Bureaucrat points to a player. Put the Bureaucrat's “Vote x3” reminder by the chosen player's character token.", - "otherNight": 1, - "otherNightReminder": "The Bureaucrat points to a player. Put the Bureaucrat's “Vote x3” reminder by the chosen player's character token.", - "reminders": [ - "Vote x3" - ], - "setup": false, - "name": "Bureaucrat", - "team": "traveler", - "ability": "Each night, choose a player (not yourself): their vote counts as 3 votes tomorrow." - }, - { - "id": "thief", - "edition": "tb", - "firstNight": 1, - "firstNightReminder": "The Thief points to a player. Put the Thief's “Negative vote” reminder by the chosen player's character token.", - "otherNight": 1, - "otherNightReminder": "The Thief points to a player. Put the Thief's “Negative vote” reminder by the chosen player's character token.", - "reminders": [ - "Negative vote" - ], - "setup": false, - "name": "Thief", - "team": "traveler", - "ability": "Each night, choose a player (not yourself): their vote counts negatively tomorrow." - }, - { - "id": "apprentice", - "edition": "bmr", - "firstNight": 1, - "firstNightReminder": "Show the Apprentice the \"You are\" info token, then a Townsfolk or Minion token. In the Grimoire, replace the Apprentice token with that character token, and put the Apprentice's \"Apprentice ability\" reminder by that character token.", - "otherNight": 0, - "otherNightReminder": "", - "reminders": [ - "Apprentice ability" - ], - "setup": false, - "name": "Apprentice", - "team": "traveler", - "ability": "On your 1st night, you gain a Townsfolk ability (if good), or a Minion ability (if evil)." - }, - { - "id": "matron", - "edition": "bmr", - "firstNight": 0, - "firstNightReminder": "", - "otherNight": 0, - "otherNightReminder": "", - "reminders": [], - "setup": false, - "name": "Matron", - "team": "traveler", - "ability": "Each day, you may choose up to 3 pairs of players to swap seats. Players may not leave their seats to talk in private." - }, - { - "id": "voudon", - "edition": "bmr", - "firstNight": 0, - "firstNightReminder": "", - "otherNight": 0, - "otherNightReminder": "", - "reminders": [], - "setup": false, - "name": "Voudon", - "team": "traveler", - "ability": "Only you and the dead can vote. They don't need a vote token to do so. A 50% majority is not required." - }, - { - "id": "judge", - "edition": "bmr", - "firstNight": 0, - "firstNightReminder": "", - "otherNight": 0, - "otherNightReminder": "", - "reminders": [ - "Used" - ], - "setup": false, - "name": "Judge", - "team": "traveler", - "ability": "Once per game, if another player nominated, you may choose to force the current execution to pass or fail." - }, - { - "id": "bishop", - "edition": "bmr", - "firstNight": 0, - "firstNightReminder": "", - "otherNight": 0, - "otherNightReminder": "", - "reminders": [ - "Nominate Good", - "Nominate Evil" - ], - "setup": false, - "name": "Bishop", - "team": "traveler", - "ability": "Only the Storyteller can nominate. At least 1 opposite player must be nominated each day." + "ability": "Each night*, choose a living player: if they agree, you learn their character, but you both might die." }, { "id": "butcher", + "name": "Butcher", "edition": "snv", + "team": "traveler", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", "reminders": [], "setup": false, - "name": "Butcher", - "team": "traveler", "ability": "Each day, after the 1st execution, you nominate again." }, { "id": "bonecollector", + "name": "Bone Collector", "edition": "snv", + "team": "traveler", "firstNight": 0, "firstNightReminder": "", - "otherNight": 1, - "otherNightReminder": "The Bone Collector either shake their head no or point at any dead player. If they pointed at any dead player, put the Bone Collector's \"Has Ability\" reminder by the chosen player's character token. (They may need to be woken tonight to use it.)", - "reminders": [ - "Used", - "Has Ability" - ], + "otherNight": 0, + "otherNightReminder": "The Bone Collector either shakes their head no or points at any dead player. If they pointed at any dead player, put the Bone Collector's 'Has Ability' reminder by the chosen player's character token. (They may need to be woken tonight to use it.)", + "reminders": ["No ability", + "Has ability"], "setup": false, - "name": "Bone Collector", - "team": "traveler", "ability": "Once per game, at night, choose a dead player: they regain their ability until dusk." }, - { - "id": "harlot", - "edition": "snv", - "firstNight": 0, - "firstNightReminder": "", - "otherNight": 1, - "otherNightReminder": "The Harlot points at any player. Then, put the Harlot to sleep. Wake the chosen player, show them the \"This character selected you\" token, then the Harlot token. That player either nods their head yes or shakes their head no. If they nodded their head yes, wake the Harlot and show them the chosen player's character token. Then, you may decide that both players die.", - "reminders": [ - "Die" - ], - "setup": false, - "name": "Harlot", - "team": "traveler", - "ability": "Each night*, choose a living player: if they agree, you learn their character, but you both might die." - }, - { - "id": "barista", - "edition": "snv", - "firstNight": 1, - "firstNightReminder": "Each night, put the Barista's \"Sober and Healthy\" reminder or their \"Acts Twice\" reminder by any character token. Wake that character’s player and show them the “This player selected you” info token, then the Barista token, then one finger (to show they are sober and healthy) or two fingers (to show they act twice).", - "otherNight": 1, - "otherNightReminder": "Each night, put the Barista's \"Sober and Healthy\" reminder or their \"Acts Twice\" reminder by any character token. Wake that character’s player and show them the “This player selected you” info token, then the Barista token, then one finger (to show they are sober and healthy) or two fingers (to show they act twice).", - "reminders": [ - "Acts Twice", - "Sober and Healthy" - ], - "setup": false, - "name": "Barista", - "team": "traveler", - "ability": "Each night, until dusk, 1) a player becomes sober, healthy and gets true info, or 2) their ability works twice. They learn which." - }, { "id": "deviant", + "name": "Deviant", "edition": "snv", + "team": "traveler", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", "reminders": [], "setup": false, - "name": "Deviant", - "team": "traveler", "ability": "If you were funny today, you can not be exiled." }, { - "id": "balloonist", + "id": "bountyhunter", + "name": "Bounty Hunter", "edition": "", - "firstNight": 30, - "firstNightReminder": "Choose a character type. Point to a player whose character is of that type. Place the Balloonist's \"Seen\" reminder next to that character.", - "otherNight": 47, - "otherNightReminder": "Choose a character type you have not chosen yet. Point to a player whose character is of that type, if there are any. Place the Balloonist's \"Seen\" reminder next to that character.", - "reminders": [ - "Seen Townsfolk", - "Seen Outsider", - "Seen Minion", - "Seen Demon" - ], - "setup": true, - "name": "Balloonist", "team": "townsfolk", + "firstNight": 31, + "firstNightReminder": "Point to 1 evil player. Wake the townsfolk who is evil and show them the 'You are' card and the thumbs down evil sign.", + "otherNight": 54, + "otherNightReminder": "If the known evil player has died, point to another evil player. ", + "reminders": ["Known"], + "setup": true, + "ability": "You start knowing 1 evil player. If the player you know dies, you learn another evil player tonight. [1 Townsfolk is evil]" + }, + { + "id": "preacher", + "name": "Preacher", + "edition": "", + "team": "townsfolk", + "firstNight": 7, + "firstNightReminder": "The Preacher chooses a player. If a Minion is chosen, wake the Minion and show the 'This character selected you' card and then the Preacher token.", + "otherNight": 4, + "otherNightReminder": "The Preacher chooses a player. If a Minion is chosen, wake the Minion and show the 'This character selected you' card and then the Preacher token.", + "reminders": ["At a sermon"], + "setup": false, + "ability": "Each night, choose a player: a Minion, if chosen, learns this. All chosen Minions have no ability." + }, + { + "id": "general", + "name": "General", + "edition": "", + "team": "townsfolk", + "firstNight": 34, + "firstNightReminder": "Show the General thumbs up for good winning, thumbs down for evil winning or thumb to the side for neither.", + "otherNight": 57, + "otherNightReminder": "Show the General thumbs up for good winning, thumbs down for evil winning or thumb to the side for neither.", + "reminders": [], + "setup": false, + "ability": "Each night, you learn which alignment the Storyteller believes is winning: good, evil, or neither." + }, + { + "id": "balloonist", + "name": "Balloonist", + "edition": "", + "team": "townsfolk", + "firstNight": 30, + "firstNightReminder": "Choose a character type. Point to a player whose character is of that type. Place the Balloonist's Seen reminder next to that character.", + "otherNight": 53, + "otherNightReminder": "Choose a character type that does not yet have a Seen reminder next to a character of that type. Point to a player whose character is of that type, if there are any. Place the Balloonist's Seen reminder next to that character.", + "reminders": ["Seen Townsfolk", + "Seen Outsider", + "Seen Minion", + "Seen Demon", + "Seen Traveller"], + "setup": true, "ability": "Each night, you learn 1 player of each character type, until there are no more types to learn. [+1 Outsider]" }, { - "id": "amnesiac", + "id": "cultleader", + "name": "Cult Leader", "edition": "", + "team": "townsfolk", + "firstNight": 32, + "firstNightReminder": "If the cult leader changed alignment, show them the thumbs up good signal of the thumbs down evil signal accordingly.", + "otherNight": 55, + "otherNightReminder": "If the cult leader changed alignment, show them the thumbs up good signal of the thumbs down evil signal accordingly.", + "reminders": [], + "setup": false, + "ability": "Each night, you become the alignment of an alive neighbour. If all good players choose to join your cult, your team wins." + }, + { + "id": "lycanthrope", + "name": "Lycanthrope", + "edition": "", + "team": "townsfolk", + "firstNight": 0, + "firstNightReminder": "", + "otherNight": 16, + "otherNightReminder": "The Lycanthrope points to a living player: if good, they die and no one else can die tonight.", + "reminders": ["Dead"], + "setup": false, + "ability": "Each night*, choose a living player: if good, they die, but they are the only player that can die tonight." + }, + { + "id": "amnesiac", + "name": "Amnesiac", + "edition": "", + "team": "townsfolk", "firstNight": 6, "firstNightReminder": "Decide the Amnesiac's entire ability. If the Amnesiac's ability causes them to wake tonight: Wake the Amnesiac and run their ability.", "otherNight": 3, "otherNightReminder": "If the Amnesiac's ability causes them to wake tonight: Wake the Amnesiac and run their ability.", - "reminders": [], + "reminders": ["?"], "setup": false, - "name": "Amnesiac", - "team": "townsfolk", "ability": "You do not know what your ability is. Each day, privately guess what it is: you learn how accurate you are." }, - { - "id": "cannibal", - "edition": "", - "firstNight": 0, - "firstNightReminder": "", - "otherNight": 0, - "otherNightReminder": "", - "reminders": [ - "Ability gained", - "Poisoned" - ], - "setup": false, - "name": "Cannibal", - "team": "townsfolk", - "ability": "You have the ability of the recently killed executee. If they are evil, you are poisoned until a good player dies this way." - }, { "id": "fisherman", + "name": "Fisherman", "edition": "", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", - "reminders": [ - "Used" - ], + "reminders": ["No ability"], "setup": false, - "name": "Fisherman", - "team": "townsfolk", "ability": "Once per game, during the day, visit the Storyteller for some advice to help you win." }, { - "id": "goblin", + "id": "cannibal", + "name": "Cannibal", "edition": "", + "team": "townsfolk", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, - "otherNightReminder": "", - "reminders": [ - "Claimed today" - ], + "otherNightReminder": "Wake the cannibal when the character who was executed today would wake", + "reminders": ["Poisoned", + "Died today"], "setup": false, - "name": "Goblin", - "team": "minion", - "ability": "When nominated, you may publicly claim to be the Goblin: if you are executed that day, your team wins." - }, - { - "id": "widow", - "edition": "", - "firstNight": 10, - "firstNightReminder": "Show the Grimoire to the Widow for as long as they need. The Widow points to a player. That player is poisoned. Wake a good player. Show the “These characters are in play” card, then the Widow character token.", - "otherNight": 0, - "otherNightReminder": "", - "reminders": [ - "Poisoned", - "Knowing" - ], - "setup": false, - "name": "Widow", - "team": "minion", - "ability": "On your 1st night, look at the Grimoire and choose a player: they are poisoned. 1 good player knows a Widow is in play." - }, - { - "id": "leviathan", - "edition": "", - "firstNight": 38, - "firstNightReminder": "Place the Leviathan “Day 1” marker. Announce “The Leviathan is in play; this is Day 1.”.", - "otherNight": 100, - "otherNightReminder": "Place the next Leviathan “Day n” marker, where “n” is the day number. Announce “The Leviathan is in play; this is Day n.”.", - "reminders": [ - "Good executed", - "Day 1", - "Day 2", - "Day 3", - "Day 4", - "Day 5" - ], - "setup": false, - "name": "Leviathan", - "team": "demon", - "ability": "All players know you are in play. After 5 days, evil wins. If more than 1 good player is executed, evil wins." + "ability": "You have the ability of the recently killed executee. If they are evil, you are poisoned until a good player dies by execution." }, { "id": "acrobat", - "edition": "", - "firstNight": 0, - "firstNightReminder": "", - "otherNight": 21, - "otherNightReminder": "If either good living neighbor is drunk or poisoned, the Acrobat dies.", - "reminders": [ - "Die" - ], - "setup": false, "name": "Acrobat", + "edition": "", "team": "outsider", - "ability": "Each night*, if either good living neighbor is drunk or poisoned, you die." - }, - { - "id": "bountyhunter", - "edition": "", - "firstNight": 31, - "firstNightReminder": "Point to a player that is evil.", - "otherNight": 53, - "otherNightReminder": "If the evil player that was known by the Bounty Hunter died since the previous night: Point to another player that is evil.", - "reminders": [ - "Known" - ], - "setup": true, - "name": "Bounty Hunter", - "team": "townsfolk", - "ability": "You start knowing 1 evil player. If the evil player you know dies, you learn another that night. [1 Townsfolk is evil]" - }, - { - "id": "cultleader", - "edition": "", - "firstNight": 32, - "firstNightReminder": "The Cult Leader becomes the alignment of an alive neighbor: Show the “You are” card. Show the hand signal (thumb-up “good”, thumb-down “evil”) for the Cult Leader's current alignment.", - "otherNight": 54, - "otherNightReminder": "The Cult Leader becomes the alignment of an alive neighbor: Show the “You are” card. Show the hand signal (thumb-up “good”, thumb-down “evil”) for the Cult Leader's current alignment.", - "reminders": [], + "firstNight": 0, + "firstNightReminder": "If a good living neighbour is drunk or poisoned, the Acrobat player dies.", + "otherNight": 22, + "otherNightReminder": "If a good living neighbour is drunk or poisoned, the Acrobat player dies.", + "reminders": ["Dead"], "setup": false, - "name": "Cult Leader", - "team": "townsfolk", - "ability": "Each night, you become the alignment of an alive neighbor. If all good players choose to join your cult, your team wins." - }, - { - "id": "preacher", - "edition": "", - "firstNight": 7, - "firstNightReminder": "The Preacher points to a player. If that player is a Minion: Wake the Minion. Show the Preacher token. The Minion now does not have an ability anymore.", - "otherNight": 4, - "otherNightReminder": "The Preacher points to a player. If that player is a Minion: Wake the Minion. Show the Preacher token. The Minion now does not have an ability anymore.", - "reminders": [ - "No ability" - ], - "setup": false, - "name": "Preacher", - "team": "townsfolk", - "ability": "Each night, choose a player: a Minion, if chosen, learns this. All chosen Minions have no ability." + "ability": "Each night*, if either good living neighbour is drunk or poisoned, you die." }, { "id": "politician", + "name": "Politician", "edition": "", + "team": "outsider", "firstNight": 0, "firstNightReminder": "", "otherNight": 0, "otherNightReminder": "", "reminders": [], "setup": false, - "name": "Politician", - "team": "outsider", "ability": "If you were the player most responsible for your team losing, you change alignment & win, even if dead." }, { - "id": "lilmonsta", + "id": "widow", + "name": "Widow", "edition": "", - "firstNight": 8, - "firstNightReminder": "Wake all Minions. The Minions point to a player that receives the Lil' Monsta token and becomes the Demon.", - "otherNight": 27, - "otherNightReminder": "Wake all Minions. The Minions point to a player that receives the Lil' Monsta token and becomes the Demon. Choose a player that dies.", - "reminders": [], - "remindersGlobal": [ - "Die", - "The Demon" - ], - "setup": true, - "name": "Lil' Monsta", - "team": "demon", - "ability": "Each night, Minions choose who babysits Lil' Monsta's token & “is the Demon”. A player dies each night*. [+1 Minion]" + "team": "minion", + "firstNight": 10, + "firstNightReminder": "Show the Grimoire to the Widow for as long as they need. The Widow points to a player. That player is poisoned. Wake a good player. Show the 'These characters are in play' card, then the Widow character token.", + "otherNight": 0, + "otherNightReminder": "", + "reminders": ["Poisoned", + "Knows"], + "setup": false, + "ability": "On your 1st night, look at the Grimoire and choose a player: they are poisoned. 1 good player knows a Widow is in play." }, { - "id": "general", + "id": "goblin", + "name": "Goblin", "edition": "", - "firstNight": 34, - "firstNightReminder": "Show the hand signal (thumb-up “good”, thumb-down “evil”, thumb-sideways “neither”) for the alignment that you believe is winning.", - "otherNight": 56, - "otherNightReminder": "Show the hand signal (thumb-up “good”, thumb-down “evil”, thumb-sideways “neither”) for the alignment that you believe is winning.", - "reminders": [], - "remindersGlobal": [], + "team": "minion", + "firstNight": 0, + "firstNightReminder": "", + "otherNight": 0, + "otherNightReminder": "", + "reminders": ["Claimed"], "setup": false, - "name": "General", - "team": "townsfolk", - "ability": "Each night, you learn which alignment the Storyteller believes is winning: good, evil, or neither." + "ability": "If you publicly claim to be the Goblin when nominated & are executed that day, your team wins." + }, + { + "id": "lilmonsta", + "name": "Lil Monsta", + "edition": "", + "team": "demon", + "firstNight": 8, + "firstNightReminder": "", + "otherNight": 29, + "otherNightReminder": "Choose a player, that player dies.", + "reminders": ["Dead", + "Is the Demon"], + "setup": true, + "ability": "Each night, Minions choose who babysits Lil Monsta's token & \"is the Demon\". A player dies each night*. [+1 Minion]" + }, + { + "id": "leviathan", + "name": "Leviathan", + "edition": "", + "team": "demon", + "firstNight": 38, + "firstNightReminder": "Place the Leviathan 'Day 1' marker. Announce 'The Leviathan is in play; this is Day 1.'", + "otherNight": 0, + "otherNightReminder": "Place the next Leviathan 'Day n' marker, where 'n' is the next day number. Announce 'The Leviathan is in play; this is Day n.'.", + "reminders": ["Day 1", + "Day 2", + "Day 3", + "Day 4", + "Day 5", + "Good player executed"], + "setup": false, + "ability": "If more than 1 good player is executed, you win. All players know you are in play. After day 5, evil wins." } ] + From 9bd959c2a2e6c74c9d213b0acc45b5ed4f18efa3 Mon Sep 17 00:00:00 2001 From: Steffen Date: Thu, 7 Jan 2021 23:06:11 +0100 Subject: [PATCH 20/62] changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f54c923..ef0bbfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Release Notes +## Version 2.3.0 +- added spoiler role (Lycanthrope!) +- fixed copy to clipboard in Firefox +- fixed non-countdown votes still playing countdown sound for a split second + +--- + ## Version 2.2.1 - clearing players / roles now also clears Fabled (closes #85) - fix list of locked votes showing unlocked votes sometimes @@ -18,6 +25,7 @@ - fixed global reminders not showing up anymore when the associated role is assigned to a player - adjusted backend metrics + --- ## Version 2.1.0 From 012954f7f464c93e4dc686123af1ed551c0b66f7 Mon Sep 17 00:00:00 2001 From: Steffen Date: Thu, 7 Jan 2021 23:06:25 +0100 Subject: [PATCH 21/62] 2.3.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index ec3e314..8357c6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "townsquare", - "version": "2.2.1", + "version": "2.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 117ffff..e93d0aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "townsquare", - "version": "2.2.1", + "version": "2.3.0", "description": "Blood on the Clocktower Town Square", "author": "Steffen Baumgart", "scripts": { From c1db6aa4479d965d307532816278a2068a0c7a17 Mon Sep 17 00:00:00 2001 From: Dave Date: Fri, 8 Jan 2021 17:55:46 +0000 Subject: [PATCH 22/62] adding propertie to state for travelers not in the selected edition --- src/store/index.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/store/index.js b/src/store/index.js index eea3ae8..ac50082 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -25,6 +25,15 @@ const getRolesByEdition = (edition = editionJSON[0]) => { ); }; +const getTravelersNotInEdition = (edition = editionJSON[0]) => { + return new Map( + rolesJSON + .filter(r => r.team === "traveler") + .filter(r => r.edition !== edition.id || !edition.roles.includes(r.id)) + .map(role => [role.id, role]) + ); +}; + // base definition for custom roles const imageBase = "https://raw.githubusercontent.com/bra1n/townsquare/main/src/assets/icons/"; @@ -70,6 +79,7 @@ export default new Vuex.Store({ }, edition: editionJSONbyId.get("tb"), roles: getRolesByEdition(), + extraTravelers: getTravelersNotInEdition(), fabled }, getters: { From 0df7d8386d53e45b76eaf159676c1f6fc24b7fed Mon Sep 17 00:00:00 2001 From: Dave Date: Fri, 8 Jan 2021 18:35:22 +0000 Subject: [PATCH 23/62] making non edition travelers appear in roleModal --- src/components/modals/RoleModal.vue | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/components/modals/RoleModal.vue b/src/components/modals/RoleModal.vue index cd0f520..87f6d94 100644 --- a/src/components/modals/RoleModal.vue +++ b/src/components/modals/RoleModal.vue @@ -20,6 +20,14 @@ >

  • +
  • + +
  • @@ -33,6 +41,20 @@ export default { components: { Token, Modal }, props: ["playerIndex"], computed: { + extraTravelers() { + const extraTravelers = []; + const players = this.$store.state.players.players; + this.$store.state.extraTravelers.forEach(role => { + if ( + this.playerIndex >= 0 || + (this.playerIndex < 0 && + !players.some(player => player.role.id === role.id)) + ) { + extraTravelers.push(role); + } + }); + return extraTravelers; + }, availableRoles() { const availableRoles = []; const players = this.$store.state.players.players; From 7396a4574e8fba360000f977db9534a17751bb75 Mon Sep 17 00:00:00 2001 From: Jul Gvoz Date: Sat, 9 Jan 2021 00:46:34 +0200 Subject: [PATCH 24/62] Clearer majority representation --- src/components/modals/VoteHistoryModal.vue | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/components/modals/VoteHistoryModal.vue b/src/components/modals/VoteHistoryModal.vue index df43c1d..ae2d7e1 100644 --- a/src/components/modals/VoteHistoryModal.vue +++ b/src/components/modals/VoteHistoryModal.vue @@ -20,7 +20,7 @@ Type Votes Hand up - Passed + Majority @@ -28,13 +28,18 @@ {{ vote.nominator }} {{ vote.nominee }} {{ vote.type }} - {{ vote.votes.length }} / {{ vote.majority }} + {{ vote.votes.length }} {{ vote.votes.join(", ") }} - + + From ea574fcc58ebaa085f5a8812ec0482e01f825782 Mon Sep 17 00:00:00 2001 From: Dave Date: Sat, 9 Jan 2021 00:21:45 +0000 Subject: [PATCH 25/62] cleaning up code pulling non edition travellers in to the role modal and fixing spelling of travellers --- src/components/modals/RoleModal.vue | 17 +++-------------- src/store/index.js | 4 ++-- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/components/modals/RoleModal.vue b/src/components/modals/RoleModal.vue index 87f6d94..b55bd39 100644 --- a/src/components/modals/RoleModal.vue +++ b/src/components/modals/RoleModal.vue @@ -21,7 +21,7 @@
  • { - if ( - this.playerIndex >= 0 || - (this.playerIndex < 0 && - !players.some(player => player.role.id === role.id)) - ) { - extraTravelers.push(role); - } - }); - return extraTravelers; + extraTravellers() { + return [...this.$store.state.extraTravellers.values()]; }, availableRoles() { const availableRoles = []; diff --git a/src/store/index.js b/src/store/index.js index ac50082..61ea65c 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -25,7 +25,7 @@ const getRolesByEdition = (edition = editionJSON[0]) => { ); }; -const getTravelersNotInEdition = (edition = editionJSON[0]) => { +const getTravellersNotInEdition = (edition = editionJSON[0]) => { return new Map( rolesJSON .filter(r => r.team === "traveler") @@ -79,7 +79,7 @@ export default new Vuex.Store({ }, edition: editionJSONbyId.get("tb"), roles: getRolesByEdition(), - extraTravelers: getTravelersNotInEdition(), + extraTravellers: getTravellersNotInEdition(), fabled }, getters: { From 016d7feb39555e8d22148c95089f177be0a34ebd Mon Sep 17 00:00:00 2001 From: Dave Date: Sat, 9 Jan 2021 13:23:59 +0000 Subject: [PATCH 26/62] adding tabs to role modal and moving non edition travellers in to second tab --- src/components/modals/RoleModal.vue | 59 +++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/src/components/modals/RoleModal.vue b/src/components/modals/RoleModal.vue index b55bd39..e908ca2 100644 --- a/src/components/modals/RoleModal.vue +++ b/src/components/modals/RoleModal.vue @@ -11,23 +11,41 @@ : "bluffing" }} -
      -
    • - -
    • -
    • - +
        +
      • + Edtition Roles + Other Travellers
      • +
          +
        • + +
        • +
        +
          +
        • + +
        • +
      @@ -63,6 +81,11 @@ export default { ...mapState(["modals", "roles", "session"]), ...mapState("players", ["players"]) }, + data() { + return { + tab: "editionRoles" + }; + }, methods: { setRole(role) { if (this.playerIndex < 0) { @@ -118,6 +141,10 @@ ul.tokens li { } } +.button.active { + background: linear-gradient(to bottom, $townsfolk 0%, rgba(0, 0, 0, 0.7) 100%); +} + #townsquare.spectator ul.tokens li.traveler { display: none; } From 7ab4bcbc4d8d24ce1b0cecda7332cf65117cbf24 Mon Sep 17 00:00:00 2001 From: Dave Date: Sat, 9 Jan 2021 13:34:01 +0000 Subject: [PATCH 27/62] Hiding additional traveller roles when selecting bluffs as travellers will not be used as bluffs anyway. --- src/components/modals/RoleModal.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/modals/RoleModal.vue b/src/components/modals/RoleModal.vue index e908ca2..c90b562 100644 --- a/src/components/modals/RoleModal.vue +++ b/src/components/modals/RoleModal.vue @@ -12,7 +12,7 @@ }}
        -
      • +
      • 0; + }, ...mapMutations(["toggleModal"]) } }; From af0d944d4520c9f9ef95852efc5e8971211cda2e Mon Sep 17 00:00:00 2001 From: Dave Date: Sat, 9 Jan 2021 13:42:25 +0000 Subject: [PATCH 28/62] linting fix --- src/components/modals/RoleModal.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/modals/RoleModal.vue b/src/components/modals/RoleModal.vue index c90b562..e483c89 100644 --- a/src/components/modals/RoleModal.vue +++ b/src/components/modals/RoleModal.vue @@ -145,7 +145,11 @@ ul.tokens li { } .button.active { - background: linear-gradient(to bottom, $townsfolk 0%, rgba(0, 0, 0, 0.7) 100%); + background: linear-gradient( + to bottom, + $townsfolk 0%, + rgba(0, 0, 0, 0.7) 100% + ); } #townsquare.spectator ul.tokens li.traveler { From f6a7cbaf28858ba2d6acfafdef6929e3620e8a73 Mon Sep 17 00:00:00 2001 From: Steffen Date: Sat, 9 Jan 2021 21:32:52 +0100 Subject: [PATCH 29/62] adjusted player menu styling for smaller screens (fixes #88) --- src/components/Player.vue | 2 +- src/media.scss | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/Player.vue b/src/components/Player.vue index ecfd808..91f8f5a 100644 --- a/src/components/Player.vue +++ b/src/components/Player.vue @@ -675,7 +675,7 @@ li.move:not(.from) .player .overlay svg.move { border: 10px solid transparent; border-right-color: black; right: 100%; - bottom: 7px; + bottom: 5px; margin-right: 2px; } diff --git a/src/media.scss b/src/media.scss index 85269dd..a42afbe 100644 --- a/src/media.scss +++ b/src/media.scss @@ -44,6 +44,12 @@ .player > .name { top: 0; } + .player > .menu { + bottom: 0; + &:before { + bottom: 0; + } + } } // Old phones From 292300523d00eec08c305a5e26147cac490a76ef Mon Sep 17 00:00:00 2001 From: Steffen Date: Sat, 9 Jan 2021 21:33:09 +0100 Subject: [PATCH 30/62] linting and details on hosting your own fork --- CONTRIBUTING.md | 22 ++++++++++++++++++++++ src/components/modals/VoteHistoryModal.vue | 12 ++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 00c34d2..cea9e5e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,6 +43,20 @@ $ npm install The development server can be started with `npm run serve`. +### Deploying to GitHub pages or with a non-root path + +Deploying a forked version to GitHub Pages or running your local +development copy in a sub-path (instead of the web root) will require you to modify +the `vue.config.js` and configure the path at which the website will be served. + +For example, deploying your forked `townsquare` project to GitHub pages would need the following +`vue.config.js` changes: +```js +module.exports = { + publicPath: process.env.NODE_ENV === "production" ? "/townsquare/" : "/" +}; +``` + ### Committing Changes Commit messages should be verbose enough to allow someone else to follow your changes and should include references to issues that are being worked on. @@ -64,6 +78,10 @@ $ npm run lint - **`dist`**: contains built files for distribution. +- **`public`**: static assets and templates that don't need to be built dynamically. + +- **`server`**: NodeJS code for the live session backend server. + - **`src`**: contains the source code. The codebase is written in ES2015. - **`assets`**: contains all graphical assets like images, fonts, icons, etc. @@ -73,9 +91,13 @@ $ npm run lint - **`fonts`**: webfonts used on the page - **`icons`**: character token icons + + - **`sounds`**: sound effects used on the page - **`components`**: the internal components used in the project - **`modals`**: the modals have a separate subfolder - **`store`**: the VueX data store and modules + + - **`modules`**: VueX modules that live in their own namespace diff --git a/src/components/modals/VoteHistoryModal.vue b/src/components/modals/VoteHistoryModal.vue index 8295ea6..93afa6a 100644 --- a/src/components/modals/VoteHistoryModal.vue +++ b/src/components/modals/VoteHistoryModal.vue @@ -30,8 +30,16 @@ - {{ vote.timestamp.getHours().toString().padStart(2, "0") }}:{{ - vote.timestamp.getMinutes().toString().padStart(2, "0") + {{ + vote.timestamp + .getHours() + .toString() + .padStart(2, "0") + }}:{{ + vote.timestamp + .getMinutes() + .toString() + .padStart(2, "0") }} {{ vote.nominator }} From c10c28d4634c2fe5be519e2a925043dea8173325 Mon Sep 17 00:00:00 2001 From: Steffen Date: Sat, 9 Jan 2021 21:34:50 +0100 Subject: [PATCH 31/62] changelog --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef0bbfc..e5c52b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Release Notes +## Version 2.3.1 +- better vote history design and added timestamps +- adjusted player menu styling on smaller screens +- improved CONTRIBUTING.md description of hosting your own copy + +--- + ## Version 2.3.0 - added spoiler role (Lycanthrope!) - fixed copy to clipboard in Firefox @@ -8,7 +15,7 @@ --- ## Version 2.2.1 -- clearing players / roles now also clears Fabled (closes #85) +- clearing players / roles now also clears Fabled - fix list of locked votes showing unlocked votes sometimes --- From 2c47933dc5ea1a0d092593a9ab071c8f35d5e058 Mon Sep 17 00:00:00 2001 From: Steffen Date: Sat, 9 Jan 2021 21:35:02 +0100 Subject: [PATCH 32/62] 2.3.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8357c6e..95bf1bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "townsquare", - "version": "2.3.0", + "version": "2.3.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index e93d0aa..8a9c3c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "townsquare", - "version": "2.3.0", + "version": "2.3.1", "description": "Blood on the Clocktower Town Square", "author": "Steffen Baumgart", "scripts": { From 5700184fff352a8e8a7f7bc37127a06551ea9147 Mon Sep 17 00:00:00 2001 From: Dave Date: Sat, 9 Jan 2021 20:40:59 +0000 Subject: [PATCH 33/62] fixing filter logic in index state to correctly get travelers not in the currently selected edition. --- src/store/index.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index 61ea65c..3165dc2 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -28,8 +28,12 @@ const getRolesByEdition = (edition = editionJSON[0]) => { const getTravellersNotInEdition = (edition = editionJSON[0]) => { return new Map( rolesJSON - .filter(r => r.team === "traveler") - .filter(r => r.edition !== edition.id || !edition.roles.includes(r.id)) + .filter( + r => + r.team === "traveler" && + r.edition !== edition.id && + !edition.roles.includes(r.id) + ) .map(role => [role.id, role]) ); }; @@ -195,6 +199,7 @@ export default new Vuex.Store({ if (editionJSONbyId.has(edition.id)) { state.edition = editionJSONbyId.get(edition.id); state.roles = getRolesByEdition(state.edition); + state.extraTravellers = getTravellersNotInEdition(state.edition); } else { state.edition = edition; } From ce6b66a33ee6210f868f80a751510249d9ff5910 Mon Sep 17 00:00:00 2001 From: Dave Date: Sat, 9 Jan 2021 21:23:24 +0000 Subject: [PATCH 34/62] making roles modal reset selected tab on close, stops traveller tab from showing on bluff selection and a better user experience --- src/components/modals/RoleModal.vue | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/modals/RoleModal.vue b/src/components/modals/RoleModal.vue index e483c89..b113616 100644 --- a/src/components/modals/RoleModal.vue +++ b/src/components/modals/RoleModal.vue @@ -1,8 +1,5 @@