mirror of https://github.com/bra1n/townsquare.git
added vote buttons
This commit is contained in:
parent
952cb1f0a5
commit
31b4cd5183
|
@ -7,7 +7,8 @@
|
|||
{
|
||||
dead: player.isDead,
|
||||
'no-vote': player.isVoteless,
|
||||
you: player.id === session.playerId
|
||||
you: player.id === session.playerId,
|
||||
'voted-yes': session.votes[index]
|
||||
},
|
||||
player.role.team
|
||||
]"
|
||||
|
@ -40,6 +41,12 @@
|
|||
/>
|
||||
|
||||
<!-- Overlay icons -->
|
||||
<font-awesome-icon
|
||||
icon="skull"
|
||||
class="vote"
|
||||
title="Vote"
|
||||
@click="vote()"
|
||||
/>
|
||||
<font-awesome-icon
|
||||
icon="times-circle"
|
||||
class="cancel"
|
||||
|
@ -71,7 +78,7 @@
|
|||
<!-- Ghost vote icon -->
|
||||
<font-awesome-icon
|
||||
icon="vote-yea"
|
||||
class="vote"
|
||||
class="has-vote"
|
||||
v-if="player.isDead && !player.isVoteless"
|
||||
@click="updatePlayer('isVoteless', true)"
|
||||
title="Ghost vote"
|
||||
|
@ -163,6 +170,9 @@ export default {
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
index: function() {
|
||||
return this.$store.state.players.players.indexOf(this.player);
|
||||
},
|
||||
...mapState(["grimoire", "session"]),
|
||||
...mapGetters({ nightOrder: "players/nightOrder" })
|
||||
},
|
||||
|
@ -235,6 +245,10 @@ export default {
|
|||
claimSeat() {
|
||||
this.isMenuOpen = false;
|
||||
this.$emit("trigger", ["claimSeat"]);
|
||||
},
|
||||
vote() {
|
||||
if (this.player.id !== this.session.playerId) return;
|
||||
this.$store.commit("session/vote", [this.index]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -402,6 +416,7 @@ export default {
|
|||
&.swap,
|
||||
&.move,
|
||||
&.nominate,
|
||||
&.vote,
|
||||
&.cancel {
|
||||
top: 9%;
|
||||
left: 20%;
|
||||
|
@ -417,6 +432,17 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
#townsquare.vote .player.voted-yes > svg.vote {
|
||||
color: $demon;
|
||||
opacity: 0.5;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
#townsquare.vote .player.you.voted-yes > svg.vote {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
li.from:not(.nominate) .player > svg.cancel {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
|
@ -432,7 +458,7 @@ li.move:not(.from) .player > svg.move {
|
|||
}
|
||||
|
||||
/****** Vote icon ********/
|
||||
.player .vote {
|
||||
.player .has-vote {
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
bottom: 45px;
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
class="square"
|
||||
v-bind:class="{
|
||||
public: grimoire.isPublic,
|
||||
spectator: session.isSpectator
|
||||
spectator: session.isSpectator,
|
||||
vote: session.nomination
|
||||
}"
|
||||
v-bind:style="{ zoom: grimoire.zoom }"
|
||||
>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="vote">
|
||||
<div id="vote">
|
||||
<div class="arrows">
|
||||
<span class="nominee" :style="nomineeStyle"></span>
|
||||
<span class="nominator" :style="nominatorStyle"></span>
|
||||
|
@ -10,17 +10,29 @@
|
|||
>!
|
||||
<br />
|
||||
<template v-if="nominee.role.team !== 'traveler'">
|
||||
<em class="blue">{{ Math.ceil(alive / 2) }} votes</em> required for an
|
||||
<em>execution</em>
|
||||
<em class="blue">{{ Math.ceil(alive / 2) }} votes</em> required to
|
||||
<em>execute</em>.
|
||||
</template>
|
||||
<template v-else>
|
||||
<em>{{ Math.ceil(players.length / 2) }} votes</em> required for an
|
||||
<em>exile</em>
|
||||
<em>{{ Math.ceil(players.length / 2) }} votes</em> required to
|
||||
<em>exile</em>.
|
||||
</template>
|
||||
<div class="button-group">
|
||||
<div class="button-group" v-if="!session.isSpectator">
|
||||
<div class="button">Start Vote</div>
|
||||
<div class="button" @click="finish">Finish Vote</div>
|
||||
</div>
|
||||
<div
|
||||
class="button-group"
|
||||
v-else-if="
|
||||
player && (!player.isVoteless || nominee.role.team === 'traveler')
|
||||
"
|
||||
>
|
||||
<div class="button vote-no" @click="vote(false)">Vote NO</div>
|
||||
<div class="button vote-yes" @click="vote(true)">Vote YES</div>
|
||||
</div>
|
||||
<div v-else-if="!player">
|
||||
Please claim a seat to vote.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -54,6 +66,10 @@ export default {
|
|||
transform: `rotate(${Math.round((nomination / players) * 360)}deg)`
|
||||
};
|
||||
},
|
||||
player: function() {
|
||||
const id = this.$store.state.session.playerId;
|
||||
return this.$store.state.players.players.find(p => p.id === id);
|
||||
},
|
||||
...mapState("players", ["players"]),
|
||||
...mapState(["session"]),
|
||||
...mapGetters({ alive: "players/alive" })
|
||||
|
@ -61,6 +77,12 @@ export default {
|
|||
methods: {
|
||||
finish() {
|
||||
this.$store.commit("session/nomination", false);
|
||||
},
|
||||
vote(vote) {
|
||||
const index = this.players.findIndex(p => p.id === this.session.playerId);
|
||||
if (index >= 0 && !!this.session.votes[index] !== vote) {
|
||||
this.$store.commit("session/vote", [index, vote]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -69,7 +91,7 @@ export default {
|
|||
<style lang="scss" scoped>
|
||||
@import "../vars.scss";
|
||||
|
||||
.vote {
|
||||
#vote {
|
||||
position: absolute;
|
||||
width: 20%;
|
||||
z-index: 20;
|
||||
|
@ -151,4 +173,30 @@ export default {
|
|||
animation: arrow-cw 1s ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
.button.vote-no {
|
||||
background: radial-gradient(
|
||||
at 0 -15%,
|
||||
rgba(255, 255, 255, 0.07) 70%,
|
||||
rgba(255, 255, 255, 0) 71%
|
||||
)
|
||||
0 0/80% 90% no-repeat content-box,
|
||||
linear-gradient(#0031ad, rgba(5, 0, 0, 0.22)) content-box,
|
||||
linear-gradient(#292929, #001142) border-box;
|
||||
box-shadow: inset 0 1px 1px #002c9c, 0 0 10px #000;
|
||||
&:hover {
|
||||
color: #008cf7;
|
||||
}
|
||||
}
|
||||
.button.vote-yes {
|
||||
background: radial-gradient(
|
||||
at 0 -15%,
|
||||
rgba(255, 255, 255, 0.07) 70%,
|
||||
rgba(255, 255, 255, 0) 71%
|
||||
)
|
||||
0 0/80% 90% no-repeat content-box,
|
||||
linear-gradient(#ad0000, rgba(5, 0, 0, 0.22)) content-box,
|
||||
linear-gradient(#292929, #420000) border-box;
|
||||
box-shadow: inset 0 1px 1px #9c0000, 0 0 10px #000;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -10,6 +10,7 @@ const faIcons = [
|
|||
"BroadcastTower",
|
||||
"Camera",
|
||||
"CheckSquare",
|
||||
"Skull",
|
||||
"Cog",
|
||||
"Copy",
|
||||
"ExchangeAlt",
|
||||
|
|
|
@ -4,7 +4,9 @@ const state = () => ({
|
|||
playerCount: 0,
|
||||
playerId: "",
|
||||
claimedSeat: -1,
|
||||
nomination: false
|
||||
nomination: false,
|
||||
votes: [],
|
||||
lockedVote: -1
|
||||
});
|
||||
|
||||
const getters = {};
|
||||
|
@ -29,6 +31,11 @@ const mutations = {
|
|||
},
|
||||
nomination(state, nomination) {
|
||||
state.nomination = nomination;
|
||||
state.votes = [];
|
||||
},
|
||||
vote(state, [index, vote]) {
|
||||
state.votes = [...state.votes];
|
||||
state.votes[index] = vote === undefined ? !state.votes[index] : vote;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -99,6 +99,12 @@ class LiveSession {
|
|||
case "ping":
|
||||
this._handlePing(params);
|
||||
break;
|
||||
case "nomination":
|
||||
this._store.commit("session/nomination", params);
|
||||
break;
|
||||
case "vote":
|
||||
this._store.commit("session/vote", params);
|
||||
break;
|
||||
case "bye":
|
||||
this._handleBye(params);
|
||||
break;
|
||||
|
@ -291,7 +297,7 @@ class LiveSession {
|
|||
}
|
||||
// remove claimed seats from players that are no longer connected
|
||||
this._store.state.players.players.forEach(player => {
|
||||
if (player.id && !this._players[player.id]) {
|
||||
if (!this._isSpectator && player.id && !this._players[player.id]) {
|
||||
this._store.commit("players/update", {
|
||||
player,
|
||||
property: "id",
|
||||
|
@ -336,20 +342,50 @@ class LiveSession {
|
|||
* @private
|
||||
*/
|
||||
_updateSeat([index, value]) {
|
||||
if (this._isSpectator) return;
|
||||
const property = "id";
|
||||
const players = this._store.state.players.players;
|
||||
// remove previous seat
|
||||
const player = this._store.state.players.players.find(
|
||||
({ id }) => id === value
|
||||
);
|
||||
if (player) {
|
||||
this._store.commit("players/update", { player, property, value: "" });
|
||||
const oldIndex = players.findIndex(({ id }) => id === value);
|
||||
if (oldIndex >= 0 && oldIndex !== index) {
|
||||
this._store.commit("players/update", {
|
||||
player: players[oldIndex],
|
||||
property,
|
||||
value: ""
|
||||
});
|
||||
}
|
||||
// add playerId to new seat
|
||||
if (index >= 0) {
|
||||
const player = this._store.state.players.players[index];
|
||||
const player = players[index];
|
||||
if (!player) return;
|
||||
this._store.commit("players/update", { player, property, value });
|
||||
}
|
||||
// update player session list as if this was a ping
|
||||
this._handlePing([true, value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* A player nomination.
|
||||
* @param nomination [nominator, nominee]
|
||||
*/
|
||||
nomination(nomination) {
|
||||
if (this._isSpectator) return;
|
||||
const players = this._store.state.players.players;
|
||||
if (
|
||||
!nomination ||
|
||||
(players.length > nomination[0] && players.length > nomination[1])
|
||||
) {
|
||||
this._send("nomination", nomination);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a vote.
|
||||
* @param index
|
||||
*/
|
||||
vote([index]) {
|
||||
if (!this._isSpectator) return;
|
||||
this._send("vote", [index, this._store.state.session.votes[index]]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,6 +407,12 @@ module.exports = store => {
|
|||
case "session/claimSeat":
|
||||
session.claimSeat(payload);
|
||||
break;
|
||||
case "session/nomination":
|
||||
session.nomination(payload);
|
||||
break;
|
||||
case "session/vote":
|
||||
session.vote(payload);
|
||||
break;
|
||||
case "players/set":
|
||||
case "players/swap":
|
||||
case "players/move":
|
||||
|
|
Loading…
Reference in New Issue