mirror of
https://github.com/bra1n/townsquare.git
synced 2025-04-04 22:24:36 +00:00
483 lines
12 KiB
Vue
483 lines
12 KiB
Vue
<template>
|
|
<Modal
|
|
class="night-reference"
|
|
@close="toggleModal('nightOrder')"
|
|
v-if="modals.nightOrder && roles.size"
|
|
>
|
|
<font-awesome-icon
|
|
@click="toggleModal('reference')"
|
|
icon="address-card"
|
|
class="toggle"
|
|
title="Show Character Reference"
|
|
/>
|
|
<h3>
|
|
{{ locale.modal.nightOrder.title }}
|
|
<font-awesome-icon icon="cloud-moon" />
|
|
{{ edition.name || locale.modal.nightOrder.custom }}
|
|
</h3>
|
|
<div class="night">
|
|
<ul class="first">
|
|
<li class="headline">{{ locale.modal.nightOrder.firstNight }}</li>
|
|
<li
|
|
v-for="role in rolesFirstNight"
|
|
:key="role.name"
|
|
:class="[role.team]"
|
|
>
|
|
<span class="name">
|
|
{{ role.name }}
|
|
<span class="player" v-if="role.players.length">
|
|
<br />
|
|
<small
|
|
v-for="(player, index) in role.players"
|
|
:class="{ dead: player.isDead }"
|
|
:key="index"
|
|
>{{
|
|
player.name + (role.players.length > index + 1 ? "," : "")
|
|
}}</small
|
|
>
|
|
</span>
|
|
<span
|
|
class="player"
|
|
v-if="
|
|
(role.id == 'dawn' || role.team == 'fabled') &&
|
|
!session.isSpectator &&
|
|
players.length && players[0].role.id
|
|
"
|
|
>
|
|
<br />
|
|
<small> </small>
|
|
</span>
|
|
</span>
|
|
<span
|
|
class="icon"
|
|
v-if="role.id"
|
|
:style="{
|
|
backgroundImage: `url(${
|
|
role.image && grimoire.isImageOptIn
|
|
? role.image
|
|
: require(
|
|
'../../assets/icons/' +
|
|
(role.imageAlt || role.id) +
|
|
'.png',
|
|
)
|
|
})`,
|
|
}"
|
|
></span>
|
|
<span class="reminder" v-if="role.firstNightReminder">
|
|
{{ role.firstNightReminder }}
|
|
</span>
|
|
</li>
|
|
</ul>
|
|
<ul class="other">
|
|
<li class="headline">{{ locale.modal.nightOrder.otherNights }}</li>
|
|
<li
|
|
v-for="role in rolesOtherNight"
|
|
:key="role.name"
|
|
:class="[role.team]"
|
|
>
|
|
<span
|
|
class="icon"
|
|
v-if="role.id"
|
|
:style="{
|
|
backgroundImage: `url(${
|
|
role.image && grimoire.isImageOptIn
|
|
? role.image
|
|
: require(
|
|
'../../assets/icons/' +
|
|
(role.imageAlt || role.id) +
|
|
'.png',
|
|
)
|
|
})`,
|
|
}"
|
|
></span>
|
|
<span class="name">
|
|
{{ role.name }}
|
|
<span class="player" v-if="role.players.length">
|
|
<br />
|
|
<small
|
|
v-for="(player, index) in role.players"
|
|
:class="{ dead: player.isDead }"
|
|
:key="index"
|
|
>{{
|
|
player.name + (role.players.length > index + 1 ? "," : "")
|
|
}}</small
|
|
>
|
|
</span>
|
|
<span
|
|
class="player"
|
|
v-if="
|
|
(role.id == 'dawn' ||
|
|
role.id == 'dusk' ||
|
|
role.team == 'fabled') &&
|
|
!session.isSpectator &&
|
|
players.length && players[0].role.id
|
|
"
|
|
>
|
|
<br />
|
|
<small> </small>
|
|
</span>
|
|
</span>
|
|
<span class="reminder" v-if="role.otherNightReminder">
|
|
{{ role.otherNightReminder }}
|
|
</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</Modal>
|
|
</template>
|
|
|
|
<script>
|
|
import Modal from "./Modal";
|
|
import { mapMutations, mapState } from "vuex";
|
|
|
|
export default {
|
|
components: {
|
|
Modal,
|
|
},
|
|
computed: {
|
|
rolesFirstNight: function () {
|
|
const rolesFirstNight = [];
|
|
// Ajouter le matin à l'ordre nocturne
|
|
rolesFirstNight.push({
|
|
id: "dawn",
|
|
name: this.locale.modal.nightOrder.dawn,
|
|
firstNight: 60,
|
|
team: "default",
|
|
players: [],
|
|
firstNightReminder: this.locale.modal.nightOrder.dawnDescription1
|
|
});
|
|
var toymaker = false;
|
|
// Ajout des fabuleux
|
|
this.fabled.forEach(fabled => {
|
|
if (fabled.firstNight) {
|
|
rolesFirstNight.push(Object.assign({ players: [] }, fabled));
|
|
} else if (fabled.id == "toymaker") {
|
|
toymaker = true;
|
|
}
|
|
});
|
|
this.roles.forEach(role => {
|
|
const players = this.players.filter(p => p.role.id === role.id);
|
|
if (role.firstNight && role.team !== "traveler") {
|
|
rolesFirstNight.push(Object.assign({ players }, role));
|
|
}
|
|
});
|
|
// Ajout des Voyageurs, en n'ajoutant qu'une fois ceux en double
|
|
const seenTravelers = [];
|
|
var nbTravelers = 0;
|
|
this.players.forEach(player => {
|
|
if (player.role.team == "traveler") {
|
|
nbTravelers++;
|
|
if (!seenTravelers.includes(player.role.id)) {
|
|
seenTravelers.push(player.role.id);
|
|
if (player.role.firstNight) {
|
|
const players = this.players.filter(
|
|
p => p.role.id === player.role.id
|
|
);
|
|
rolesFirstNight.push(Object.assign({ players }, player.role));
|
|
}
|
|
}
|
|
}
|
|
});
|
|
// Ajouter minion / demon infos à l'ordre nocturne
|
|
if (this.players.length - nbTravelers > 6 || toymaker) {
|
|
rolesFirstNight.push(
|
|
{
|
|
id: "minion",
|
|
name: this.locale.modal.nightOrder.minionInfo,
|
|
firstNight: 7,
|
|
team: "minion",
|
|
players: this.players.filter((p) => p.role.team === "minion"),
|
|
firstNightReminder:
|
|
this.locale.modal.nightOrder.minionInfoDescription,
|
|
},
|
|
{
|
|
id: "evil",
|
|
name: this.locale.modal.nightOrder.demonInfo,
|
|
firstNight: 10,
|
|
team: "demon",
|
|
players: this.players.filter((p) => p.role.team === "demon"),
|
|
firstNightReminder:
|
|
this.locale.modal.nightOrder.demonInfoDescription,
|
|
},
|
|
);
|
|
}
|
|
rolesFirstNight.sort((a, b) => a.firstNight - b.firstNight);
|
|
return rolesFirstNight;
|
|
},
|
|
rolesOtherNight: function () {
|
|
const rolesOtherNight = [];
|
|
rolesOtherNight.push(
|
|
{
|
|
id: "dusk",
|
|
name: this.locale.modal.nightOrder.dusk,
|
|
team: "default",
|
|
otherNight: 1,
|
|
players: [],
|
|
otherNightReminder: this.locale.modal.nightOrder.duskDescription
|
|
},
|
|
{
|
|
id: "dawn",
|
|
name: this.locale.modal.nightOrder.dawn,
|
|
team: "default",
|
|
otherNight: Infinity,
|
|
players: [],
|
|
otherNightReminder: this.locale.modal.nightOrder.dawnDescription2
|
|
|
|
}
|
|
);
|
|
this.fabled
|
|
.filter(({ otherNight }) => otherNight)
|
|
.forEach((fabled) => {
|
|
rolesOtherNight.push(Object.assign({ players: [] }, fabled));
|
|
});
|
|
this.roles.forEach(role => {
|
|
const players = this.players.filter(p => p.role.id === role.id);
|
|
if (role.otherNight && role.team !== "traveler") {
|
|
rolesOtherNight.push(Object.assign({ players }, role));
|
|
}
|
|
});
|
|
// Ajout des Voyageurs, en n'ajoutant qu'une fois ceux en double
|
|
const seenTravelers = [];
|
|
this.players.forEach(player => {
|
|
if (
|
|
player.role.otherNight &&
|
|
player.role.team == "traveler" &&
|
|
!seenTravelers.includes(player.role.id)
|
|
) {
|
|
const players = this.players.filter(
|
|
p => p.role.id === player.role.id
|
|
);
|
|
seenTravelers.push(player.role.id);
|
|
rolesOtherNight.push(Object.assign({ players }, player.role));
|
|
}
|
|
});
|
|
rolesOtherNight.sort((a, b) => a.otherNight - b.otherNight);
|
|
return rolesOtherNight;
|
|
},
|
|
...mapState([
|
|
"roles",
|
|
"modals",
|
|
"edition",
|
|
"grimoire",
|
|
"locale",
|
|
"session"
|
|
]),
|
|
...mapState("players", ["players", "fabled"])
|
|
},
|
|
methods: {
|
|
...mapMutations(["toggleModal"]),
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
@import "../../vars.scss";
|
|
|
|
.toggle {
|
|
position: absolute;
|
|
left: 20px;
|
|
top: 15px;
|
|
cursor: pointer;
|
|
&:hover {
|
|
color: red;
|
|
}
|
|
}
|
|
|
|
h3 {
|
|
margin: 0 40px;
|
|
svg {
|
|
vertical-align: middle;
|
|
}
|
|
}
|
|
|
|
h4 {
|
|
text-transform: capitalize;
|
|
display: flex;
|
|
align-items: center;
|
|
height: 20px;
|
|
&:before,
|
|
&:after {
|
|
content: " ";
|
|
width: 100%;
|
|
height: 1px;
|
|
border-radius: 2px;
|
|
}
|
|
&:before {
|
|
margin-right: 15px;
|
|
}
|
|
&:after {
|
|
margin-left: 15px;
|
|
}
|
|
}
|
|
|
|
.fabled {
|
|
.name {
|
|
background: linear-gradient(90deg, $fabled, transparent 35%);
|
|
.night .other & {
|
|
background: linear-gradient(-90deg, $fabled, transparent 35%);
|
|
}
|
|
}
|
|
}
|
|
.townsfolk {
|
|
.name {
|
|
background: linear-gradient(90deg, $townsfolk, transparent 35%);
|
|
.night .other & {
|
|
background: linear-gradient(-90deg, $townsfolk, transparent 35%);
|
|
}
|
|
}
|
|
}
|
|
.outsider {
|
|
.name {
|
|
background: linear-gradient(90deg, $outsider, transparent 35%);
|
|
.night .other & {
|
|
background: linear-gradient(-90deg, $outsider, transparent 35%);
|
|
}
|
|
}
|
|
}
|
|
.minion {
|
|
.name {
|
|
background: linear-gradient(90deg, $minion, transparent 35%);
|
|
.night .other & {
|
|
background: linear-gradient(-90deg, $minion, transparent 35%);
|
|
}
|
|
}
|
|
}
|
|
.demon {
|
|
.name {
|
|
background: linear-gradient(90deg, $demon, transparent 35%);
|
|
.night .other & {
|
|
background: linear-gradient(-90deg, $demon, transparent 35%);
|
|
}
|
|
}
|
|
}
|
|
.traveler {
|
|
.name {
|
|
background: linear-gradient(90deg, $traveler, transparent 35%);
|
|
.night .other & {
|
|
background: linear-gradient(-90deg, $traveler, transparent 35%);
|
|
}
|
|
}
|
|
}
|
|
.default {
|
|
.name {
|
|
background: linear-gradient(90deg, $default, transparent 35%);
|
|
.night .other & {
|
|
background: linear-gradient(-90deg, $default, transparent 35%);
|
|
}
|
|
}
|
|
}
|
|
ul {
|
|
li {
|
|
display: flex;
|
|
width: 100%;
|
|
margin-bottom: 3px;
|
|
.icon {
|
|
width: 5vh;
|
|
background-size: 100% auto;
|
|
background-position: center center;
|
|
background-repeat: no-repeat;
|
|
flex-grow: 0;
|
|
flex-shrink: 0;
|
|
text-align: center;
|
|
margin: 0 2px;
|
|
&:after {
|
|
content: " ";
|
|
display: block;
|
|
padding-top: 66%;
|
|
}
|
|
}
|
|
.name {
|
|
flex-grow: 0;
|
|
flex-shrink: 0;
|
|
width: 5%;
|
|
text-align: right;
|
|
font-size: 110%;
|
|
padding: 5px;
|
|
border-left: 1px solid rgba(255, 255, 255, 0.4);
|
|
border-right: 1px solid rgba(255, 255, 255, 0.4);
|
|
small {
|
|
color: #888;
|
|
margin-right: 5px;
|
|
&.dead {
|
|
text-decoration: line-through;
|
|
}
|
|
}
|
|
}
|
|
.reminder {
|
|
position: fixed;
|
|
padding: 5px 10px;
|
|
left: 50%;
|
|
bottom: 10%;
|
|
width: 500px;
|
|
z-index: 25;
|
|
background: rgba(0, 0, 0, 0.75);
|
|
border-radius: 10px;
|
|
border: 3px solid black;
|
|
filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.5));
|
|
text-align: left;
|
|
pointer-events: none;
|
|
opacity: 0;
|
|
transition: opacity 200ms ease-in-out;
|
|
margin-left: -250px;
|
|
}
|
|
&:hover .reminder {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
&.legend {
|
|
font-weight: bold;
|
|
height: 20px;
|
|
margin-top: 10px;
|
|
li span {
|
|
background: none;
|
|
height: auto;
|
|
font-family: inherit;
|
|
font-size: inherit;
|
|
}
|
|
.icon:after {
|
|
padding-top: 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
.night {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: center;
|
|
> *:first-child {
|
|
margin-right: 2vh;
|
|
}
|
|
> * {
|
|
flex-grow: 0;
|
|
flex-wrap: nowrap;
|
|
flex-direction: column;
|
|
}
|
|
.headline {
|
|
display: block;
|
|
font-weight: bold;
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.4);
|
|
padding: 5px 10px;
|
|
border-radius: 0;
|
|
text-align: center;
|
|
}
|
|
.name {
|
|
flex-grow: 1;
|
|
}
|
|
.first {
|
|
.name {
|
|
border-left: 0;
|
|
}
|
|
}
|
|
.other {
|
|
li .name {
|
|
text-align: left;
|
|
border-right: 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/** hide players when town square is set to "public" **/
|
|
#townsquare.public ~ .night-reference .modal .player {
|
|
display: none;
|
|
}
|
|
</style>
|