diff --git a/src/assets/icons/demon_info.png b/src/assets/icons/demon_info.png
new file mode 100644
index 0000000..f59435e
Binary files /dev/null and b/src/assets/icons/demon_info.png differ
diff --git a/src/assets/icons/minion_info.png b/src/assets/icons/minion_info.png
new file mode 100644
index 0000000..01a2092
Binary files /dev/null and b/src/assets/icons/minion_info.png differ
diff --git a/src/components/Menu.vue b/src/components/Menu.vue
index 46133ca..09f808d 100644
--- a/src/components/Menu.vue
+++ b/src/components/Menu.vue
@@ -87,7 +87,7 @@
Background image
-
+
Disable Animations
-
- Send Characters
-
-
[V]
- Leave Session
+ 退出房间
{{ session.sessionId }}
@@ -154,13 +150,13 @@
Players
- Add[A]
+ 添加座位[A]
- Randomize
+ 随机座位
- Remove all
+ 移除全部座位
@@ -169,22 +165,26 @@
Characters
- Select Edition
+ 选择剧本
[E]
- Choose & Assign
+ 分配角色
[C]
+
+ 发送角色
+
+
- Add Fabled
+ 传奇角色
- Remove all
+ 移除全部角色
@@ -193,11 +193,11 @@
Help
- Reference Sheet
+ 角色能力表
[R]
- Night Order Sheet
+ 夜晚顺序表
[N]
@@ -253,7 +253,7 @@ export default {
hostSession() {
if (this.session.sessionId) return;
const sessionId = prompt(
- "Enter a channel number / name for your session",
+ "输入你想要创建的房间的名称或号码",
Math.round(Math.random() * 10000)
);
if (sessionId) {
@@ -271,7 +271,7 @@ export default {
distributeRoles() {
if (this.session.isSpectator) return;
const popup =
- "Do you want to distribute assigned characters to all SEATED players?";
+ "你确定要向所有已入座的玩家发送角色吗?";
if (confirm(popup)) {
this.$store.commit("session/distributeRoles", true);
setTimeout(
@@ -292,7 +292,7 @@ export default {
joinSession() {
if (this.session.sessionId) return this.leaveSession();
let sessionId = prompt(
- "Enter the channel number / name of the session you want to join"
+ "输入你想要加入的房间的名称或号码"
);
if (sessionId.match(/^https?:\/\//i)) {
sessionId = sessionId.split("#").pop();
@@ -305,7 +305,7 @@ export default {
}
},
leaveSession() {
- if (confirm("Are you sure you want to leave the active live game?")) {
+ if (confirm("你确定要离开房间吗?")) {
this.$store.commit("session/setSpectator", false);
this.$store.commit("session/setSessionId", "");
}
@@ -320,13 +320,13 @@ export default {
},
randomizeSeatings() {
if (this.session.isSpectator) return;
- if (confirm("Are you sure you want to randomize seatings?")) {
+ if (confirm("你确定要打乱座位吗?")) {
this.$store.dispatch("players/randomize");
}
},
clearPlayers() {
if (this.session.isSpectator) return;
- if (confirm("Are you sure you want to remove all players?")) {
+ if (confirm("你确定要移除所有座位吗?")) {
// abort vote if in progress
if (this.session.nomination) {
this.$store.commit("session/nomination");
@@ -335,7 +335,7 @@ export default {
}
},
clearRoles() {
- if (confirm("Are you sure you want to remove all player roles?")) {
+ if (confirm("你确定要移除所有玩家的角色吗?")) {
this.$store.dispatch("players/clearRoles");
}
},
diff --git a/src/components/Player.vue b/src/components/Player.vue
index 65bdf61..7392068 100644
--- a/src/components/Player.vue
+++ b/src/components/Player.vue
@@ -10,9 +10,9 @@
'no-vote': player.isVoteless,
you: session.sessionId && player.id && player.id === session.playerId,
'vote-yes': session.votes[index],
- 'vote-lock': voteLocked
+ 'vote-lock': voteLocked,
},
- player.role.team
+ player.role.team,
]"
>
@@ -121,7 +121,7 @@
@click="changePronouns"
v-if="
!session.isSpectator ||
- (session.isSpectator && player.id === session.playerId)
+ (session.isSpectator && player.id === session.playerId)
"
>
Change Pronouns
@@ -162,9 +162,7 @@
:class="{ disabled: player.id && player.id !== session.playerId }"
>
-
- Claim seat
-
+ Claim seat
Vacate seat
@@ -188,10 +186,12 @@
backgroundImage: `url(${
reminder.image && grimoire.isImageOptIn
? reminder.image
- : require('../assets/icons/' +
- (reminder.imageAlt || reminder.role) +
- '.png')
- })`
+ : require(
+ '../assets/icons/' +
+ (reminder.imageAlt || reminder.role) +
+ '.png',
+ )
+ })`,
}"
>
{{ reminder.name }}
@@ -210,22 +210,22 @@ import { mapGetters, mapState } from "vuex";
export default {
components: {
- Token
+ Token,
},
props: {
player: {
type: Object,
- required: true
- }
+ required: true,
+ },
},
computed: {
...mapState("players", ["players"]),
...mapState(["grimoire", "session"]),
...mapGetters({ nightOrder: "players/nightOrder" }),
- index: function() {
+ index: function () {
return this.players.indexOf(this.player);
},
- voteLocked: function() {
+ voteLocked: function () {
const session = this.session;
const players = this.players.length;
if (!session.nomination) return false;
@@ -233,7 +233,7 @@ export default {
(this.index - 1 + players - session.nomination[1]) % players;
return indexAdjusted < session.lockedVote - 1;
},
- zoom: function() {
+ zoom: function () {
const unit = window.innerWidth > window.innerHeight ? "vh" : "vw";
if (this.players.length < 7) {
return { width: 18 + this.grimoire.zoom + unit };
@@ -244,12 +244,12 @@ export default {
} else {
return { width: 12 + this.grimoire.zoom + unit };
}
- }
+ },
},
data() {
return {
isMenuOpen: false,
- isSwap: false
+ isSwap: false,
};
},
methods: {
@@ -305,7 +305,7 @@ export default {
this.$store.commit("players/update", {
player: this.player,
property,
- value
+ value,
});
if (closeMenu) {
this.isMenuOpen = false;
@@ -342,10 +342,10 @@ export default {
if (!this.voteLocked) return;
this.$store.commit("session/voteSync", [
this.index,
- !this.session.votes[this.index]
+ !this.session.votes[this.index],
]);
- }
- }
+ },
+ },
};
@@ -632,11 +632,11 @@ li.move:not(.from) .player .overlay svg.move {
}
}
-@include glow("townsfolk", $townsfolk);
-@include glow("outsider", $outsider);
-@include glow("demon", $demon);
-@include glow("minion", $minion);
-@include glow("traveler", $traveler);
+@include glow("镇民", $townsfolk);
+@include glow("外来者", $outsider);
+@include glow("恶魔", $demon);
+@include glow("爪牙", $minion);
+@include glow("旅行者", $traveler);
.player.you .token {
animation: townsfolk-glow 5s ease-in-out infinite;
@@ -869,7 +869,10 @@ li.move:not(.from) .player .overlay svg.move {
width: 100%;
position: absolute;
top: 15%;
- text-shadow: 0 1px 1px #f6dfbd, 0 -1px 1px #f6dfbd, 1px 0 1px #f6dfbd,
+ text-shadow:
+ 0 1px 1px #f6dfbd,
+ 0 -1px 1px #f6dfbd,
+ 1px 0 1px #f6dfbd,
-1px 0 1px #f6dfbd;
}
diff --git a/src/components/TownSquare.vue b/src/components/TownSquare.vue
index 33a6707..b3c551f 100644
--- a/src/components/TownSquare.vue
+++ b/src/components/TownSquare.vue
@@ -5,7 +5,7 @@
:class="{
public: grimoire.isPublic,
spectator: session.isSpectator,
- vote: session.nomination
+ vote: session.nomination,
}"
>
@@ -18,7 +18,7 @@
from: Math.max(swap, move, nominate) === index,
swap: swap > -1,
move: move > -1,
- nominate: nominate > -1
+ nominate: nominate > -1,
}"
>
@@ -29,12 +29,20 @@
ref="bluffs"
:class="{ closed: !isBluffsOpen }"
>
-
+
Other characters
- Demon bluffs
-
-
-
+ 恶魔的伪装角色
+
+
+
-
-
- Fabled
-
-
-
+
+ 传奇角色
+
+
+
- playerIndex ? nomination[0] - 1 : nomination[0],
- nomination[1] > playerIndex ? nomination[1] - 1 : nomination[1]
+ nomination[1] > playerIndex ? nomination[1] - 1 : nomination[1],
]);
}
}
@@ -186,7 +202,7 @@ export default {
if (this.session.nomination) {
// update nomination if one of the involved players is swapped
const swapTo = this.players.indexOf(to);
- const updatedNomination = this.session.nomination.map(nom => {
+ const updatedNomination = this.session.nomination.map((nom) => {
if (nom === this.swap) return swapTo;
if (nom === swapTo) return this.swap;
return nom;
@@ -200,7 +216,7 @@ export default {
}
this.$store.commit("players/swap", [
this.swap,
- this.players.indexOf(to)
+ this.players.indexOf(to),
]);
this.cancel();
}
@@ -214,7 +230,7 @@ export default {
if (this.session.nomination) {
// update nomination if it is affected by the move
const moveTo = this.players.indexOf(to);
- const updatedNomination = this.session.nomination.map(nom => {
+ const updatedNomination = this.session.nomination.map((nom) => {
if (nom === this.move) return moveTo;
if (nom > this.move && nom <= moveTo) return nom - 1;
if (nom < this.move && nom >= moveTo) return nom + 1;
@@ -229,7 +245,7 @@ export default {
}
this.$store.commit("players/move", [
this.move,
- this.players.indexOf(to)
+ this.players.indexOf(to),
]);
this.cancel();
}
@@ -251,8 +267,8 @@ export default {
this.move = -1;
this.swap = -1;
this.nominate = -1;
- }
- }
+ },
+ },
};
@@ -272,8 +288,8 @@ export default {
.circle {
padding: 0;
- width: 100%;
- height: 100%;
+ width: 100vw;
+ height: min(100vw, 100vh);
list-style: none;
margin: 0;
@@ -459,8 +475,8 @@ export default {
align-items: center;
justify-content: center;
li {
- width: 14vh;
- height: 14vh;
+ width: max(min(8vh, 8vw), 50px);
+ height: max(min(8vh, 8vw), 50px);
margin: 0 0.5%;
display: inline-block;
transition: all 250ms;
diff --git a/src/components/modals/Modal.vue b/src/components/modals/Modal.vue
index d1bd5e6..301e041 100644
--- a/src/components/modals/Modal.vue
+++ b/src/components/modals/Modal.vue
@@ -31,16 +31,16 @@
diff --git a/src/components/modals/NightOrderModal.vue b/src/components/modals/NightOrderModal.vue
index 97ba4a2..6ab4b22 100644
--- a/src/components/modals/NightOrderModal.vue
+++ b/src/components/modals/NightOrderModal.vue
@@ -113,25 +113,24 @@ export default {
if (this.players.length > 6) {
rolesFirstNight.push(
{
- id: "evil",
- name: "Minion info",
+ id: "minion_info",
+ name: "爪牙信息",
firstNight: 5,
team: "minion",
players: this.players.filter(p => p.role.team === "minion"),
firstNightReminder:
- "• If more than one Minion, they all make eye contact with each other. " +
- "• Show the “This is the Demon” card. Point to the Demon."
+ "• 如果有七名或以上玩家:爪牙睁眼相互认识。" +
+ "• 告诉他们恶魔是哪名玩家。"
},
{
- id: "evil",
- name: "Demon info & bluffs",
+ id: "demon_info",
+ name: "恶魔信息",
firstNight: 8,
team: "demon",
players: this.players.filter(p => p.role.team === "demon"),
firstNightReminder:
- "• Show the “These are your minions” card. Point to each Minion. " +
- "• Show the “These characters are not in play” card. Show 3 character tokens of good " +
- "characters not in play."
+ "• 如果有七名或以上玩家:告诉恶魔,这些玩家是你的爪牙。 " +
+ "• 告诉恶魔3个不在场的伪装角色。"
}
);
}
diff --git a/src/components/modals/ReminderModal.vue b/src/components/modals/ReminderModal.vue
index b781b7b..d1802ce 100644
--- a/src/components/modals/ReminderModal.vue
+++ b/src/components/modals/ReminderModal.vue
@@ -18,10 +18,12 @@
backgroundImage: `url(${
reminder.image && grimoire.isImageOptIn
? reminder.image
- : require('../../assets/icons/' +
- (reminder.imageAlt || reminder.role) +
- '.png')
- })`
+ : require(
+ '../../assets/icons/' +
+ (reminder.imageAlt || reminder.role) +
+ '.png',
+ )
+ })`,
}"
>
{{ reminder.name }}
@@ -39,12 +41,14 @@ import { mapMutations, mapState } from "vuex";
* @param role The role for which the reminder should be generated
* @return {function(*): {image: string|string[]|string|*, role: *, name: *, imageAlt: string|*}}
*/
-const mapReminder = ({ id, image, imageAlt }) => name => ({
- role: id,
- image,
- imageAlt,
- name
-});
+const mapReminder =
+ ({ id, image, imageAlt }) =>
+ (name) => ({
+ role: id,
+ image,
+ imageAlt,
+ name,
+ });
export default {
components: { Modal },
@@ -53,31 +57,31 @@ export default {
availableReminders() {
let reminders = [];
const { players, bluffs } = this.$store.state.players;
- this.$store.state.roles.forEach(role => {
+ this.$store.state.roles.forEach((role) => {
// add reminders from player roles
- if (players.some(p => p.role.id === role.id)) {
+ if (players.some((p) => p.role.id === role.id)) {
reminders = [...reminders, ...role.reminders.map(mapReminder(role))];
}
// add reminders from bluff/other roles
- else if (bluffs.some(bluff => bluff.id === role.id)) {
+ else if (bluffs.some((bluff) => bluff.id === role.id)) {
reminders = [...reminders, ...role.reminders.map(mapReminder(role))];
}
// add global reminders
if (role.remindersGlobal && role.remindersGlobal.length) {
reminders = [
...reminders,
- ...role.remindersGlobal.map(mapReminder(role))
+ ...role.remindersGlobal.map(mapReminder(role)),
];
}
});
// add fabled reminders
- this.$store.state.players.fabled.forEach(role => {
+ this.$store.state.players.fabled.forEach((role) => {
reminders = [...reminders, ...role.reminders.map(mapReminder(role))];
});
// add out of script traveler reminders
- this.$store.state.otherTravelers.forEach(role => {
- if (players.some(p => p.role.id === role.id)) {
+ this.$store.state.otherTravelers.forEach((role) => {
+ if (players.some((p) => p.role.id === role.id)) {
reminders = [...reminders, ...role.reminders.map(mapReminder(role))];
}
});
@@ -88,7 +92,7 @@ export default {
return reminders;
},
...mapState(["modals", "grimoire"]),
- ...mapState("players", ["players"])
+ ...mapState("players", ["players"]),
},
methods: {
addReminder(reminder) {
@@ -104,12 +108,12 @@ export default {
this.$store.commit("players/update", {
player,
property: "reminders",
- value
+ value,
});
this.$store.commit("toggleModal", "reminder");
},
- ...mapMutations(["toggleModal"])
- }
+ ...mapMutations(["toggleModal"]),
+ },
};
@@ -117,8 +121,8 @@ export default {
ul.reminders .reminder {
background: url("../../assets/reminder.png") center center;
background-size: 100%;
- width: 14vh;
- height: 14vh;
+ width: max(min(14vh, 14vw), 50px);
+ height: max(min(14vh, 14vw), 50px);
max-width: 100px;
max-height: 100px;
display: flex;
@@ -145,12 +149,12 @@ ul.reminders .reminder {
.text {
color: black;
- font-size: 65%;
+ font-size: 0.9em;
font-weight: bold;
text-align: center;
top: 28%;
width: 80%;
- line-height: 1;
+ line-height: 0.9em;
}
&:hover {
diff --git a/src/components/modals/RoleModal.vue b/src/components/modals/RoleModal.vue
index eadde8c..6f2c8be 100644
--- a/src/components/modals/RoleModal.vue
+++ b/src/components/modals/RoleModal.vue
@@ -60,12 +60,12 @@ export default {
availableRoles() {
const availableRoles = [];
const players = this.$store.state.players.players;
- this.$store.state.roles.forEach(role => {
+ this.$store.state.roles.forEach((role) => {
// don't show bluff roles that are already assigned to players
if (
this.playerIndex >= 0 ||
(this.playerIndex < 0 &&
- !players.some(player => player.role.id === role.id))
+ !players.some((player) => player.role.id === role.id))
) {
availableRoles.push(role);
}
@@ -75,11 +75,11 @@ export default {
},
...mapState(["modals", "roles", "session"]),
...mapState("players", ["players"]),
- ...mapState(["otherTravelers"])
+ ...mapState(["otherTravelers"]),
},
data() {
return {
- tab: "editionRoles"
+ tab: "editionRoles",
};
},
methods: {
@@ -88,7 +88,7 @@ export default {
// assign to bluff slot (index < 0)
this.$store.commit("players/setBluff", {
index: this.playerIndex * -1 - 1,
- role
+ role,
});
} else {
if (this.session.isSpectator && role.team === "traveler") return;
@@ -97,7 +97,7 @@ export default {
this.$store.commit("players/update", {
player,
property: "role",
- value: role
+ value: role,
});
}
this.tab = "editionRoles";
@@ -107,8 +107,8 @@ export default {
this.tab = "editionRoles";
this.toggleModal("role");
},
- ...mapMutations(["toggleModal"])
- }
+ ...mapMutations(["toggleModal"]),
+ },
};
@@ -117,24 +117,34 @@ export default {
ul.tokens li {
border-radius: 50%;
- width: 6vw;
+ width: max(6vw, 60px);
margin: 1%;
transition: transform 500ms ease;
&.townsfolk {
- box-shadow: 0 0 10px $townsfolk, 0 0 10px #004cff;
+ box-shadow:
+ 0 0 10px $townsfolk,
+ 0 0 10px #004cff;
}
&.outsider {
- box-shadow: 0 0 10px $outsider, 0 0 10px $outsider;
+ box-shadow:
+ 0 0 10px $outsider,
+ 0 0 10px $outsider;
}
&.minion {
- box-shadow: 0 0 10px $minion, 0 0 10px $minion;
+ box-shadow:
+ 0 0 10px $minion,
+ 0 0 10px $minion;
}
&.demon {
- box-shadow: 0 0 10px $demon, 0 0 10px $demon;
+ box-shadow:
+ 0 0 10px $demon,
+ 0 0 10px $demon;
}
&.traveler {
- box-shadow: 0 0 10px $traveler, 0 0 10px $traveler;
+ box-shadow:
+ 0 0 10px $traveler,
+ 0 0 10px $traveler;
}
&:hover {
transform: scale(1.2);
diff --git a/src/components/modals/RolesModal.vue b/src/components/modals/RolesModal.vue
index 27833b0..6672654 100644
--- a/src/components/modals/RolesModal.vue
+++ b/src/components/modals/RolesModal.vue
@@ -4,7 +4,7 @@
v-if="modals.roles && nonTravelers >= 5"
@close="toggleModal('roles')"
>
-
Select the characters for {{ nonTravelers }} players:
+ 为 {{ nonTravelers }} 个玩家选择角色: