finished adding night reminders to fabled

This commit is contained in:
Steffen 2020-11-30 22:04:21 +01:00
parent 02d7002e34
commit f10ff968a6
5 changed files with 206 additions and 142 deletions

View File

@ -148,10 +148,13 @@ body {
body { body {
font-size: 1.1em; font-size: 1.1em;
} }
.player .night em { .night-order em {
width: 30px; width: 30px;
height: 30px; height: 30px;
} }
.fabled .night-order.first span {
left: 30px;
}
} }
// Medium devices (tablets, less than 992px) // Medium devices (tablets, less than 992px)
@ -163,10 +166,13 @@ body {
#controls svg { #controls svg {
font-size: 20px; font-size: 20px;
} }
.player .night em { .night-order em {
width: 20px; width: 20px;
height: 20px; height: 20px;
} }
.fabled .night-order.first span {
left: 20px;
}
#townsquare { #townsquare {
padding: 10px; padding: 10px;
} }

View File

@ -18,7 +18,7 @@
<div class="life" @click="toggleStatus()"></div> <div class="life" @click="toggleStatus()"></div>
<div <div
class="night first" class="night-order first"
v-if="nightOrder.get(player).first && grimoire.isNightOrder" v-if="nightOrder.get(player).first && grimoire.isNightOrder"
> >
<em>{{ nightOrder.get(player).first }}.</em> <em>{{ nightOrder.get(player).first }}.</em>
@ -27,7 +27,7 @@
}}</span> }}</span>
</div> </div>
<div <div
class="night other" class="night-order other"
v-if="nightOrder.get(player).other && grimoire.isNightOrder" v-if="nightOrder.get(player).other && grimoire.isNightOrder"
> >
<em>{{ nightOrder.get(player).other }}.</em> <em>{{ nightOrder.get(player).other }}.</em>
@ -676,137 +676,11 @@ li.move:not(.from) .player .overlay svg.move {
} }
/**** Night reminders ****/ /**** Night reminders ****/
.player .night { .player .night-order {
position: absolute; z-index: 3;
width: 100%;
z-index: 2;
cursor: pointer;
opacity: 1;
transition: opacity 200ms;
display: flex;
top: 0;
align-items: center;
pointer-events: none;
&:after {
content: " ";
display: block;
padding-top: 100%;
}
#townsquare.public & {
opacity: 0;
pointer-events: none;
}
&:hover ~ .token .ability {
opacity: 0;
}
span {
display: flex;
position: absolute;
padding: 5px 10px 5px 30px;
width: 350px;
z-index: 25;
font-size: 70%;
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));
text-align: left;
align-items: center;
opacity: 0;
transition: opacity 200ms ease-in-out;
&:before {
transform: rotate(-90deg);
transform-origin: center top;
left: -98px;
top: 50%;
font-size: 100%;
position: absolute;
font-weight: bold;
text-align: center;
width: 200px;
}
&:after {
content: " ";
border: 10px solid transparent;
width: 0;
height: 0;
position: absolute;
}
}
&.first span {
right: 120%;
background: linear-gradient(
to right,
$townsfolk 0%,
rgba(0, 0, 0, 0.5) 20%
);
&:before {
content: "First Night";
}
&:after {
border-left-color: $townsfolk;
margin-left: 3px;
left: 100%;
}
}
&.other span {
left: 120%;
background: linear-gradient(to right, $demon 0%, rgba(0, 0, 0, 0.5) 20%);
&:before {
content: "Other Nights";
}
&:after {
right: 100%;
margin-right: 3px;
border-right-color: $demon;
}
}
em {
font-style: normal;
position: absolute;
width: 40px;
height: 40px;
border-radius: 50%;
border: 3px solid black;
filter: drop-shadow(0 0 6px rgba(0, 0, 0, 0.5));
font-weight: bold;
opacity: 1;
pointer-events: all;
transition: opacity 200ms;
display: flex;
justify-content: center;
align-items: center;
}
&.first em {
left: -10%;
background: linear-gradient(180deg, rgba(0, 0, 0, 1) 0%, $townsfolk 100%);
}
&.other em {
right: -10%;
background: linear-gradient(180deg, rgba(0, 0, 0, 1) 0%, $demon 100%);
}
em:hover + span {
opacity: 1;
}
#app.screenshot & {
display: none;
}
} }
.player.dead .night em { .player.dead .night-order em {
color: #ddd; color: #ddd;
background: linear-gradient(180deg, rgba(0, 0, 0, 1) 0%, gray 100%); background: linear-gradient(180deg, rgba(0, 0, 0, 1) 0%, gray 100%);
} }

