townsquare/src/components/TownSquare.vue

245 lines
5.3 KiB
Vue
Raw Normal View History

2020-04-01 22:57:14 +02:00
<template>
<div
id="townsquare"
class="square"
v-bind:class="{
public: grimoire.isPublic,
spectator: session.isSpectator
}"
2020-05-02 21:33:44 +02:00
v-bind:style="{ zoom: grimoire.zoom }"
>
<ul class="circle" v-bind:class="['size-' + players.length]">
<Player
2020-04-05 21:50:06 +02:00
v-for="(player, index) in players"
:key="index"
2020-04-05 19:50:33 +02:00
:player="player"
2020-05-03 23:05:17 +02:00
@add-reminder="openReminderModal(index)"
@set-role="openRoleModal(index)"
@remove-player="removePlayer(index)"
2020-05-12 22:22:36 +02:00
@swap-seats="swapSeats(index, $event)"
2020-04-19 22:54:25 +02:00
@screenshot="$emit('screenshot', $event)"
2020-05-12 22:22:36 +02:00
v-bind:class="{
'swap-from': swapFrom === index,
swap: swapFrom > -1
}"
></Player>
</ul>
2020-05-03 23:05:17 +02:00
2020-04-19 22:54:25 +02:00
<div class="bluffs" v-if="players.length > 6" ref="bluffs">
2020-04-18 21:03:58 +02:00
<h3>Demon bluffs</h3>
2020-04-19 22:54:25 +02:00
<font-awesome-icon icon="camera" @click.stop="takeScreenshot" />
2020-04-18 21:03:58 +02:00
<ul>
2020-04-05 19:50:33 +02:00
<li
2020-05-03 23:05:17 +02:00
v-for="index in bluffs"
:key="index"
@click="openRoleModal(index * -1)"
2020-04-05 19:50:33 +02:00
>
2020-05-03 23:05:17 +02:00
<Token :role="grimoire.bluffs[index - 1]"></Token>
</li>
</ul>
2020-05-03 23:05:17 +02:00
</div>
2020-05-02 21:33:44 +02:00
2020-05-03 23:05:17 +02:00
<ReminderModal :player-index="selectedPlayer"></ReminderModal>
<RoleModal :player-index="selectedPlayer"></RoleModal>
</div>
2020-04-01 22:57:14 +02:00
</template>
<script>
2020-05-03 23:05:17 +02:00
import { mapState } from "vuex";
2020-04-05 19:50:33 +02:00
import Player from "./Player";
import Token from "./Token";
2020-05-03 23:05:17 +02:00
import ReminderModal from "./modals/ReminderModal";
import RoleModal from "./modals/RoleModal";
2020-04-01 22:57:14 +02:00
2020-04-05 19:50:33 +02:00
export default {
components: {
2020-05-03 23:05:17 +02:00
Player,
Token,
2020-05-03 23:05:17 +02:00
RoleModal,
ReminderModal
2020-04-05 19:50:33 +02:00
},
2020-05-03 23:05:17 +02:00
computed: {
...mapState(["grimoire", "roles", "session"]),
2020-05-03 23:05:17 +02:00
...mapState("players", ["players"])
},
2020-04-05 19:50:33 +02:00
data() {
return {
2020-05-03 23:05:17 +02:00
selectedPlayer: 0,
2020-05-12 22:22:36 +02:00
bluffs: 3,
swapFrom: -1
2020-04-05 19:50:33 +02:00
};
},
methods: {
2020-04-19 22:54:25 +02:00
takeScreenshot() {
const { width, height, x, y } = this.$refs.bluffs.getBoundingClientRect();
this.$emit("screenshot", { width, height, x, y });
},
2020-05-03 23:05:17 +02:00
openReminderModal(playerIndex) {
this.selectedPlayer = playerIndex;
this.$store.commit("toggleModal", "reminder");
2020-04-05 19:50:33 +02:00
},
2020-05-03 23:05:17 +02:00
openRoleModal(playerIndex) {
const player = this.players[playerIndex];
if (this.session.isSpectator && player.role.team === "traveler") return;
2020-05-03 23:05:17 +02:00
this.selectedPlayer = playerIndex;
this.$store.commit("toggleModal", "role");
},
2020-05-03 23:05:17 +02:00
removePlayer(playerIndex) {
if (this.session.isSpectator) return;
2020-05-03 23:05:17 +02:00
if (
confirm(
`Do you really want to remove ${this.players[playerIndex].name}?`
)
) {
this.$store.commit("players/remove", playerIndex);
}
2020-05-12 22:22:36 +02:00
},
swapSeats(from, to) {
if (to === undefined) {
this.swapFrom = from;
} else if (to === false) {
this.swapFrom = -1;
} else {
this.$store.commit("players/swap", [
this.swapFrom,
this.players.indexOf(to)
]);
this.swapFrom = -1;
}
2020-04-01 22:57:14 +02:00
}
}
2020-04-05 19:50:33 +02:00
};
2020-04-01 22:57:14 +02:00
</script>
<style lang="scss">
2020-04-05 19:50:33 +02:00
.circle {
padding: 0;
width: 100%;
height: 100%;
list-style: none;
margin: 0;
2020-04-01 22:57:14 +02:00
2020-05-12 22:22:36 +02:00
> li {
2020-04-05 19:50:33 +02:00
position: absolute;
top: 0;
left: 50%;
height: 50%;
transform-origin: 0 100%;
text-align: center;
2020-04-02 22:23:40 +02:00
2020-04-05 19:50:33 +02:00
&:hover {
z-index: 25 !important;
2020-04-01 22:57:14 +02:00
}
2020-04-05 19:50:33 +02:00
> * {
2020-04-19 22:54:25 +02:00
margin-left: -78px;
width: 156px;
2020-04-02 22:23:40 +02:00
}
}
2020-04-05 19:50:33 +02:00
}
2020-04-01 22:57:14 +02:00
2020-04-05 21:50:06 +02:00
@mixin on-circle($item-count) {
$angle: (360 / $item-count);
$rot: 0;
@for $i from 1 through $item-count {
&:nth-child(#{$i}) {
transform: rotate($rot * 1deg);
@if $i - 1 <= $item-count / 2 {
z-index: $item-count - $i + 1;
} @else {
z-index: $i - 1;
2020-04-25 22:19:47 +02:00
.ability {
2020-04-22 23:07:25 +02:00
right: 120%;
left: auto;
2020-04-18 20:21:26 +02:00
&:before {
border-right-color: transparent;
border-left-color: black;
right: auto;
left: 100%;
2020-04-05 21:50:06 +02:00
}
}
}
> * {
transform: rotate($rot * -1deg);
}
2020-04-08 22:42:51 +02:00
.life,
2020-04-10 11:21:27 +02:00
.token,
2020-04-22 23:07:25 +02:00
.shroud,
.night {
2020-04-10 11:21:27 +02:00
transition-delay: ($i - 1) * 50ms;
2020-04-08 21:30:55 +02:00
}
2020-04-22 21:21:54 +02:00
// move reminders closer to the sides of the circle
$q: $item-count / 4;
$x: $i - 1;
@if $x < $q or ($x >= $item-count / 2 and $x < $q * 3) {
.player {
margin-bottom: -10px + 20px * (1 - ($x % $q / $q));
}
} @else {
.player {
margin-bottom: -10px + 20px * ($x % $q / $q);
}
}
2020-04-05 21:50:06 +02:00
}
$rot: $rot + $angle;
}
}
@for $i from 1 through 20 {
2020-05-12 22:22:36 +02:00
.circle.size-#{$i} > li {
2020-04-05 19:50:33 +02:00
@include on-circle($item-count: $i);
}
2020-04-05 19:50:33 +02:00
}
2020-04-05 19:50:33 +02:00
#townsquare {
width: 100%;
height: 100%;
border-radius: 50%;
padding: 20px;
}
2020-04-01 22:57:14 +02:00
2020-04-18 21:03:58 +02:00
/***** Demon bluffs *******/
.bluffs {
position: absolute;
bottom: 10px;
left: 10px;
background: rgba(0, 0, 0, 0.5);
border-radius: 10px;
border: 3px solid black;
filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.5));
transform-origin: bottom left;
transform: scale(1);
opacity: 1;
transition: all 200ms ease-in-out;
2020-04-22 21:21:54 +02:00
#townsquare.public & {
opacity: 0;
transform: scale(0.1);
}
2020-04-19 22:54:25 +02:00
> svg {
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
&:hover {
color: red;
}
2020-04-22 21:21:54 +02:00
#app.screenshot & {
display: none;
}
2020-04-19 22:54:25 +02:00
}
2020-04-18 21:03:58 +02:00
h3 {
margin-top: 5px;
}
li {
width: 120px;
height: 120px;
margin: 0 5px;
display: inline-block;
font-size: 18px;
}
}
2020-04-01 22:57:14 +02:00
</style>