mirror of
https://github.com/AlecM33/Werewolf.git
synced 2025-12-26 15:57:50 +01:00
first draft editing of custom roles
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<!-- Created with Method Draw - http://github.com/duopixel/Method-Draw/ -->
|
||||
<g>
|
||||
<title>background</title>
|
||||
<rect fill="none" id="canvas_background" height="211" width="211" y="-1" x="-1"/>
|
||||
<rect fill="none" id="canvas_background" height="172" width="172" y="-1" x="-1"/>
|
||||
<g display="none" overflow="visible" y="0" x="0" height="100%" width="100%" id="canvasGrid">
|
||||
<rect fill="url(#gridpattern)" stroke-width="0" y="0" x="0" height="100%" width="100%"/>
|
||||
</g>
|
||||
|
||||
|
Before Width: | Height: | Size: 840 B After Width: | Height: | Size: 840 B |
@@ -1,14 +1,14 @@
|
||||
<svg width="132" height="192" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="172" height="172" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Created with Method Draw - http://github.com/duopixel/Method-Draw/ -->
|
||||
<g>
|
||||
<title>background</title>
|
||||
<rect fill="none" id="canvas_background" height="194" width="134" y="-1" x="-1"/>
|
||||
<rect fill="none" id="canvas_background" height="174" width="174" y="-1" x="-1"/>
|
||||
<g display="none" overflow="visible" y="0" x="0" height="100%" width="100%" id="canvasGrid">
|
||||
<rect fill="url(#gridpattern)" stroke-width="0" y="0" x="0" height="100%" width="100%"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<title>Layer 1</title>
|
||||
<path id="svg_2" d="m124.961908,17.099698l-20.881294,-13.124489c-5.268417,-3.308101 -12.210471,-1.715912 -15.530119,3.553603l-8.230499,13.1l39.946799,25.089697l8.23699,-13.093919c3.307049,-5.275788 1.728716,-12.224161 -3.541878,-15.524891l0,0zm-115.727379,116.707156l39.948976,25.089439l65.110209,-103.65022l-39.967994,-25.095989l-65.091198,103.656764l0.000007,0.000007zm-6.102198,31.877066l-0.88233,23.566079l20.849261,-11.027851l19.374887,-10.229887l-38.540057,-24.219893l-0.801755,21.911559l0,0l-0.000007,-0.000007z" stroke-width="4.5" stroke="none" fill="green"/>
|
||||
<path id="svg_1" d="m139.382578,14.249727l-18.982996,-11.931355c-4.78947,-3.007365 -11.100429,-1.559921 -14.118291,3.230549l-7.482272,11.909092l36.315275,22.808817l7.488173,-11.903564c3.006409,-4.796172 1.57156,-11.112875 -3.219889,-14.113539l0,0zm-105.206717,106.097424l36.317254,22.808582l59.191104,-94.22748l-36.334543,-22.814538l-59.173821,94.233429l0.000006,0.000006zm-5.547453,28.979153l-0.802118,21.42371l18.953876,-10.02532l17.613535,-9.299898l-35.036418,-22.018086l-0.728868,19.9196l0,0l-0.000006,-0.000006z" stroke-width="1.5" stroke="none" fill="green"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
94
static/modules/card-manager.js
Normal file
94
static/modules/card-manager.js
Normal file
@@ -0,0 +1,94 @@
|
||||
const finishedArtArray = ["Villager", "Werewolf", "Seer", "Shadow", "Hunter", "Mason", "Minion", "Sorcerer", "Dream Wolf"];
|
||||
|
||||
export class CardManager {
|
||||
constructor() {}
|
||||
|
||||
static createCard(card) {
|
||||
return new Card(card.role, card.team, card.description, card.quantity=0, card.isTypeOfWerewolf, card.custom, card.saved);
|
||||
}
|
||||
|
||||
// builds element for the informational role modal on the setup page
|
||||
static constructModalRoleElement(card) {
|
||||
const modalRole = document.createElement("div");
|
||||
modalRole.setAttribute("class", "modal-role");
|
||||
const roleClass = card.team === "good" ? "role-village" : "role-wolf";
|
||||
let roleImage;
|
||||
if (card.custom === true) {
|
||||
roleImage = "<img alt='No art' class='card-image-custom' src='/assets/images/custom.svg' />";
|
||||
} else {
|
||||
roleImage = finishedArtArray.includes(card.role) ?
|
||||
"<img alt='No art' src='/assets/images/roles-small/" + card.role.replace(/\s/g, '') + ".png' />"
|
||||
: "<span>Art soon.</span>";
|
||||
}
|
||||
modalRole.innerHTML =
|
||||
"<div>" +
|
||||
roleImage +
|
||||
"<div>" +
|
||||
"<h2 class='" + roleClass + "'>" + card.role + "</h2>" +
|
||||
"<p>" + card.team + "</p>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"<p>" + card.description + "</p>";
|
||||
return modalRole;
|
||||
}
|
||||
|
||||
static constructDeckBuilderElement(card, index) {
|
||||
const cardContainer = document.createElement("div");
|
||||
|
||||
const quantityClass = card.team === "good" ? "card-quantity quantity-village" : "card-quantity quantity-wolf";
|
||||
|
||||
let cardClass = card.isTypeOfWerewolf ? "card card-werewolf" : "card";
|
||||
cardContainer.setAttribute("class", cardClass);
|
||||
cardContainer.setAttribute("id", "card-" + index);
|
||||
cardContainer.innerHTML =
|
||||
"<div class='card-top'>" +
|
||||
"<div class='card-header'>" +
|
||||
"<div>" +
|
||||
"<p class='card-role'>" + card.role + "</p>" +
|
||||
"<div class='" + quantityClass + "'>" + card.quantity + "</div>" +
|
||||
"</div>" +
|
||||
"<p>+</p>" +
|
||||
"</div>" +
|
||||
"</div>";
|
||||
cardContainer.innerHTML = card.custom
|
||||
? cardContainer.innerHTML += "<img class='card-image card-image-custom' src='/assets/images/custom.svg' alt='" + card.role + "'/>"
|
||||
: cardContainer.innerHTML +="<img class='card-image' src='/assets/images/roles-small/" + card.role.replace(/\s/g, '') + ".png' alt='" + card.role + "'/>";
|
||||
cardContainer.innerHTML +=
|
||||
"<div class='card-bottom'>" +
|
||||
"<p>-</p>" +
|
||||
"</div>";
|
||||
|
||||
return cardContainer;
|
||||
}
|
||||
|
||||
static constructCustomCardIndicator() {
|
||||
let customCard = document.createElement("div");
|
||||
customCard.classList.add("card", "custom-card");
|
||||
customCard.setAttribute("id", "custom");
|
||||
|
||||
let cardHeader = document.createElement("h1");
|
||||
cardHeader.innerText = "Add Custom Role";
|
||||
|
||||
let cardBody = document.createElement("div");
|
||||
cardBody.innerText = "+";
|
||||
|
||||
customCard.appendChild(cardHeader);
|
||||
customCard.appendChild(cardBody);
|
||||
|
||||
return customCard;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Card {
|
||||
constructor(role, team, description, quantity, isTypeOfWerewolf, custom, saved) {
|
||||
this.id = null;
|
||||
this.role = role;
|
||||
this.isTypeOfWerewolf = isTypeOfWerewolf;
|
||||
this.team = team;
|
||||
this.description = description;
|
||||
this.quantity = quantity;
|
||||
this.custom = custom;
|
||||
this.saved = saved;
|
||||
}
|
||||
}
|
||||
322
static/setup.js
322
static/setup.js
@@ -1,20 +1,8 @@
|
||||
import {cards} from './cards.js'
|
||||
import {utility} from './util.js'
|
||||
import {CardManager} from './modules/card-manager.js'
|
||||
|
||||
const socket = io();
|
||||
const finishedArtArray = ["Villager", "Werewolf", "Seer", "Shadow", "Hunter", "Mason", "Minion", "Sorcerer", "Dream Wolf"];
|
||||
|
||||
// important declarations
|
||||
class Card {
|
||||
constructor(role, team, description, isTypeOfWerewolf) {
|
||||
this.id = null;
|
||||
this.role = role;
|
||||
this.isTypeOfWerewolf = isTypeOfWerewolf;
|
||||
this.team = team;
|
||||
this.description = description;
|
||||
this.quantity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
class Game {
|
||||
constructor(accessCode, size, deck, time, hasDreamWolf) {
|
||||
@@ -58,198 +46,229 @@ function renderAvailableCards() {
|
||||
});
|
||||
document.getElementById("card-select").innerHTML = "";
|
||||
document.getElementById("roles").innerHTML = "";
|
||||
document.getElementById("custom-roles").innerHTML = "";
|
||||
for (let i = 0; i < cards.length; i ++) {
|
||||
const newCard = new Card(cards[i].role, cards[i].team, cards[i].description, cards[i].isTypeOfWerewolf);
|
||||
// put card info in the informational role description modal
|
||||
const modalRole = document.createElement("div");
|
||||
modalRole.setAttribute("class", "modal-role");
|
||||
const roleClass = cards[i].team === "good" ? "role-village" : "role-wolf";
|
||||
let roleImage;
|
||||
if (cards[i].custom === true) {
|
||||
roleImage = "<img alt='No art' class='card-image-custom' src='/assets/images/custom.svg' />";
|
||||
} else {
|
||||
roleImage = finishedArtArray.includes(cards[i].role) ?
|
||||
"<img alt='No art' src='/assets/images/roles-small/" + cards[i].role.replace(/\s/g, '') + ".png' />"
|
||||
: "<span>Art soon.</span>";
|
||||
const card = CardManager.createCard(cards[i]);
|
||||
if (card.custom) {
|
||||
renderCustomRoleInModal(cards[i], i);
|
||||
}
|
||||
modalRole.innerHTML =
|
||||
"<div>" +
|
||||
roleImage +
|
||||
"<div>" +
|
||||
"<h2 class='" + roleClass + "'>" + cards[i].role + "</h2>" +
|
||||
"<p>" + cards[i].team + "</p>" +
|
||||
"</div>" +
|
||||
"</div>" +
|
||||
"<p>" + cards[i].description + "</p>";
|
||||
fullDeck.push(card);
|
||||
|
||||
document.getElementById("roles").appendChild(modalRole);
|
||||
document.getElementById("roles").appendChild(CardManager.constructModalRoleElement(card));
|
||||
document.getElementById("card-select").appendChild(CardManager.constructDeckBuilderElement(card, i));
|
||||
|
||||
fullDeck.push(newCard);
|
||||
|
||||
const cardContainer = document.createElement("div");
|
||||
|
||||
const quantityClass = cards[i].team === "good" ? "card-quantity quantity-village" : "card-quantity quantity-wolf";
|
||||
|
||||
let cardClass = newCard.isTypeOfWerewolf ? "card card-werewolf" : "card";
|
||||
cardContainer.setAttribute("class", cardClass);
|
||||
cardContainer.setAttribute("id", "card-" + i);
|
||||
cardContainer.innerHTML =
|
||||
"<div class='card-top'>" +
|
||||
"<div class='card-header'>" +
|
||||
"<div>" +
|
||||
"<p class='card-role'>" + newCard.role + "</p>" +
|
||||
"<div class='" + quantityClass + "'>" + newCard.quantity + "</div>" +
|
||||
"</div>" +
|
||||
"<p>+</p>" +
|
||||
"</div>" +
|
||||
"</div>";
|
||||
cardContainer.innerHTML = cards[i].custom
|
||||
? cardContainer.innerHTML += "<img class='card-image card-image-custom' src='../assets/images/custom.svg' alt='" + newCard.role + "'/>"
|
||||
: cardContainer.innerHTML +="<img class='card-image' src='../assets/images/roles-small/" + newCard.role.replace(/\s/g, '') + ".png' alt='" + newCard.role + "'/>";
|
||||
cardContainer.innerHTML +=
|
||||
"<div class='card-bottom'>" +
|
||||
"<p>-</p>" +
|
||||
"</div>";
|
||||
document.getElementById("card-select").appendChild(cardContainer);
|
||||
// Add event listeners to the top and bottom halves of the card to change the quantity.
|
||||
let cardTop = document.getElementById("card-" + i).getElementsByClassName("card-top")[0];
|
||||
let cardQuantity = document.getElementById("card-" + i).getElementsByClassName("card-quantity")[0];
|
||||
let cardBottom = document.getElementById("card-" + i).getElementsByClassName("card-bottom")[0];
|
||||
cardTop.addEventListener("click", incrementCardQuantity, false);
|
||||
cardBottom.addEventListener("click", decrementCardQuantity, false);
|
||||
cardTop.card = newCard;
|
||||
cardTop.card = card;
|
||||
cardTop.quantityEl = cardQuantity;
|
||||
cardBottom.card = newCard;
|
||||
cardBottom.card = card;
|
||||
cardBottom.quantityEl = cardQuantity;
|
||||
|
||||
}
|
||||
renderCustomCard();
|
||||
resetCardQuantities();
|
||||
}
|
||||
|
||||
function renderCustomCard() {
|
||||
let customCard = document.createElement("div");
|
||||
customCard.classList.add("card", "custom-card");
|
||||
customCard.setAttribute("id", "custom");
|
||||
if (document.getElementById("custom-roles").getElementsByClassName("custom-role-edit").length === 0) {
|
||||
document.getElementById("custom-roles").innerHTML = "<h2>You haven't added any custom cards.</h2>";
|
||||
}
|
||||
|
||||
let cardHeader = document.createElement("h1");
|
||||
cardHeader.innerText = "Add Custom Role";
|
||||
|
||||
let cardBody = document.createElement("div");
|
||||
cardBody.innerText = "+";
|
||||
|
||||
customCard.appendChild(cardHeader);
|
||||
customCard.appendChild(cardBody);
|
||||
document.getElementById("card-select").appendChild(customCard);
|
||||
|
||||
customCard.addEventListener("click", function() {
|
||||
let customCardElement = CardManager.constructCustomCardIndicator();
|
||||
document.getElementById("card-select").appendChild(customCardElement);
|
||||
customCardElement.addEventListener("click", function() {
|
||||
displayModal("custom-card-modal");
|
||||
});
|
||||
}
|
||||
|
||||
function addCustomCardToRoles(e) {
|
||||
e.preventDefault();
|
||||
let newCard = {
|
||||
role: document.getElementById("custom-role-name").value,
|
||||
team: document.getElementById("custom-role-team").value,
|
||||
description: document.getElementById("custom-role-desc").value,
|
||||
isTypeOfWerewolf: document.getElementById("custom-role-wolf").checked,
|
||||
custom: true,
|
||||
saved: document.getElementById("custom-role-remember").checked
|
||||
};
|
||||
cards.push(newCard);
|
||||
renderAvailableCards();
|
||||
if (!cards.find((card) => card.role === document.getElementById("custom-role-name").value)) {
|
||||
let newCard = {
|
||||
role: document.getElementById("custom-role-name").value,
|
||||
team: document.getElementById("custom-role-team").value,
|
||||
description: document.getElementById("custom-role-desc").value,
|
||||
isTypeOfWerewolf: document.getElementById("custom-role-wolf").checked,
|
||||
custom: true,
|
||||
saved: document.getElementById("custom-role-remember").checked
|
||||
};
|
||||
cards.push(newCard);
|
||||
renderAvailableCards();
|
||||
|
||||
if (newCard.saved === true) {
|
||||
let existingRoles = localStorage.getItem("play-werewolf-custom-roles");
|
||||
if (existingRoles !== null) {
|
||||
let rolesArray;
|
||||
try {
|
||||
rolesArray = JSON.parse(existingRoles);
|
||||
} catch(e) {
|
||||
console.error(e.message);
|
||||
if (newCard.saved === true) {
|
||||
let existingRoles = localStorage.getItem("play-werewolf-custom-roles");
|
||||
if (existingRoles !== null) {
|
||||
let rolesArray;
|
||||
try {
|
||||
rolesArray = JSON.parse(existingRoles);
|
||||
} catch (e) {
|
||||
console.error(e.message);
|
||||
}
|
||||
if (rolesArray) {
|
||||
rolesArray.push(newCard);
|
||||
}
|
||||
localStorage.setItem("play-werewolf-custom-roles", JSON.stringify(rolesArray));
|
||||
} else {
|
||||
localStorage.setItem("play-werewolf-custom-roles", JSON.stringify(new Array(newCard)));
|
||||
}
|
||||
if (rolesArray) {
|
||||
rolesArray.push(newCard);
|
||||
}
|
||||
localStorage.setItem("play-werewolf-custom-roles", JSON.stringify(rolesArray));
|
||||
} else {
|
||||
localStorage.setItem("play-werewolf-custom-roles", JSON.stringify(new Array(newCard)));
|
||||
}
|
||||
updateCustomRoleModal();
|
||||
closeModal();
|
||||
document.getElementById("custom-role-form").reset();
|
||||
} else {
|
||||
alert("A custom or standard card already exists with that name!")
|
||||
}
|
||||
updateCustomRoleModal();
|
||||
closeModal();
|
||||
document.getElementById("custom-role-form").reset();
|
||||
}
|
||||
|
||||
function updateCustomRoleModal() {
|
||||
document.getElementById("custom-roles").innerHTML = "";
|
||||
cards.forEach((card) => {
|
||||
if (card.custom) {
|
||||
renderCustomRoleInModal(card);
|
||||
for (let i = 0; i < cards.length; i++){
|
||||
if (cards[i].custom) {
|
||||
renderCustomRoleInModal(cards[i], i);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function readInUserCustomRoles() {
|
||||
let existingRoles = localStorage.getItem("play-werewolf-custom-roles");
|
||||
if (existingRoles !== null) {
|
||||
let rolesArray;
|
||||
try {
|
||||
rolesArray = JSON.parse(existingRoles);
|
||||
} catch(e) {
|
||||
console.error(e.message);
|
||||
let expectedKeys = ["role", "description", "team", "isTypeOfWerewolf", "custom", "saved"];
|
||||
let userCustomRoles = utility.validateCustomRolesJsonObject("play-werewolf-custom-roles", expectedKeys);
|
||||
if (userCustomRoles) {
|
||||
for (let i = 0; i < userCustomRoles.length; i++) {
|
||||
cards.push(userCustomRoles[i]);
|
||||
}
|
||||
if (rolesArray) {
|
||||
rolesArray.forEach((card) => {
|
||||
renderCustomRoleInModal(card);
|
||||
cards.push(card);
|
||||
})
|
||||
}
|
||||
}
|
||||
if (document.getElementById("custom-roles").getElementsByClassName("custom-role-edit").length === 0) {
|
||||
document.getElementById("custom-roles").innerHTML = "<h2>You haven't added any custom roles.</h2>";
|
||||
}
|
||||
}
|
||||
|
||||
function renderCustomRoleInModal(card) {
|
||||
function renderCustomRoleInModal(card, index) {
|
||||
let roleElement = document.createElement("div");
|
||||
let editRemoveContainer = document.createElement("div");
|
||||
let roleLabel = document.createElement("div");
|
||||
let roleName = document.createElement("p");
|
||||
let remove = document.createElement("img");
|
||||
let edit = document.createElement("img");
|
||||
let editForm = buildRoleEditForm(index);
|
||||
|
||||
// TODO: add edit functionality
|
||||
roleName.innerText = card.role;
|
||||
remove.setAttribute("src", "../assets/images/delete.svg");
|
||||
remove.setAttribute("title", "Delete");
|
||||
remove.addEventListener("click", function() { removeCustomRole(card.role) });
|
||||
|
||||
edit.setAttribute("src", "../assets/images/pencil_green.svg");
|
||||
edit.setAttribute("title", "Edit");
|
||||
edit.addEventListener("click", function(e) { toggleEditForm(e, index) });
|
||||
roleElement.setAttribute("class", "custom-role-edit");
|
||||
|
||||
editRemoveContainer.appendChild(remove);
|
||||
roleElement.appendChild(roleName);
|
||||
roleElement.appendChild(editRemoveContainer);
|
||||
editRemoveContainer.appendChild(edit);
|
||||
roleLabel.appendChild(roleName);
|
||||
roleLabel.appendChild(editRemoveContainer);
|
||||
roleElement.appendChild(roleLabel);
|
||||
roleElement.appendChild(editForm);
|
||||
|
||||
document.getElementById("custom-roles").appendChild(roleElement);
|
||||
|
||||
document.getElementById("edit-form-" + index).addEventListener("submit", function(e) {
|
||||
updateCustomRole(e, index);
|
||||
});
|
||||
}
|
||||
|
||||
function toggleEditForm(event, index) {
|
||||
event.preventDefault();
|
||||
let displayRule = document.getElementById("edit-form-" + index).style.display;
|
||||
document.getElementById("edit-form-" + index).style.display = displayRule === "none" ? "block" : "none";
|
||||
|
||||
if (document.getElementById("edit-form-" + index).style.display === "block") {
|
||||
populateEditRoleForm(cards[index], index);
|
||||
}
|
||||
}
|
||||
|
||||
function buildRoleEditForm(index) {
|
||||
let infoForm = document.createElement("div");
|
||||
infoForm.style.display = "none";
|
||||
infoForm.setAttribute("id", "edit-form-" + index);
|
||||
infoForm.innerHTML =
|
||||
"<form class=\"edit-role-form\" id=\"edit-role-form-" + index + "\">" +
|
||||
"<label for=\"edit-role-desc-" + index + "\">Description</label>" +
|
||||
"<textarea rows=\"3\" id=\"edit-role-desc-" + index + "\" required></textarea>" +
|
||||
"<label for=\"edit-role-team-" + index + "\">Team</label>" +
|
||||
"<select id=\"edit-role-team-" + index + "\">" +
|
||||
"<option value=\"good\">Good</option>" +
|
||||
"<option value=\"evil\">Evil</option>" +
|
||||
"</select>" +
|
||||
"<div class=\"checkbox\">" +
|
||||
"<input type=\"checkbox\" id=\"edit-role-wolf-" + index + "\">" +
|
||||
"<label for=\"edit-role-wolf-" + index + "\">Werewolf role (counts for parity)</label>" +
|
||||
"</div>" +
|
||||
"<div class=\"checkbox\">" +
|
||||
"<input type=\"checkbox\" id=\"edit-role-remember-" + index + "\">" +
|
||||
"<label for=\"edit-role-remember-" + index + "\">Remember this role for later (uses cookies)</label>" +
|
||||
"</div>" +
|
||||
"<br><br>" +
|
||||
"<input type=\"submit\" class=\"app-btn\" value=\"Update\">" +
|
||||
"</form>";
|
||||
return infoForm;
|
||||
}
|
||||
|
||||
function populateEditRoleForm(card, index) {
|
||||
document.getElementById("edit-role-desc-" + index).value = card.description;
|
||||
document.getElementById("edit-role-team-" + index).value = card.team;
|
||||
document.getElementById("edit-role-wolf-" + index).checked = card.isTypeOfWerewolf;
|
||||
document.getElementById("edit-role-remember-" + index).checked = card.saved;
|
||||
}
|
||||
|
||||
function removeCustomRole(name) {
|
||||
let matchingCards = cards.filter((card) => card.role === name);
|
||||
matchingCards.forEach((card) => {
|
||||
cards.splice(cards.indexOf(card), 1);
|
||||
});
|
||||
let existingRoles = localStorage.getItem("play-werewolf-custom-roles");
|
||||
if (existingRoles !== null) {
|
||||
let rolesArray;
|
||||
try {
|
||||
rolesArray = JSON.parse(existingRoles);
|
||||
} catch (e) {
|
||||
console.error(e.message);
|
||||
if (confirm("Delete this role?")) {
|
||||
let matchingCards = cards.filter((card) => card.role === name);
|
||||
matchingCards.forEach((card) => {
|
||||
cards.splice(cards.indexOf(card), 1);
|
||||
});
|
||||
let expectedKeys = ["role", "description", "team", "isTypeOfWerewolf", "custom", "saved"];
|
||||
let userCustomRoles = utility.validateCustomRolesJsonObject("play-werewolf-custom-roles", expectedKeys);
|
||||
if (userCustomRoles) {
|
||||
userCustomRoles = userCustomRoles.filter((card) => card.role !== name);
|
||||
localStorage.setItem("play-werewolf-custom-roles", JSON.stringify(userCustomRoles));
|
||||
}
|
||||
updateCustomRoleModal();
|
||||
renderAvailableCards();
|
||||
}
|
||||
}
|
||||
|
||||
function updateCustomRole(event, index) {
|
||||
event.preventDefault();
|
||||
if (index >= 0 && index < cards.length) {
|
||||
let cardToUpdate = cards[index];
|
||||
cardToUpdate.team = document.getElementById("edit-role-team-" + index).value;
|
||||
cardToUpdate.description = document.getElementById("edit-role-desc-" + index).value;
|
||||
cardToUpdate.isTypeOfWerewolf = document.getElementById("edit-role-wolf-" + index).checked;
|
||||
cardToUpdate.saved = document.getElementById("edit-role-remember-" + index).checked;
|
||||
|
||||
removeOrAddSavedRoleIfNeeded(cardToUpdate);
|
||||
toggleEditForm(event, index);
|
||||
renderAvailableCards();
|
||||
}
|
||||
}
|
||||
|
||||
function removeOrAddSavedRoleIfNeeded(card) {
|
||||
let expectedKeys = ["role", "description", "team", "isTypeOfWerewolf", "custom", "saved"];
|
||||
let userCustomRoles = utility.validateCustomRolesJsonObject("play-werewolf-custom-roles", expectedKeys);
|
||||
if (userCustomRoles) {
|
||||
if (card.saved) {
|
||||
let roleToUpdate = userCustomRoles.find((savedCard) => savedCard.role === card.role);
|
||||
if (roleToUpdate) {
|
||||
userCustomRoles[userCustomRoles.indexOf(roleToUpdate)] = card;
|
||||
} else {
|
||||
userCustomRoles.push(card);
|
||||
}
|
||||
localStorage.setItem("play-werewolf-custom-roles", JSON.stringify(userCustomRoles));
|
||||
} else {
|
||||
let roleToRemove = userCustomRoles.find((savedCard) => savedCard.role === card.role);
|
||||
if (roleToRemove) {
|
||||
userCustomRoles.splice(userCustomRoles.indexOf(roleToRemove), 1);
|
||||
localStorage.setItem("play-werewolf-custom-roles", JSON.stringify(userCustomRoles));
|
||||
}
|
||||
}
|
||||
if (rolesArray) {
|
||||
rolesArray = rolesArray.filter((card) => card.role !== name);
|
||||
}
|
||||
localStorage.setItem("play-werewolf-custom-roles", JSON.stringify(rolesArray));
|
||||
}
|
||||
updateCustomRoleModal();
|
||||
renderAvailableCards();
|
||||
}
|
||||
|
||||
|
||||
@@ -305,9 +324,8 @@ function buildDeckFromQuantities() {
|
||||
let playerDeck = [];
|
||||
for (const card of fullDeck) {
|
||||
for (let i = 0; i < card.quantity; i++) {
|
||||
let newCard = new Card(card.role, card.team, card.description, card.isTypeOfWerewolf);
|
||||
newCard.id = utility.generateID();
|
||||
playerDeck.push(newCard);
|
||||
card.id = utility.generateID();
|
||||
playerDeck.push(card);
|
||||
}
|
||||
}
|
||||
return playerDeck;
|
||||
|
||||
@@ -446,12 +446,13 @@ button {
|
||||
}
|
||||
|
||||
#custom-roles img {
|
||||
width: 20px;
|
||||
width: 25px;
|
||||
}
|
||||
|
||||
#custom-roles .custom-role-edit {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
font-size: 19px;
|
||||
align-items: center;
|
||||
@@ -460,6 +461,27 @@ button {
|
||||
margin: 0.3em;
|
||||
}
|
||||
|
||||
.edit-role-form {
|
||||
background-color: #1a1a1a;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.custom-role-edit > div:nth-child(1) {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.custom-role-edit > div:nth-child(1) div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.custom-role-edit > div:nth-child(2) {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.custom-role-edit p {
|
||||
text-overflow: ellipsis;
|
||||
overflow-x: hidden;
|
||||
@@ -470,6 +492,7 @@ button {
|
||||
#custom-roles .custom-role-edit div > img {
|
||||
margin: 0 1em;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#custom-roles .custom-role-edit div > img:hover {
|
||||
@@ -977,7 +1000,7 @@ label {
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#lobby-subheader {
|
||||
@@ -1193,7 +1216,7 @@ label {
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
justify-content: space-between;
|
||||
box-shadow: 3px 10px 10px rgba(0,0,0,0.6);
|
||||
margin: 0.3em;
|
||||
position: relative;
|
||||
|
||||
@@ -19,5 +19,32 @@ export const utility =
|
||||
[array[i], array[j]] = [array[j], array[i]];
|
||||
}
|
||||
return array;
|
||||
}
|
||||
},
|
||||
|
||||
validateCustomRolesJsonObject(name, expectedKeys) {
|
||||
let value = localStorage.getItem(name);
|
||||
if (value !== null) {
|
||||
let valueJson;
|
||||
try {
|
||||
valueJson = JSON.parse(value);
|
||||
} catch(e) {
|
||||
console.error(e.message);
|
||||
localStorage.removeItem(name);
|
||||
return false;
|
||||
}
|
||||
if (valueJson && Array.isArray(valueJson)) { // some defensive programming - check if it's an array, and that the object has the expected structure
|
||||
for (let i = 0; i < valueJson.length; i++){
|
||||
if (expectedKeys.some((key) => !Object.keys(valueJson[i]).includes(key))) {
|
||||
console.error("tried to read invalid object: " + valueJson[i] + " with expected keys: " + expectedKeys);
|
||||
valueJson.splice(i, 1);
|
||||
localStorage.setItem(name, JSON.stringify(valueJson));
|
||||
}
|
||||
}
|
||||
return valueJson;
|
||||
} else { // object has been messed with. remove it.
|
||||
localStorage.removeItem(name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
wolves as villagers, the wolves win (as they can kill a villager at night, and then have the majority to kill the
|
||||
remaining villager during the day). If the village manages to kill every wolf, then they win. In the scenario
|
||||
where there is one villager and one wolf remaining, if the remaining villager is a Hunter, then the village wins.
|
||||
There are several "power roles" such as the Hunter, which can help the village or the wolves. If you are a power
|
||||
There are several "power cards" such as the Hunter, which can help the village or the wolves. If you are a power
|
||||
role, you can read the description on your card to find out what your special ability is.
|
||||
</p>
|
||||
<a href="/"><button class="app-btn">Back</button></a>
|
||||
|
||||
Reference in New Issue
Block a user