View File

@ -56,11 +56,29 @@
</h3> </h3>
<ul> <ul>
<li <li
v-for="(fabledRole, index) in fabled" v-for="(role, index) in fabled"
:key="index" :key="index"
@click="removeFabled(index)" @click="removeFabled(index)"
> >
<Token :role="fabledRole"></Token> <div
class="night-order first"
v-if="nightOrder.get(role).first && grimoire.isNightOrder"
>
<em>{{ nightOrder.get(role).first }}.</em>
<span v-if="role.firstNightReminder">{{
role.firstNightReminder
}}</span>
</div>
<div
class="night-order other"
v-if="nightOrder.get(role).other && grimoire.isNightOrder"
>
<em>{{ nightOrder.get(role).other }}.</em>
<span v-if="role.otherNightReminder">{{
role.otherNightReminder
}}</span>
</div>
<Token :role="role"></Token>
</li> </li>
</ul> </ul>
</div> </div>
@ -71,7 +89,7 @@
</template> </template>
<script> <script>
import { mapState } from "vuex"; import { mapGetters, mapState } from "vuex";
import Player from "./Player"; import Player from "./Player";
import Token from "./Token"; import Token from "./Token";
import ReminderModal from "./modals/ReminderModal"; import ReminderModal from "./modals/ReminderModal";
@ -85,6 +103,7 @@ export default {
ReminderModal ReminderModal
}, },
computed: { computed: {
...mapGetters({ nightOrder: "players/nightOrder" }),
...mapState(["grimoire", "roles", "session"]), ...mapState(["grimoire", "roles", "session"]),
...mapState("players", ["players", "bluffs", "fabled"]) ...mapState("players", ["players", "bluffs", "fabled"])
}, },
@ -194,6 +213,8 @@ export default {
</script> </script>
<style lang="scss"> <style lang="scss">
@import "../vars.scss";
#townsquare { #townsquare {
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -288,7 +309,7 @@ export default {
.life, .life,
.token, .token,
.shroud, .shroud,
.night { .night-order {
transition-delay: ($i - 1) * 50ms; transition-delay: ($i - 1) * 50ms;
} }
@ -409,6 +430,9 @@ export default {
ul li { ul li {
width: 0; width: 0;
height: 0; height: 0;
.night-order {
opacity: 0;
}
.token { .token {
border-width: 0; border-width: 0;
} }
@ -424,6 +448,153 @@ export default {
z-index: 2; z-index: 2;
} }
/**** Night reminders ****/
.night-order {
position: absolute;
width: 100%;
cursor: pointer;
opacity: 1;
transition: opacity 200ms;
display: flex;
top: 0;
align-items: center;
pointer-events: none;
&:after {
content: " ";
display: block;
padding-top: 100%;
}
#townsquare.public & {
opacity: 0;
pointer-events: none;
}
&:hover ~ .token .ability {
opacity: 0;
}
span {
display: flex;
position: absolute;
padding: 5px 10px 5px 30px;
width: 350px;
z-index: 25;
font-size: 70%;
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));
text-align: left;
align-items: center;
opacity: 0;
transition: opacity 200ms ease-in-out;
&:before {
transform: rotate(-90deg);
transform-origin: center top;
left: -98px;
top: 50%;
font-size: 100%;
position: absolute;
font-weight: bold;
text-align: center;
width: 200px;
}
&:after {
content: " ";
border: 10px solid transparent;
width: 0;
height: 0;
position: absolute;
}
}
&.first span {
right: 120%;
background: linear-gradient(
to right,
$townsfolk 0%,
rgba(0, 0, 0, 0.5) 20%
);
&:before {
content: "First Night";
}
&:after {
border-left-color: $townsfolk;
margin-left: 3px;
left: 100%;
}
}
&.other span {
left: 120%;
background: linear-gradient(to right, $demon 0%, rgba(0, 0, 0, 0.5) 20%);
&:before {
content: "Other Nights";
}
&:after {
right: 100%;
margin-right: 3px;
border-right-color: $demon;
}
}
em {
font-style: normal;
position: absolute;
width: 40px;
height: 40px;
border-radius: 50%;
border: 3px solid black;
filter: drop-shadow(0 0 6px rgba(0, 0, 0, 0.5));
font-weight: bold;
opacity: 1;
pointer-events: all;
transition: opacity 200ms;
display: flex;
justify-content: center;
align-items: center;
z-index: 3;
}
&.first em {
left: -10%;
background: linear-gradient(180deg, rgba(0, 0, 0, 1) 0%, $townsfolk 100%);
}
&.other em {
right: -10%;
background: linear-gradient(180deg, rgba(0, 0, 0, 1) 0%, $demon 100%);
}
em:hover + span {
opacity: 1;
}
#app.screenshot & {
display: none;
}
// adjustment for fabled
.fabled &.first {
span {
right: auto;
left: 40px;
&:after {
left: auto;
right: 100%;
margin-left: 0;
margin-right: 3px;
border-left-color: transparent;
border-right-color: $townsfolk;
}
}
}
}
#townsquare:not(.spectator) .fabled ul li:hover .token:before { #townsquare:not(.spectator) .fabled ul li:hover .token:before {
opacity: 1; opacity: 1;
} }

