Allow saving decks with custom cards

This commit is contained in:
Andrio Celos
2024-02-06 13:51:45 +11:00
parent 935d3de744
commit 686db54fa0
9 changed files with 61 additions and 25 deletions

View File

@@ -63,7 +63,8 @@ class Card {
return card;
}
get isUpcoming() { return this.number < 0; }
get isCustom() { return this.number <= CUSTOM_CARD_START; }
get isUpcoming() { return this.number < 0 && !this.isCustom; }
get isSpecialWeapon() { return this.specialCost == 3 && this.size == 12 };
getSpace(x: number, y: number, rotation: number) {

View File

@@ -11,8 +11,8 @@ class CardButton extends CheckButton implements ICardElement {
button.type = 'button';
button.classList.add('cardButton');
button.classList.add([ 'common', 'rare', 'fresh' ][card.rarity]);
if (card.number <= CUSTOM_CARD_START) button.classList.add('custom');
else if (card.number < 0) button.classList.add('upcoming');
if (card.isCustom) button.classList.add('custom');
else if (card.isUpcoming) button.classList.add('upcoming');
button.dataset.cardNumber = card.number.toString();
super(button);
this.element = button;
@@ -37,7 +37,7 @@ class CardButton extends CheckButton implements ICardElement {
let el2 = document.createElement('div');
el2.classList.add('cardNumber');
el2.innerText = card.number >= 0 ? `No. ${card.number}` : card.number <= CUSTOM_CARD_START ? 'Custom' : 'Upcoming';
el2.innerText = card.number >= 0 ? `No. ${card.number}` : card.isCustom ? 'Custom' : 'Upcoming';
row.appendChild(el2);
el2 = document.createElement('div');

View File

@@ -1,6 +1,14 @@
const cardDatabase = {
/** The list of official cards, or null if the database has not yet been loaded. */
cards: null as Card[] | null,
/** The list of custom cards added by the user. */
customCards: [ ] as Card[],
/** The list of custom cards used in the current game that were not added by the user. */
receivedCustomCards: [ ] as Card[],
customCardsModified: false,
/** The number of official cards, and the highest card number among official cards. */
lastOfficialCardNumber: 0,
_byAltNumber: [ ] as Card[],
// Upcoming cards are identified with a negative number, as their actual numbers aren't known until their release.
@@ -10,8 +18,11 @@ const cardDatabase = {
if (number > 0) {
number--;
if (number < cardDatabase.lastOfficialCardNumber) return cardDatabase.cards[number];
} else if (number <= RECEIVED_CUSTOM_CARD_START) {
const card = cardDatabase.receivedCustomCards[RECEIVED_CUSTOM_CARD_START - number];
if (card) return card;
} else if (number <= CUSTOM_CARD_START) {
const card = customCards[CUSTOM_CARD_START - number];
const card = cardDatabase.customCards[CUSTOM_CARD_START - number];
if (card) return card;
} else if (number < 0) {
const card = cardDatabase._byAltNumber[-number];
@@ -19,9 +30,15 @@ const cardDatabase = {
}
throw new RangeError(`No card with number ${number}`);
},
isValidCardNumber(number: number) {
isValidOfficialCardNumber(number: number) {
return number > 0 ? number <= cardDatabase.lastOfficialCardNumber : cardDatabase._byAltNumber[-number] != undefined;
},
isValidCardNumber(number: number) {
return number > 0 ? number <= cardDatabase.lastOfficialCardNumber
: number <= RECEIVED_CUSTOM_CARD_START ? RECEIVED_CUSTOM_CARD_START - number < cardDatabase.receivedCustomCards.length
: number <= CUSTOM_CARD_START ? CUSTOM_CARD_START - number < cardDatabase.customCards.length
: cardDatabase._byAltNumber[-number] != undefined;
},
loadAsync() {
return new Promise<Card[]>((resolve, reject) => {
if (cardDatabase.cards != null) {

View File

@@ -21,8 +21,8 @@ class CardDisplay implements ICardElement {
this.svg = svg;
element.appendChild(svg);
if (card.number <= CUSTOM_CARD_START) svg.classList.add('custom');
else if (card.number < 0) svg.classList.add('upcoming');
if (card.isCustom) svg.classList.add('custom');
else if (card.isUpcoming) svg.classList.add('upcoming');
svg.dataset.cardNumber = card.number.toString();
svg.style.setProperty("--number", card.number.toString());

View File

@@ -90,7 +90,7 @@ class CardList<T extends ICardElement> {
removeAllCustomCards() {
for (let i = this.cardButtons.length - 1; i >= 0; i--) {
const button = this.cardButtons[i];
if (button.card.number <= CUSTOM_CARD_START) {
if (button.card.isCustom) {
this.listElement.removeChild(button.element);
this.cardButtons.splice(i, 1);
}

View File

@@ -58,5 +58,5 @@ function saveChecklist() {
}
function saveCustomCards() {
localStorage.setItem('customCards', JSON.stringify(customCards));
localStorage.setItem('customCards', JSON.stringify(cardDatabase.customCards));
}

View File

@@ -124,10 +124,10 @@ function editDeck() {
}
function reloadCustomCards() {
if (!customCardsModified) return;
if (!cardDatabase.customCardsModified) return;
cardList.removeAllCustomCards();
testAllCardsList.removeAllCustomCards();
for (const card of customCards) {
for (const card of cardDatabase.customCards) {
addCardToDeckEditor(card);
addTestCard(card);
}

View File

@@ -31,7 +31,7 @@ function showCardList() {
}
function galleryInitCardDatabase(cards: Card[]) {
for (const card of cards.concat(customCards)) {
for (const card of cards.concat(cardDatabase.customCards)) {
addCardToGallery(card);
}
updateBitsToComplete();
@@ -47,7 +47,7 @@ function createGalleryCardDisplay(card: Card) {
const cardNumber = document.createElement('div');
cardNumber.className = 'cardNumber';
cardNumber.innerText = card.number >= 0 ? `No. ${card.number}` : card.number <= CUSTOM_CARD_START ? 'Custom' : 'Upcoming';
cardNumber.innerText = card.number >= 0 ? `No. ${card.number}` : card.isCustom ? 'Custom' : 'Upcoming';
display.element.insertBefore(cardNumber, display.element.firstChild);
display.element.addEventListener('click', () => {
@@ -88,8 +88,8 @@ function openGalleryCardView(card: Card) {
display.element.appendChild(galleryCardEditor);
galleryCardEditor.hidden = true;
display.element.classList.remove('editing');
galleryCardEditorEditButton.hidden = card.number > CUSTOM_CARD_START;
galleryCardEditorDeleteButton.hidden = card.number > CUSTOM_CARD_START;
galleryCardEditorEditButton.hidden = !card.isCustom;
galleryCardEditorDeleteButton.hidden = !card.isCustom;
galleryCardEditorSubmitButton.hidden = true;
galleryCardEditorCancelButton.innerText = 'Close';
@@ -214,9 +214,9 @@ function updateBitsToComplete() {
const customCardsString = localStorage.getItem('customCards');
if (customCardsString) {
for (const cardJson of JSON.parse(customCardsString)) {
customCards.push(Card.fromJson(cardJson));
cardDatabase.customCards.push(Card.fromJson(cardJson));
}
customCardsModified = customCards.length > 0;
cardDatabase.customCardsModified = cardDatabase.customCards.length > 0;
}
}
@@ -296,13 +296,13 @@ galleryCardEditorSubmitButton.addEventListener('click', () => {
card.size = customCardSize;
card.specialCost = customCardSpecialCost;
if (card.number == UNSAVED_CUSTOM_CARD_INDEX) {
card.number = CUSTOM_CARD_START - customCards.length;
customCards.push(card);
card.number = CUSTOM_CARD_START - cardDatabase.customCards.length;
cardDatabase.customCards.push(card);
addCardToGallery(card);
} else {
updateCardInGallery(card);
}
customCardsModified = true;
cardDatabase.customCardsModified = true;
saveCustomCards();
});
@@ -316,6 +316,25 @@ galleryCardEditorDeleteYesButton.addEventListener('click', () => {
const card = galleryCardDisplay!.card;
galleryCardList.remove(card);
galleryCardDialog.close();
customCards.splice(customCards.indexOf(card), 1);
let i = cardDatabase.customCards.indexOf(card);
if (i < 0) return;
// Remove the card from decks and update other custom card numbers.
for (const deck of decks) {
for (let i = 0; i < deck.cards.length; i++) {
if (deck.cards[i] == card.number)
deck.cards[i] = 0;
else if (deck.cards[i] < card.number)
deck.cards[i]++;
}
}
// Update the custom cards list.
cardDatabase.customCards.splice(i, 1);
for (; i < cardDatabase.customCards.length; i++)
cardDatabase.customCards[i].number++;
saveCustomCards();
saveDecks();
});

View File

@@ -1,6 +1,7 @@
declare var baseUrl: string;
const CUSTOM_CARD_START = -1000; // TODO: Card numbers in replays shall be expanded to 2 bytes.
const CUSTOM_CARD_START = -10000; // TODO: Card numbers in replays shall be expanded to 2 bytes.
const RECEIVED_CUSTOM_CARD_START = -20000;
const UNSAVED_CUSTOM_CARD_INDEX = CUSTOM_CARD_START + 1;
const defaultColours = [
[ { r: 236, g: 249, b: 1 }, { r: 250, g: 158, b: 0 }, { r: 249, g: 249, b: 31 } ],
@@ -20,8 +21,6 @@ let initialiseCallback: (() => void) | null = null;
let canPushState = isSecureContext && location.protocol != 'file:';
const decks = [ new SavedDeck('Starter Deck', 0, [ 6, 34, 159, 13, 45, 137, 22, 52, 141, 28, 55, 103, 40, 56, 92 ], new Array(15).fill(1), true) ];
const customCards: Card[] = [ ];
let customCardsModified = false;
let selectedDeck: SavedDeck | null = null;
let editingDeck = false;
let deckModified = false;