added seat claiming

This commit is contained in:
Steffen 2020-05-31 00:18:31 +02:00
parent 0f1397c53d
commit f42d7dd2be
No known key found for this signature in database
GPG Key ID: 764D74E98267DFC6
5 changed files with 138 additions and 23 deletions

View File

@ -3,11 +3,14 @@
<div <div
ref="player" ref="player"
class="player" class="player"
:class="{ :class="[
{
dead: player.isDead, dead: player.isDead,
'no-vote': player.isVoteless, 'no-vote': player.isVoteless,
traveler: player.role && player.role.team === 'traveler' you: player.id === session.playerId
}" },
player.role.team
]"
> >
<div class="shroud" @click="toggleStatus()"></div> <div class="shroud" @click="toggleStatus()"></div>
<div class="life" @click="toggleStatus()"></div> <div class="life" @click="toggleStatus()"></div>
@ -31,8 +34,12 @@
}}</span> }}</span>
</div> </div>
<Token :role="player.role" @set-role="$emit('set-role')" /> <Token
:role="player.role"
@set-role="$emit('trigger', ['openRoleModal'])"
/>
<!-- Overlay icons -->
<font-awesome-icon <font-awesome-icon
icon="times-circle" icon="times-circle"
class="cancel" class="cancel"
@ -52,6 +59,10 @@
title="Move player to this seat" title="Move player to this seat"
/> />
<!-- Claimed seat icon -->
<font-awesome-icon icon="chair" v-if="player.id" class="seat" />
<!-- Ghost vote icon -->
<font-awesome-icon <font-awesome-icon
icon="vote-yea" icon="vote-yea"
class="vote" class="vote"
@ -90,13 +101,17 @@
<font-awesome-icon icon="camera" /> <font-awesome-icon icon="camera" />
Screenshot Screenshot
</li> </li>
<li @click="$emit('remove-player')"> <li @click="$emit('trigger', ['removePlayer'])">
<font-awesome-icon icon="times-circle" /> <font-awesome-icon icon="times-circle" />
Remove Remove
</li> </li>
</template> </template>
<li @click="claimSeat" v-if="session.isSpectator"> <li @click="claimSeat" v-if="session.isSpectator">
<font-awesome-icon icon="chair" /> Claim seat <font-awesome-icon icon="chair" />
<template v-if="player.id !== session.playerId">
Claim seat
</template>
<template v-else> Vacate seat </template>
</li> </li>
</ul> </ul>
</transition> </transition>
@ -121,7 +136,7 @@
{{ reminder.name }} {{ reminder.name }}
</div> </div>
</template> </template>
<div class="reminder add" @click="$emit('add-reminder')"> <div class="reminder add" @click="$emit('trigger', ['openReminderModal'])">
<span class="icon"></span> <span class="icon"></span>
</div> </div>
</li> </li>
@ -198,14 +213,18 @@ export default {
}, },
swapPlayer(player) { swapPlayer(player) {
this.isMenuOpen = false; this.isMenuOpen = false;
this.$emit("swap-player", player); this.$emit("trigger", ["swapPlayer", player]);
}, },
movePlayer(player) { movePlayer(player) {
this.isMenuOpen = false; this.isMenuOpen = false;
this.$emit("move-player", player); this.$emit("trigger", ["movePlayer", player]);
}, },
cancel() { cancel() {
this.$emit("cancel"); this.$emit("trigger", ["cancel"]);
},
claimSeat() {
this.isMenuOpen = false;
this.$emit("trigger", ["claimSeat"]);
} }
} }
}; };
@ -407,7 +426,6 @@ li.move:not(.from) .player > svg.move {
bottom: 45px; bottom: 45px;
color: #fff; color: #fff;
filter: drop-shadow(0 0 3px black); filter: drop-shadow(0 0 3px black);
cursor: pointer;
transition: opacity 250ms; transition: opacity 250ms;
#townsquare.public & { #townsquare.public & {
@ -416,6 +434,50 @@ li.move:not(.from) .player > svg.move {
} }
} }
@mixin glow($name, $color) {
@keyframes #{$name}-glow {
0% {
box-shadow: 0 0 rgba($color, 1);
border-color: $color;
}
50% {
border-color: black;
}
100% {
box-shadow: 0 0 20px 16px transparent;
border-color: $color;
}
}
.player.you.#{$name} .token {
animation: #{$name}-glow 2s ease-in-out infinite;
}
}
@include glow("townsfolk", $townsfolk);
@include glow("outsider", $outsider);
@include glow("demon", $demon);
@include glow("minion", $minion);
@include glow("traveler", $traveler);
.player.you .token {
animation: townsfolk-glow 2s ease-in-out infinite;
}
/****** Seat icon ********/
.player .seat {
position: absolute;
left: 2px;
bottom: 45px;
color: #fff;
filter: drop-shadow(0 0 3px black);
cursor: default;
}
.player.you .seat {
color: $townsfolk;
}
/***** Player name *****/ /***** Player name *****/
.player > .name { .player > .name {
font-size: 120%; font-size: 120%;

View File

@ -13,13 +13,8 @@
v-for="(player, index) in players" v-for="(player, index) in players"
:key="index" :key="index"
:player="player" :player="player"
@add-reminder="openReminderModal(index)"
@set-role="openRoleModal(index)"
@remove-player="removePlayer(index)"
@cancel="cancel(index)"
@swap-player="swapPlayer(index, $event)"
@move-player="movePlayer(index, $event)"
@screenshot="$emit('screenshot', $event)" @screenshot="$emit('screenshot', $event)"
@trigger="handleTrigger(index, $event)"
v-bind:class="{ v-bind:class="{
from: Math.max(swap, move, nominate) === index, from: Math.max(swap, move, nominate) === index,
swap: swap > -1, swap: swap > -1,
@ -80,6 +75,19 @@ export default {
const { width, height, x, y } = this.$refs.bluffs.getBoundingClientRect(); const { width, height, x, y } = this.$refs.bluffs.getBoundingClientRect();
this.$emit("screenshot", { width, height, x, y }); this.$emit("screenshot", { width, height, x, y });
}, },
handleTrigger(playerIndex, [method, params]) {
if (typeof this[method] === "function") {
this[method](playerIndex, params);
}
},
claimSeat(playerIndex) {
if (!this.session.isSpectator) return;
if (this.session.playerId === this.players[playerIndex].id) {
this.$store.commit("session/claimSeat", -1);
} else {
this.$store.commit("session/claimSeat", playerIndex);
}
},
openReminderModal(playerIndex) { openReminderModal(playerIndex) {
this.selectedPlayer = playerIndex; this.selectedPlayer = playerIndex;
this.$store.commit("toggleModal", "reminder"); this.$store.commit("toggleModal", "reminder");

View File

@ -1,4 +1,6 @@
const NEWPLAYER = { const NEWPLAYER = {
name: "",
id: "",
role: {}, role: {},
reminders: [], reminders: [],
isVoteless: false, isVoteless: false,
@ -60,9 +62,9 @@ const actions = {
}); });
} else { } else {
players = state.players.map(({ name, id }) => ({ players = state.players.map(({ name, id }) => ({
...NEWPLAYER,
name, name,
id, id
...NEWPLAYER
})); }));
} }
commit("set", players); commit("set", players);
@ -84,8 +86,8 @@ const mutations = {
}, },
add(state, name) { add(state, name) {
state.players.push({ state.players.push({
name, ...NEWPLAYER,
...NEWPLAYER name
}); });
}, },
remove(state, index) { remove(state, index) {

View File

@ -22,6 +22,9 @@ const mutations = {
}, },
setPlayerCount(state, playerCount) { setPlayerCount(state, playerCount) {
state.playerCount = playerCount; state.playerCount = playerCount;
},
claimSeat(state, claimedSeat) {
state.claimedSeat = claimedSeat;
} }
}; };