View File

@ -24,7 +24,7 @@ const getters = {
return Math.min(nonTravelers.length, 15); return Math.min(nonTravelers.length, 15);
}, },
// calculate a Map of player => night order // calculate a Map of player => night order
nightOrder({ players }) { nightOrder({ players, fabled }) {
const firstNight = [0]; const firstNight = [0];
const otherNight = [0]; const otherNight = [0];
players.forEach(({ role }) => { players.forEach(({ role }) => {
@ -35,6 +35,14 @@ const getters = {
otherNight.push(role.otherNight); otherNight.push(role.otherNight);
} }
}); });
fabled.forEach(role => {
if (role.firstNight && !firstNight.includes(role.firstNight)) {
firstNight.push(role.firstNight);
}
if (role.otherNight && !otherNight.includes(role.otherNight)) {
otherNight.push(role.otherNight);
}
});
firstNight.sort((a, b) => a - b); firstNight.sort((a, b) => a - b);
otherNight.sort((a, b) => a - b); otherNight.sort((a, b) => a - b);
const nightOrder = new Map(); const nightOrder = new Map();
@ -43,6 +51,11 @@ const getters = {
const other = Math.max(otherNight.indexOf(player.role.otherNight), 0); const other = Math.max(otherNight.indexOf(player.role.otherNight), 0);
nightOrder.set(player, { first, other }); nightOrder.set(player, { first, other });
}); });
fabled.forEach(role => {
const first = Math.max(firstNight.indexOf(role.firstNight), 0);
const other = Math.max(otherNight.indexOf(role.otherNight), 0);
nightOrder.set(role, { first, other });
});
return nightOrder; return nightOrder;
} }
}; };

View File

@ -18,14 +18,14 @@ module.exports = store => {
} }
if (localStorage.bluffs !== undefined) { if (localStorage.bluffs !== undefined) {
JSON.parse(localStorage.bluffs).forEach((role, index) => { JSON.parse(localStorage.bluffs).forEach((role, index) => {
store.commit("setBluff", { store.commit("players/setBluff", {
index, index,
role: store.state.roles.get(role) || {} role: store.state.roles.get(role) || {}
}); });
}); });
} }
if (localStorage.fabled !== undefined) { if (localStorage.fabled !== undefined) {
store.commit("setFabled", { store.commit("players/setFabled", {
fabled: JSON.parse(localStorage.fabled).map(id => fabled: JSON.parse(localStorage.fabled).map(id =>
store.state.fabled.get(id) store.state.fabled.get(id)
) )
@ -88,13 +88,13 @@ module.exports = store => {
localStorage.setItem("roles", JSON.stringify(payload)); localStorage.setItem("roles", JSON.stringify(payload));
} }
break; break;
case "setBluff": case "players/setBluff":
localStorage.setItem( localStorage.setItem(
"bluffs", "bluffs",
JSON.stringify(state.players.bluffs.map(({ id }) => id)) JSON.stringify(state.players.bluffs.map(({ id }) => id))
); );
break; break;
case "setFabled": case "players/setFabled":
localStorage.setItem( localStorage.setItem(
"fabled", "fabled",
JSON.stringify(state.players.fabled.map(({ id }) => id)) JSON.stringify(state.players.fabled.map(({ id }) => id))