mirror of
https://github.com/AndrioCelos/TableturfBattleApp.git
synced 2026-08-20 18:04:00 -05:00
Allow saving decks with custom cards
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -58,5 +58,5 @@ function saveChecklist() {
|
||||
}
|
||||
|
||||
function saveCustomCards() {
|
||||
localStorage.setItem('customCards', JSON.stringify(customCards));
|
||||
localStorage.setItem('customCards', JSON.stringify(cardDatabase.customCards));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user