View File

@ -93,6 +93,9 @@ class LiveSession {
case "player": case "player":
this._updatePlayer(params); this._updatePlayer(params);
break; break;
case "claim":
this._updateSeat(params);
break;
case "ping": case "ping":
this._handlePing(params); this._handlePing(params);
break; break;
@ -304,6 +307,40 @@ class LiveSession {
Object.keys(this._players).length Object.keys(this._players).length
); );
} }
/**
* Claim a seat, needs to be confirmed by the Storyteller.
* @param seat either -1 or the index of the seat claimed
*/
claimSeat(seat) {
if (!this._isSpectator) return;
if (this._store.state.players.players.length > seat) {
this._send("claim", [seat, this._store.state.session.playerId]);
}
}
/**
* Update a player id associated with that seat.
* @param index seat index or -1
* @param value playerId to add / remove
* @private
*/
_updateSeat([index, value]) {
const property = "id";
// remove previous seat
const player = this._store.state.players.players.find(
({ id }) => id === value
);
if (player) {
this._store.commit("players/update", { player, property, value: "" });
}
// add playerId to new seat
if (index >= 0) {
const player = this._store.state.players.players[index];
if (!player) return;
this._store.commit("players/update", { player, property, value });
}
}
} }
module.exports = store => { module.exports = store => {
@ -321,6 +358,9 @@ module.exports = store => {
session.disconnect(); session.disconnect();
} }
break; break;
case "session/claimSeat":
session.claimSeat(payload);
break;
case "players/set": case "players/set":
case "players/swap": case "players/swap":
case "players/move": case "players/move":