mirror of https://github.com/bra1n/townsquare.git
added seat claiming
This commit is contained in:
parent
0f1397c53d
commit
f42d7dd2be
|
@ -3,11 +3,14 @@
|
||||||
<div
|
<div
|
||||||
ref="player"
|
ref="player"
|
||||||
class="player"
|
class="player"
|
||||||
:class="{
|
:class="[
|
||||||
dead: player.isDead,
|
{
|
||||||
'no-vote': player.isVoteless,
|
dead: player.isDead,
|
||||||
traveler: player.role && player.role.team === 'traveler'
|
'no-vote': player.isVoteless,
|
||||||
}"
|
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%;
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -22,6 +22,9 @@ const mutations = {
|
||||||
},
|
},
|
||||||
setPlayerCount(state, playerCount) {
|
setPlayerCount(state, playerCount) {
|
||||||
state.playerCount = playerCount;
|
state.playerCount = playerCount;
|
||||||
|
},
|
||||||
|
claimSeat(state, claimedSeat) {
|
||||||
|
state.claimedSeat = claimedSeat;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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":
|
||||||
|
|
Loading…
Reference in New Issue