From 96381e0153308372606594240f2c1a55fab1ec17 Mon Sep 17 00:00:00 2001 From: onsetsu Date: Sun, 12 Jan 2025 16:05:13 +0100 Subject: [PATCH] enabled multitype cards SQUASHED: AUTO-COMMIT-demos-stefan-untitled-board-game-ubg-card.js,AUTO-COMMIT-src-components-widgets-ubg-card.js,AUTO-COMMIT-src-components-widgets-ubg-cards-editor.html,AUTO-COMMIT-src-components-widgets-ubg-cards-editor.js,AUTO-COMMIT-src-components-widgets-ubg-cards-entry.js,AUTO-COMMIT-src-components-widgets-ubg-cards.js, --- demos/stefan/untitled-board-game/ubg-card.js | 57 +++++++++++++++-- src/components/widgets/ubg-card.js | 56 ++++++++--------- src/components/widgets/ubg-cards-editor.html | 6 +- src/components/widgets/ubg-cards-editor.js | 24 ++++---- src/components/widgets/ubg-cards-entry.js | 34 ++++++++--- src/components/widgets/ubg-cards.js | 64 ++++++++++---------- 6 files changed, 151 insertions(+), 90 deletions(-) diff --git a/demos/stefan/untitled-board-game/ubg-card.js b/demos/stefan/untitled-board-game/ubg-card.js index 982ff15ef..ddedd001b 100644 --- a/demos/stefan/untitled-board-game/ubg-card.js +++ b/demos/stefan/untitled-board-game/ubg-card.js @@ -39,13 +39,60 @@ export default class Card { } } - getType() { - return this.versions.last.type; - } +// getType() { +// return this.versions.last.type; +// } + +// setType(type) { +// this.ensureUnprintedVersion(); +// this.versions.last.type = type; +// } - setType(type) { + getTypes() { + const type = this.versions.last.type; + + if (!type) { + return [] + } + + if (Array.isArray(type)) { + return type + } + + if (typeof type === 'string') { + return [type] + } + + throw new Error('unknown type for card type: ' + type) + } + + setTypes(types) { this.ensureUnprintedVersion(); - this.versions.last.type = type; + + if (!types) { + delete this.versions.last.type; + return; + } + + if (!Array.isArray(types)) { + throw new Error('"types" is not an Array, but: ' + typeof types) + } + + if (types.length === 0) { + delete this.versions.last.type; + } + + if (types.length === 1) { + this.versions.last.type = types.first; + } + + if (types.length >= 2) { + this.versions.last.type = types; + } + } + + hasType(t) { + return this.getTypes().some(type => type.toLowerCase() === t) } getElement() { diff --git a/src/components/widgets/ubg-card.js b/src/components/widgets/ubg-card.js index d477262f4..fdc0150f9 100644 --- a/src/components/widgets/ubg-card.js +++ b/src/components/widgets/ubg-card.js @@ -98,7 +98,7 @@ export default class UbgCard extends Morph { const currentVersion = card.versions.last; - if (card.getType() === 'character') { + if (card.hasType('character')) { return ['#efc241', '#b8942d', BOX_FILL_OPACITY]; } @@ -213,13 +213,19 @@ background: ${color}; } } - const typeString = cardDesc.getType() && cardDesc.getType().toLowerCase && cardDesc.getType().toLowerCase() - const defaultFiles = { - gadget: 'default-gadget.jpg', - character: 'default-character.jpg', - spell: 'default-spell.jpg' - }; - return this.assetsFolder + (defaultFiles[typeString] || 'default.jpg'); + return this.filePathForBackgroundImageForCardTypes(cardDesc) + } + + filePathForBackgroundImageForCardTypes(cardDesc) { + if (cardDesc.hasType('gadget')) { + return this.assetsFolder + 'default-gadget.jpg'; + } else if (cardDesc.hasType('character')) { + return this.assetsFolder + 'default-character.jpg'; + } else if (cardDesc.hasType('spell')) { + return this.assetsFolder + 'default-spell.jpg'; + } + + return this.assetsFolder + 'default.jpg'; } async setBackgroundImage(cardDesc, assetsInfo) { @@ -340,14 +346,11 @@ font-family: "${CSS_FONT_FAMILY_CARD_NAME}"; } async renderFullBleedStyle(cardDesc, outsideBorder, assetsInfo) { - const type = cardDesc.getType(); - const typeString = type && type.toLowerCase && type.toLowerCase() || ''; - - if (typeString === 'spell') { + if (cardDesc.hasType('spell')) { await this.renderSpell(cardDesc, outsideBorder, assetsInfo) - } else if (typeString === 'gadget') { + } else if (cardDesc.hasType('gadget')) { await this.renderGadget(cardDesc, outsideBorder, assetsInfo) - } else if (typeString === 'character') { + } else if (cardDesc.hasType('character')) { await this.renderCharacter(cardDesc, outsideBorder, assetsInfo) } else { await this.renderMagicStyle(cardDesc, outsideBorder, assetsInfo) @@ -618,7 +621,7 @@ font-family: "${CSS_FONT_FAMILY_CARD_NAME}"; // cost this.renderCost(cardDesc, currentCenter, costCoinRadius) - if ((cardDesc.getType() || '').toLowerCase() !== 'character') { + if (!cardDesc.hasType('character')) { // vp currentCenter = currentCenter.addY(costCoinRadius * 2.75); this.renderBaseVP(cardDesc, currentCenter, costCoinRadius) @@ -791,23 +794,10 @@ backdrop-filter: blur(4px); } renderType(cardDesc, anchorPt, color, opacity) { - // function curate() { - // return this.toLower().upperFirst(); - // } - // function prepend(other) { - // return other + ' ' + this; - // } - // const element = cardDesc.getElement(); - let fullText = (cardDesc.getType() || '').toLower().upperFirst() - // if (Array.isArray(element)) { - // element.forEach(element => { - // fullText = fullText::prepend(element::curate()) - // }) - // } else if (element) { - // fullText = fullText::prepend(element::curate()) - // } + const types = cardDesc.getTypes(); + const fullText = types.length === 0 ? '<no type>' : types.map(type => type.toLower().upperFirst()).join('
'); - this.content.append({fullText}); + `}>; + typesNode.innerHTML = fullText; + this.content.append(typesNode); } renderQRCode(cardDesc, qrAnchor, outsideBorder) { diff --git a/src/components/widgets/ubg-cards-editor.html b/src/components/widgets/ubg-cards-editor.html index cc6c917b5..9b64bd669 100644 --- a/src/components/widgets/ubg-cards-editor.html +++ b/src/components/widgets/ubg-cards-editor.html @@ -135,7 +135,7 @@ "id-key id-value id-value id-value preview" "name-key name-value name-value name-value preview" "identity-key identity-value identity-value identity-value preview" - "type-key type-value type-value type-value preview" + "types-key types-value types-value types-value preview" "element-key element-value element-value element-value preview" "cost-key cost-value cost-modifier-key cost-modifier-value preview" "vp-key vp-value vp-value vp-value preview" @@ -231,8 +231,8 @@ identity - type - + types + element cost diff --git a/src/components/widgets/ubg-cards-editor.js b/src/components/widgets/ubg-cards-editor.js index 4e2ec9163..5038a99ce 100644 --- a/src/components/widgets/ubg-cards-editor.js +++ b/src/components/widgets/ubg-cards-editor.js @@ -19,7 +19,7 @@ export default class UBGCardsEditor extends Morph { this.$id.addEventListener(eventName, evt => this.modify$id(evt, eventName), false); this.$name.addEventListener(eventName, evt => this.modify$name(evt), false); this.$identity.addEventListener(eventName, evt => this.modify$identity(evt), false); - this.$type.addEventListener(eventName, evt => this.modify$type(evt), false); + this.$types.addEventListener(eventName, evt => this.modify$types(evt), false); this.$element.addEventListener(eventName, evt => this.modify$element(evt), false); this.$cost.addEventListener(eventName, evt => this.modify$cost(evt), false); this.$costModifier.addEventListener(eventName, evt => this.modify$costModifier(evt), false); @@ -107,8 +107,8 @@ export default class UBGCardsEditor extends Morph { get $identity() { return this.get('#identity'); } - get $type() { - return this.get('#type'); + get $types() { + return this.get('#types'); } get $element() { return this.get('#element'); @@ -197,19 +197,21 @@ export default class UBGCardsEditor extends Morph { this.$identity.value = identity === undefined ? '' : identity; } - modify$type(evt) { - const type = this.$type.value; + modify$types(evt) { + const type = this.$types.value; + if (type === '') { - this.card.setType(); + this.card.setTypes(); } else { - this.card.setType(type); + const types = type.split(',').map(t => t.trim()).filter(t => t); + this.card.setTypes(types); } this.propagateChange() } - display$type() { - const type = this.card.getType(); - this.$type.value = type === undefined ? '' : type; + display$types() { + const types = this.card.getTypes(); + this.$types.value = types.join(', '); } modify$element(evt) { @@ -530,7 +532,7 @@ export default class UBGCardsEditor extends Morph { this.display$id(); this.display$name(); this.display$identity(); - this.display$type(); + this.display$types(); this.display$element(); this.display$cost(); this.display$costModifier(); diff --git a/src/components/widgets/ubg-cards-entry.js b/src/components/widgets/ubg-cards-entry.js index 994b01f80..ff67e026f 100644 --- a/src/components/widgets/ubg-cards-entry.js +++ b/src/components/widgets/ubg-cards-entry.js @@ -80,14 +80,7 @@ export default class UBGCardEntry extends Morph { id.innerHTML = card.id || '???'; - const type = v.type && v.type.toLowerCase(); - this.get('#type').className = { - spell: 'fa fa-magic', - gadget: 'fa fa-gear', - character: 'fa fa-user', - trap: 'fa fa-bug' - }[type && type.toLowerCase()] || 'fa fa-question'; - + this.renderType(card) this.renderElement(v); this.get('#cost').innerHTML = ((v.cost === undefined ? '' : v.cost) + (v.costModifier || '')) || '/'; @@ -119,6 +112,31 @@ export default class UBGCardEntry extends Morph { this.classList.toggle('hidden', !matching); } + renderType(c) { + const types = c.getTypes(); + + let iconClass; + if (types.length === 0) { + iconClass = 'fa fa-question' + } + + if (types.length >= 1) { + const typeLower = types.first.toLowerCase(); + iconClass = { + spell: 'fa fa-magic', + gadget: 'fa fa-gear', + character: 'fa fa-user', + trap: 'fa fa-bug' + }[typeLower && typeLower.toLowerCase()] || 'fa fa-question'; + } + + if (types.length >= 2) { + iconClass = 'fa fa-bars' + } + + this.get('#type').className = iconClass + } + renderElement(v) { const element = v.element; diff --git a/src/components/widgets/ubg-cards.js b/src/components/widgets/ubg-cards.js index 5307eb735..33656fea1 100644 --- a/src/components/widgets/ubg-cards.js +++ b/src/components/widgets/ubg-cards.js @@ -1111,33 +1111,6 @@ export default class Cards extends Morph { getCharacterColors() { } - colorsForCard(card) { - const BOX_FILL_OPACITY = 0.7; - - const currentVersion = card.versions.last; - - if (card.getType() === 'character') { - return ['#efc241', '#b8942d', BOX_FILL_OPACITY]; - } - - const multiElement = Array.isArray(card.getElement()); - if (multiElement) { - return ['#ff88ff', '#ff00ff', BOX_FILL_OPACITY]; - } - - const singleElementColors = { - fire: ['#ffaaaa', '#dd0000', BOX_FILL_OPACITY], - water: ['#aaaaff', '#0000ff', BOX_FILL_OPACITY], - earth: ['#eeee88', '#cccc00', BOX_FILL_OPACITY], - wind: ['#88ff88', '#00bb00', BOX_FILL_OPACITY] - }[currentVersion.element && currentVersion.element.toLowerCase && currentVersion.element.toLowerCase()]; - if (singleElementColors) { - return singleElementColors; - } - - return ['#ffffff', '#888888', BOX_FILL_OPACITY]; - } - /*MD ## Extract Card Info MD*/ getNameFromCard(cardDesc) { const currentVersion = cardDesc.versions.last; @@ -1266,7 +1239,7 @@ export default class Cards extends Morph { if (that && that.localName === 'lively-code-mirror' && document.contains(that)) { lively.showElement(that) - const matches = that.value.matchAll(/^([^0-9]+)?\s([0-9]+)?\s?([a-zA-Z ]+)?\s?(?:\(([0-9,]+)\))?(?:\s?([0-9*+-]+))?\.\s(.*)?$/gmi); + const matches = that.value.matchAll(/^([^0-9]+)?\s([0-9]+)?\s?([a-zA-Z ]+)?\s?(?:\(([0-9,]+)(\+?\-?\*?)\))?(?:\s?([0-9*+-]+))?\.\s(.*)?$/gmi); const newCards = [...matches].map(match => { const card = new Card(); @@ -1280,17 +1253,41 @@ export default class Cards extends Morph { } card.setName(match[1]) - card.setText(match[6]) + card.setText(match[7]) const typesAndElements = match[3]; if (typesAndElements) { let type = '' let element; - const typeElement = match[3].split(' ').forEach(te => { + match[3].split(' ').forEach(te => { if (!te) { return; } + // Transmutation & Transformation + // Flux, Shift, Metamorph + + // Knowledge Structures & Doctrines + // Codex, Canon, Tenet + + // Tools & Apparatus + // Device, Machina, Engine + + // Symbolic Systems & Signs + // Sigil, Rune, Glyph + + // Substances & Essences & Reagents + // Elixir, Essence + + // Mediating Entities (Familiars & Spirits) + // Familiar, Eidolon + + // Philosophical & Spiritual Worldviews + // Creed, Dogma, Doctrine + + // Hierarchies & Secret Orders + // Order, Guild, Circle + if (['gadget', 'character', 'spell'].includes(te.toLowerCase())) { type += te return @@ -1324,7 +1321,12 @@ export default class Cards extends Morph { } } - const baseVP = match[5]; + const costModifier = match[5]; + if (costModifier) { + card.setCostModifier(costModifier); + } + + const baseVP = match[6]; const intBaseVP = parseInt(baseVP); if (!_.isNaN(intBaseVP)) { card.setBaseVP(intBaseVP)