diff --git a/assets/images/question_mark.svg b/assets/images/question_mark.svg
new file mode 100644
index 0000000..a90b9f9
--- /dev/null
+++ b/assets/images/question_mark.svg
@@ -0,0 +1,14 @@
+
diff --git a/javascript/game.js b/javascript/game.js
index 4932124..e1b4dae 100644
--- a/javascript/game.js
+++ b/javascript/game.js
@@ -70,14 +70,19 @@ function triggerEntranceAnimation(selector, entranceClass, exitClass, image) {
transitionEl.entranceClass = entranceClass;
transitionEl.exitClass = exitClass;
transitionEl.offsetWidth;
- if (image && standardRoles.includes(currentGame.killedRole)) {
- transitionEl.classList.remove("killed-role-custom");
- transitionEl.setAttribute("src", "../assets/images/roles/" + currentGame.killedRole.replace(/\s/g, '') + ".png");
- } else {
- if (image) {
- transitionEl.setAttribute("src", "../assets/images/custom.svg");
- transitionEl.setAttribute("class", "killed-role-custom");
+ if (currentGame.reveals) {
+ if (image && standardRoles.includes(currentGame.killedRole)) {
+ transitionEl.classList.remove("killed-role-custom");
+ transitionEl.setAttribute("src", "../assets/images/roles/" + currentGame.killedRole.replace(/\s/g, '') + ".png");
+ } else {
+ if (image) {
+ transitionEl.setAttribute("src", "../assets/images/custom.svg");
+ transitionEl.setAttribute("class", "killed-role-custom");
+ }
}
+ } else {
+ transitionEl.setAttribute("src", "../assets/images/question_mark.svg");
+ transitionEl.setAttribute("class", "killed-role-hidden");
}
transitionEl.classList.add(entranceClass);
}
@@ -148,7 +153,9 @@ function renderGame() {
document.querySelector("#message-box").style.display = 'block';
if (currentGame.killedRole && currentGame.lastKilled !== lastKilled) { // a new player has been killed
lastKilled = currentGame.lastKilled;
- document.getElementById("killed-name").innerText = currentGame.killedPlayer + " was a " + currentGame.killedRole + "!";
+ document.getElementById("killed-name").innerText = currentGame.reveals
+ ? currentGame.killedPlayer + " was a " + currentGame.killedRole + "!"
+ : currentGame.killedPlayer + " has died!";
playKilledAnimation();
document.getElementById("message-box").innerText = currentGame.message;
}
@@ -205,11 +212,12 @@ function renderGame() {
function renderDeadAndAliveInformation() {
// TODO: Refactor this function.
- let infoContainer = document.getElementById("info-container");
- let alivePlayers = currentGame.players.filter((player) => !player.dead).sort((a, b) =>
+ currentGame.players = currentGame.players.sort((a, b) =>
{
return a.card.role > b.card.role ? 1 : -1;
});
+ let infoContainer = document.getElementById("info-container");
+ let alivePlayers = currentGame.players.filter((player) => !player.dead);
let deadPlayers = currentGame.players.filter((player) => player.dead);
deadPlayers.sort((a, b) => { // sort players by the time they died
return new Date(a.deadAt) > new Date(b.deadAt) ? -1 : 1;
@@ -220,49 +228,24 @@ function renderDeadAndAliveInformation() {
let killedHeader = document.createElement("h2");
killedHeader.innerText = "Killed Players";
killedContainer.appendChild(killedHeader);
- deadPlayers.forEach((player) => {
- let deadPlayerClass = player.card.team === "good" ? "dead-player-village" : "dead-player-evil";
- if (player.card.isTypeOfWerewolf) {
- deadPlayerClass += " dead-player-wolf";
- }
- const killedPlayer = document.createElement("div");
- killedPlayer.setAttribute("class", "killed-player " + deadPlayerClass);
- killedPlayer.innerText = player.name + ": " + player.card.role;
- killedContainer.appendChild(killedPlayer);
- });
+
+ addDeadPlayers(deadPlayers, killedContainer);
let aliveContainer = document.createElement("div");
aliveContainer.setAttribute("id", "alive-container");
let aliveHeader = document.createElement("h2");
aliveContainer.appendChild(aliveHeader);
- aliveHeader.innerText = "Roles Still Alive";
+ aliveHeader.innerText = currentGame.reveals
+ ? "Roles Still Alive"
+ : "Roles in the Game";
var rollCounter = {}; // RTM
- alivePlayers.forEach((player) => {
- let alivePlayerClass = player.card.team === "good" ? "alive-player-village" : "alive-player-evil";
- if (player.card.isTypeOfWerewolf) {
- alivePlayerClass += " alive-player-wolf";
- }
- //RTM
- if (rollCounter.hasOwnProperty(player.card.role)) {
- rollCounter[player.card.role] += 1;
- }
- else {
- rollCounter[player.card.role] = 1;
- //RTM
- const alivePlayer = document.createElement("div");
- alivePlayer.setAttribute("class", "alive-player " + alivePlayerClass);
- alivePlayer.innerHTML = "
" + player.card.role + "
";
- let roleCount = document.createElement("span"); // RTM
- roleCount.setAttribute("class","rolecount");
- //Add hidden description span - RTM 4/18/2020
- let playerCardInfo=document.createElement("span");
- playerCardInfo.setAttribute("class","tooltiptext");
- playerCardInfo.innerText=player.card.description;
- alivePlayer.prepend(roleCount);
- alivePlayer.appendChild(playerCardInfo);
- aliveContainer.appendChild(alivePlayer);
- }
- });
+
+ if (currentGame.reveals) {
+ addAlivePlayers(alivePlayers, aliveContainer, rollCounter);
+ } else {
+ addAlivePlayers(currentGame.players, aliveContainer, rollCounter);
+ }
+
if (infoContainer === null) {
infoContainer = document.createElement("div");
infoContainer.setAttribute("id", "info-container");
@@ -271,7 +254,7 @@ function renderDeadAndAliveInformation() {
document.getElementById("game-container").appendChild(infoContainer);
// Has to be done AFTER the infoContainer is rendered in the DOM to insert the updated counts
for (let x of document.getElementsByClassName("alive-player")) {
- x.getElementsByClassName("rolecount")[0].innerText = rollCounter[x.getElementsByTagName("p")[0].innerText];
+ x.getElementsByClassName("rolecount")[0].innerText = rollCounter[x.getElementsByTagName("p")[0].innerText];
}
} else {
document.getElementById("killed-container").remove();
@@ -280,11 +263,58 @@ function renderDeadAndAliveInformation() {
document.getElementById("info-container").append(aliveContainer);
// Has to be done AFTER the infoContainer is rendered in the DOM to insert the updated counts
for (let x of document.getElementsByClassName("alive-player")) {
- x.getElementsByClassName("rolecount")[0].innerText = rollCounter[x.getElementsByTagName("p")[0].innerText];
+ x.getElementsByClassName("rolecount")[0].innerText = rollCounter[x.getElementsByTagName("p")[0].innerText];
}
}
}
+function addDeadPlayers(deadPlayers, killedContainer) {
+ deadPlayers.forEach((player) => {
+ let deadPlayerClass = player.card.team === "good" ? "dead-player-village" : "dead-player-evil";
+ if (player.card.isTypeOfWerewolf) {
+ deadPlayerClass += " dead-player-wolf";
+ }
+ const killedPlayer = document.createElement("div");
+ if (currentGame.reveals) {
+ killedPlayer.setAttribute("class", "killed-player " + deadPlayerClass);
+ } else {
+ killedPlayer.setAttribute("class", "killed-player dead-player-no-reveals");
+ }
+ killedPlayer.innerText = currentGame.reveals
+ ? player.name + ": " + player.card.role
+ : player.name;
+ killedContainer.appendChild(killedPlayer);
+ });
+}
+
+function addAlivePlayers(alivePlayers, aliveContainer, rollCounter) {
+ alivePlayers.forEach((player) => {
+ let alivePlayerClass = player.card.team === "good" ? "alive-player-village" : "alive-player-evil";
+ if (player.card.isTypeOfWerewolf) {
+ alivePlayerClass += " alive-player-wolf";
+ }
+ //RTM
+ if (rollCounter.hasOwnProperty(player.card.role)) {
+ rollCounter[player.card.role] += 1;
+ } else {
+ rollCounter[player.card.role] = 1;
+ //RTM
+ const alivePlayer = document.createElement("div");
+ alivePlayer.setAttribute("class", "alive-player " + alivePlayerClass);
+ alivePlayer.innerHTML = "" + player.card.role + "
";
+ let roleCount = document.createElement("span"); // RTM
+ roleCount.setAttribute("class", "rolecount");
+ //Add hidden description span - RTM 4/18/2020
+ let playerCardInfo=document.createElement("span");
+ playerCardInfo.setAttribute("class","tooltiptext");
+ playerCardInfo.innerText=player.card.description;
+ alivePlayer.prepend(roleCount);
+ alivePlayer.appendChild(playerCardInfo);
+ aliveContainer.appendChild(alivePlayer);
+ }
+ });
+}
+
function renderPlayerCard(player) {
const card = player.card;
const cardArt = standardRoles.includes(card.role) ?
diff --git a/javascript/index.js b/javascript/index.js
new file mode 100644
index 0000000..419cfa1
--- /dev/null
+++ b/javascript/index.js
@@ -0,0 +1,27 @@
+let gameModeSelect = false;
+
+window.onload = function() {
+ document.getElementById("create-game").addEventListener("click", toggleGameModeSelect);
+ document.getElementById("game-mode-back").addEventListener("click", toggleGameModeSelect)
+};
+
+function toggleGameModeSelect() {
+ gameModeSelect = !gameModeSelect;
+ let mainButtons = document.getElementById("main-buttons");
+ let gameModes = document.getElementById("game-mode-select");
+ if (gameModeSelect) {
+ mainButtons.classList.remove("slide-in");
+ mainButtons.offsetWidth;
+ mainButtons.classList.add("slide-out");
+ mainButtons.addEventListener("animationend", function() { mainButtons.style.display = "none" }, {capture: true, once: true});
+
+ gameModes.style.display = "flex";
+ } else {
+ gameModes.style.display = "none";
+
+ mainButtons.style.display = "flex";
+ mainButtons.classList.remove("slide-out");
+ mainButtons.offsetWidth;
+ mainButtons.classList.add("slide-in");
+ }
+}
diff --git a/javascript/setup.js b/javascript/setup.js
index 7dd1766..79d9a5f 100644
--- a/javascript/setup.js
+++ b/javascript/setup.js
@@ -5,8 +5,9 @@ import {CardManager} from './modules/card-manager.js'
const socket = io();
class Game {
- constructor(accessCode, size, deck, time, hasDreamWolf) {
+ constructor(accessCode, reveals, size, deck, time, hasDreamWolf) {
this.accessCode = accessCode;
+ this.reveals = reveals;
this.size = size;
this.deck = deck;
this.time = time;
@@ -37,6 +38,10 @@ Array.from(document.getElementsByClassName("close")).forEach(function(element) {
// render all of the available cards to the user
window.onload = function() {
+ const urlParams = new URLSearchParams(window.location.search);
+ document.getElementById("create-game-header").innerText = urlParams.get('reveals') === "true"
+ ? "Create Reveal Game"
+ : "Create No-Reveal Game";
readInUserCustomRoles();
renderAvailableCards(false);
};
@@ -411,6 +416,9 @@ function buildDeckFromQuantities() {
function createGame() {
if (document.getElementById("name").value.length > 0 && atLeastOnePlayer) {
+ const urlParams = new URLSearchParams(window.location.search);
+ const revealParam = urlParams.get('reveals');
+
// generate 6 digit access code
let code = "";
let charPool = "abcdefghijklmnopqrstuvwxyz0123456789";
@@ -430,6 +438,7 @@ function createGame() {
let gameDeck = buildDeckFromQuantities();
const game = new Game(
code,
+ revealParam === "true",
gameSize,
gameDeck,
Math.ceil(document.getElementById("time").value),
diff --git a/server-helper.js b/server-helper.js
index 3ed2a21..60270e1 100644
--- a/server-helper.js
+++ b/server-helper.js
@@ -32,7 +32,9 @@ module.exports = class {
game.killedPlayer = player.name;
game.lastKilled = player.id;
game.killedRole = player.card.role;
- game.message = player.name + ", a " + player.card.role + ", was killed!";
+ game.message = game.reveals
+ ? player.name + ", a " + player.card.role + ", was killed!"
+ : player.name + " has died!";
console.log(game.message);
if (player.card.role === "Werewolf" && game.hasDreamWolf) {
this.activateDreamWolvesIfNeeded(game);
diff --git a/stylesheets/styles.css b/stylesheets/styles.css
index 6ce63e5..77563d1 100644
--- a/stylesheets/styles.css
+++ b/stylesheets/styles.css
@@ -238,7 +238,7 @@
width: 35em;
}
- #main-buttons a {
+ #main-buttons a, #main-buttons button {
max-width: 15em;
}
@@ -324,6 +324,7 @@
html, body {
margin: 0 auto;
+ height: 100%;
color: #bfb8b8;
font-family: 'sitewide-sans-serif', sans-serif;
background-color: #23282b !important;
@@ -342,7 +343,7 @@ html, body {
@keyframes slide-fade {
from {
opacity: 0;
- transform: translateX(-80px)
+ transform: translateX(80px)
}
to {
@@ -351,6 +352,18 @@ html, body {
}
}
+@keyframes slide-fade-remove {
+ from {
+ opacity: 1;
+ transform: translateX(0px)
+
+ }
+ to {
+ opacity: 0;
+ transform: translateX(-80px);
+ }
+}
+
#app-content {
text-align: center;
margin: 0 auto;
@@ -360,6 +373,7 @@ html, body {
#landing-container {
width: 100%;
height: 100%;
+ position: relative;
text-align: center;
background: linear-gradient(0deg, rgba(35,40,43,0.7959558823529411) 18%, rgba(131,131,131,0.6222864145658263) 100%);
}
@@ -766,29 +780,9 @@ button {
flex-direction: column;
align-items: center;
justify-content: center;
-}
-
-#main-buttons a:nth-child(1) {
- animation: fadein 0.3s ease-in;
- animation-fill-mode: backwards;
-}
-
-#main-buttons a:nth-child(2) {
- animation: fadein 0.3s ease-in;
- animation-fill-mode: backwards;
- animation-delay: 0.1s;
-}
-
-#main-buttons a:nth-child(3) {
- animation: fadein 0.3s ease-in;
- animation-fill-mode: backwards;
- animation-delay: 0.2s;
-}
-
-#main-buttons a:nth-child(4) {
- animation: fadein 0.3s ease-in;
- animation-fill-mode: backwards;
- animation-delay: 0.3s;
+ max-width: 18em;
+ margin: 0 auto;
+ overflow: hidden;
}
#main-buttons button {
@@ -801,7 +795,60 @@ button {
}
#main-buttons a {
- width: 75%;
+ width: 100%;
+}
+
+#game-mode-select {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ position: absolute;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+}
+
+#landing-container .slide-in {
+ animation: slide-fade 0.25s;
+ animation-delay: 0.125s;
+ animation-fill-mode: both;
+}
+
+#landing-container .slide-out {
+ animation: slide-fade-remove 0.25s;
+}
+
+
+#game-mode-select .game-mode {
+ width: 7em;
+ background-color: transparent;
+ color: whitesmoke;
+ border: 1px solid whitesmoke;
+ font-size: 30px;
+ font-weight: bold;
+ padding: 5px;
+ margin-bottom: 0.5em;
+ border-radius: 5px;
+}
+
+#game-mode-select .game-mode:hover {
+ cursor: pointer;
+ background-color: #494f52;
+}
+
+#game-mode-select span {
+ font-size: 50px;
+ font-weight: bold;
+ cursor: pointer;
+ margin-bottom: 0.2em;
+ text-align: left;
+ width: 100%;
+}
+
+#game-mode-select span:hover {
+ color: #333243;
}
#card-select-header {
@@ -813,11 +860,19 @@ button {
flex-direction: column;
}
-#card-select-header a {
+#card-select-header a, #landing-container #game-mode-select a:nth-child(2) {
text-decoration: underline;
color: #b8c4ff;
}
+#landing-container #game-mode-select a:nth-child(2) {
+ text-decoration: underline;
+ color: #b8c4ff;
+ text-align: left;
+ width: 100%;
+ margin-bottom: 1em;
+}
+
#card-select-header span > div {
display: flex;
align-items: center;
@@ -1462,6 +1517,10 @@ label {
font-size: 40px;
}
+.faq-question {
+ max-width: 60em;
+}
+
#learn-container button, #faq-container button {
margin-top: 1em;
}
@@ -1562,6 +1621,10 @@ label {
color: #bd2a2a;
}
+.dead-player-no-reveals {
+ color: whitesmoke !important;
+}
+
.alive-player-wolf, .dead-player-wolf {
border: 2px solid #bd2a2a;
}
@@ -1596,6 +1659,10 @@ label {
padding: 95px;
}
+.killed-role-hidden {
+ padding-top: 3em;
+}
+
@keyframes slide-fade-in-top {
0% {
opacity: 0;
diff --git a/views/create_game.html b/views/create_game.html
index b06c6e0..d43bd71 100644
--- a/views/create_game.html
+++ b/views/create_game.html
@@ -62,7 +62,7 @@
-
+
+
+
+
If you are playing a game with "reveals," players' roles will be revealed when they die. Otherwise, they remain a mystery.
+