diff --git a/lang/en.json b/lang/en.json index 20c66a32..817fc355 100755 --- a/lang/en.json +++ b/lang/en.json @@ -2442,7 +2442,6 @@ "single": "Miss", "plural": "Miss" }, - "missingX": "Missing {x}", "maxWithThing": "Max {thing}", "missingDragDropThing": "Drop {thing} here", "multiclass": "Multiclass", @@ -2533,9 +2532,6 @@ "recovery": { "label": "Recovery" }, "type": { "label": "Type" }, "value": { "label": "Value" } - }, - "identifier": { - "label": "Identifier" } }, "Ancestry": { @@ -2826,15 +2822,6 @@ "hideObserverPermissionInChat": { "label": "Hide Chat Info From Players", "hint": "Information such as hit/miss on attack rolls against adversaries will be hidden" - }, - "hidePartyStats": { - "label": "Hide Party Stats", - "hint": "Resources and stats in the party sheet's member list will be hidden to the following users, even if the user is part of the same party", - "choices": { - "never": "Never, always show", - "players": "Hide From Players", - "always": "Hide from Everyone" - } } } }, @@ -3223,6 +3210,7 @@ "subclassesAlreadyPresent": "You already have a class and multiclass subclass", "noDiceSystem": "Your selected dice {system} does not have a {faces} dice", "gmMenuRefresh": "You refreshed all actions and resources {types}", + "subclassAlreadyLinked": "{name} is already a subclass in the class {class}. Remove it from there if you want it to be a subclass to this class.", "gmRequired": "This action requires an online GM", "gmOnly": "This can only be accessed by the GM", "noActorOwnership": "You do not have permissions for this character", diff --git a/module/applications/characterCreation/characterCreation.mjs b/module/applications/characterCreation/characterCreation.mjs index 82ca9ccb..936bb79d 100644 --- a/module/applications/characterCreation/characterCreation.mjs +++ b/module/applications/characterCreation/characterCreation.mjs @@ -439,13 +439,10 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl 'system.domain': { key: 'system.domain', value: this.setup.class?.system.domains ?? null } }; - if (type === 'subclasses') { - const classItem = this.setup.class; - const uuid = classItem?._stats.compendiumSource ?? classItem?.uuid; + if (type === 'subclasses') presets.filter = { - 'system.linkedClass': { key: 'system.linkedClass', value: uuid } + 'system.linkedClass.uuid': { key: 'system.linkedClass.uuid', value: this.setup.class?.uuid } }; - } if (equipment.includes(type)) presets.filter = { @@ -613,8 +610,7 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl [foundry.utils.randomID()]: {} }; } else if (item.type === 'subclass' && event.target.closest('.subclass-card')) { - const classSubclasses = await this.setup.class.system.fetchSubclasses(); - if (classSubclasses.every(subclass => subclass.uuid !== item.uuid)) { + if (this.setup.class.system.subclasses.every(subclass => subclass.uuid !== item.uuid)) { ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.subclassNotInClass')); return; } diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index f40c144a..513ad3f3 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -209,9 +209,8 @@ export default class CharacterSheet extends DHBaseActorSheet { context.attributes = Object.keys(this.document.system.traits).reduce((acc, key) => { acc[key] = { ...this.document.system.traits[key], - label: _loc(CONFIG.DH.ACTOR.abilities[key].label), - verbs: CONFIG.DH.ACTOR.abilities[key].verbs.map(x => game.i18n.localize(x)), - isSpellcasting: this.document.system.spellcastModifierTrait?.key === key + name: game.i18n.localize(CONFIG.DH.ACTOR.abilities[key].name), + verbs: CONFIG.DH.ACTOR.abilities[key].verbs.map(x => game.i18n.localize(x)) }; return acc; @@ -228,7 +227,7 @@ export default class CharacterSheet extends DHBaseActorSheet { context.resources.stress.max < maxResource ? maxResource - context.resources.stress.max : 0; context.equippedItems = sortBy( - this.document.items.filter(i => i.system.equipped && (i.type === 'weapon' || i.usable)), + this.document.items.filter(i => i.system.equipped), i => (i.type === 'weapon' ? (i.system.secondary ? 1 : 0) : 2) ); diff --git a/module/applications/sheets/actors/party.mjs b/module/applications/sheets/actors/party.mjs index 403960c0..a7eeccdf 100644 --- a/module/applications/sheets/actors/party.mjs +++ b/module/applications/sheets/actors/party.mjs @@ -85,14 +85,6 @@ export default class Party extends DHBaseActorSheet { /* Prepare Context */ /* -------------------------------------------- */ - async _prepareContext(options) { - const context = await super._prepareContext(options); - const settings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Metagaming); - context.showStats = - settings.hidePartyStats === 'never' || (settings.hidePartyStats === 'players' && game.user.isGM); - return context; - } - async _preparePartContext(partId, context, options) { context = await super._preparePartContext(partId, context, options); switch (partId) { diff --git a/module/applications/sheets/items/class.mjs b/module/applications/sheets/items/class.mjs index 25c631fe..05bb0229 100644 --- a/module/applications/sheets/items/class.mjs +++ b/module/applications/sheets/items/class.mjs @@ -104,10 +104,9 @@ export default class ClassSheet extends DHBaseItemSheet { } /**@inheritdoc */ - async _prepareContext(options) { - const context = await super._prepareContext(options); + async _prepareContext(_options) { + const context = await super._prepareContext(_options); context.domains = this.document.system.domains; - context.subclasses = await this.document.system.fetchSubclasses(); return context; } @@ -129,8 +128,20 @@ export default class ClassSheet extends DHBaseItemSheet { const item = await fromUuid(data.uuid); const itemType = data.type === 'ActiveEffect' ? data.type : item.type; const target = event.target.closest('fieldset.drop-section'); - - if (['feature', 'ActiveEffect'].includes(itemType)) { + if (itemType === 'subclass') { + if (item.system.linkedClass) { + return ui.notifications.warn( + game.i18n.format('DAGGERHEART.UI.Notifications.subclassAlreadyLinked', { + name: item.name, + class: this.document.name + }) + ); + } + await item.update({ 'system.linkedClass': this.document.uuid }); + await this.document.update({ + 'system.subclasses': [...this.document.system.subclasses.map(x => x.uuid), item.uuid] + }); + } else if (['feature', 'ActiveEffect'].includes(itemType)) { super._onDrop(event); } else if (this.document.parent?.type !== 'character') { if (itemType === 'weapon') { @@ -189,6 +200,12 @@ export default class ClassSheet extends DHBaseItemSheet { static async #removeItemFromCollection(_event, element) { const { uuid, target } = element.dataset; const prop = foundry.utils.getProperty(this.document.system, target); + + if (target === 'subclasses') { + const subclass = await foundry.utils.fromUuid(uuid); + await subclass?.update({ 'system.linkedClass': null }); + } + await this.document.update({ [`system.${target}`]: prop.filter(i => i && i.uuid !== uuid).map(x => x.uuid) }); } diff --git a/module/applications/sheets/items/subclass.mjs b/module/applications/sheets/items/subclass.mjs index e9d8370e..5c731777 100644 --- a/module/applications/sheets/items/subclass.mjs +++ b/module/applications/sheets/items/subclass.mjs @@ -40,36 +40,4 @@ export default class SubclassSheet extends DHBaseItemSheet { get relatedDocs() { return this.document.system.features.map(x => x.item); } - - async _prepareContext(options) { - const context = await super._prepareContext(options); - if (this.document.system.linkedClass) { - const classData = await fromUuid(this.document.system.linkedClass); - context.class = classData ?? { - name: _loc('DAGGERHEART.GENERAL.missingX', { x: _loc('TYPES.Item.class') }), - missing: true - }; - } - return context; - } - - async _onDrop(event) { - event.stopPropagation(); - const data = TextEditor.getDragEventData(event); - const item = await fromUuid(data.uuid); - const itemType = data.type === 'ActiveEffect' ? data.type : item.type; - if (itemType === 'class') { - const uuid = item._stats.compendiumSource ?? item.uuid; - if (this.document.system.linkedClass !== uuid) { - await this.document.update({ 'system.linkedClass': uuid }); - // Re-render all class sheets for instant feedback - for (const app of foundry.applications.instances.values()) { - if (app.document?.type === 'class') app.render(); - } - } - return; - } - - return super._onDrop(event); - } } diff --git a/module/applications/ui/itemBrowser.mjs b/module/applications/ui/itemBrowser.mjs index 99b9a23d..67a16f6a 100644 --- a/module/applications/ui/itemBrowser.mjs +++ b/module/applications/ui/itemBrowser.mjs @@ -277,7 +277,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { (await foundry.applications.ux.TextEditor.implementation.enrichHTML(item.description)); } - this.fieldFilter = await this._createFieldFilter(); + this.fieldFilter = this._createFieldFilter(); if (this.presets?.filter) { Object.entries(this.presets.filter).forEach(([k, v]) => { @@ -355,12 +355,12 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { ); } - async _createFieldFilter() { + _createFieldFilter() { const filters = ItemBrowser.getFolderConfig(this.selectedMenu.data, 'filters'); - for (const f of filters) { + filters.forEach(f => { if (typeof f.field === 'string') f.field = foundry.utils.getProperty(game, f.field); else if (typeof f.choices === 'function') { - f.choices = await f.choices(this.items); + f.choices = f.choices(this.items); } // Clear field label so template uses our custom label parameter @@ -370,8 +370,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) { f.name ??= f.key; f.value = this.presets?.filter?.[f.name]?.value ?? null; - } - + }); return filters; } diff --git a/module/config/itemBrowserConfig.mjs b/module/config/itemBrowserConfig.mjs index 3e40c97b..04b387cb 100644 --- a/module/config/itemBrowserConfig.mjs +++ b/module/config/itemBrowserConfig.mjs @@ -383,8 +383,7 @@ export const typeConfig = { { key: 'system.linkedClass', label: 'TYPES.Item.class', - format: linkedClass => - foundry.utils.fromUuidSync(linkedClass)?.name ?? 'DAGGERHEART.UI.ItemBrowser.missing' + format: linkedClass => linkedClass?.name ?? 'DAGGERHEART.UI.ItemBrowser.missing' }, { key: 'system.spellcastingTrait', @@ -394,18 +393,15 @@ export const typeConfig = { ], filters: [ { - key: 'system.linkedClass', + key: 'system.linkedClass.uuid', label: 'TYPES.Item.class', - choices: async items => { - const list = []; - for (const item of items.filter(item => item.system.linkedClass)) { - const linkedClass = await foundry.utils.fromUuid(item.system.linkedClass); - list.push({ - value: linkedClass.uuid, - label: linkedClass.name - }); - } - + choices: items => { + const list = items + .filter(item => item.system.linkedClass) + .map(item => ({ + value: item.system.linkedClass.uuid, + label: item.system.linkedClass.name + })); return list.reduce((a, c) => { if (!a.find(i => i.value === c.value)) a.push(c); return a; diff --git a/module/data/item/base.mjs b/module/data/item/base.mjs index ba114fda..aebf33bf 100644 --- a/module/data/item/base.mjs +++ b/module/data/item/base.mjs @@ -200,7 +200,7 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel { const features = []; for (let f of this.features) { const fBase = f.item ?? f; - const feature = fBase.pack ? await foundry.utils.fromUuid(fBase.uuid) : fBase; + const feature = fBase.system ? fBase : await foundry.utils.fromUuid(fBase.uuid); features.push( foundry.utils.mergeObject( feature.toObject(), diff --git a/module/data/item/class.mjs b/module/data/item/class.mjs index 7014e011..d3738318 100644 --- a/module/data/item/class.mjs +++ b/module/data/item/class.mjs @@ -30,6 +30,7 @@ export default class DHClass extends BaseDataItem { }), evasion: new fields.NumberField({ initial: 0, integer: true, label: 'DAGGERHEART.GENERAL.evasion' }), features: new ItemLinkFields(), + subclasses: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false }), inventory: new fields.SchemaField({ take: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false }), choiceA: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false }), @@ -69,24 +70,6 @@ export default class DHClass extends BaseDataItem { return this.features.filter(x => x.type === CONFIG.DH.ITEM.featureSubTypes.class).map(x => x.item); } - async fetchSubclasses() { - const uuids = [this.parent.uuid, this.parent._stats?.compendiumSource].filter(u => !!u); - const subclasses = game.items.filter(x => x.type === 'subclass' && uuids.includes(x.system.linkedClass)); - for (const pack of game.packs) { - const indexes = await pack.getIndex({ fields: ['system.linkedClass'] }); - for (const index of indexes) { - if (index.type !== 'subclass') continue; - if (!uuids.includes(index.system?.linkedClass)) continue; - if (subclasses.find(x => x.uuid === index.uuid)) continue; - - const subclass = await foundry.utils.fromUuid(index.uuid); - subclasses.push(subclass); - } - } - - return subclasses; - } - async _preCreate(data, options, user) { if (this.actor?.type === 'character') { const levelupAuto = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).levelupAuto; diff --git a/module/data/item/subclass.mjs b/module/data/item/subclass.mjs index 12d85c1e..d421cc6d 100644 --- a/module/data/item/subclass.mjs +++ b/module/data/item/subclass.mjs @@ -28,7 +28,7 @@ export default class DHSubclass extends BaseDataItem { features: new ItemLinkFields(), featureState: new fields.NumberField({ required: true, initial: 1, min: 1 }), isMulticlass: new fields.BooleanField({ initial: false }), - linkedClass: new fields.DocumentUUIDField({ type: 'Item', nullable: true, initial: null }) + linkedClass: new ForeignDocumentUUIDField({ type: 'Item', nullable: true, initial: null }) }; } @@ -83,8 +83,7 @@ export default class DHSubclass extends BaseDataItem { ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.missingClass')); return false; } - - if ((await actorClass.system.fetchSubclasses()).every(x => x.uuid !== dataUuid)) { + if (actorClass.system.subclasses.every(x => x.uuid !== dataUuid)) { ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.subclassNotInClass')); return false; } diff --git a/module/data/settings/Homebrew.mjs b/module/data/settings/Homebrew.mjs index 31247458..b5e02675 100644 --- a/module/data/settings/Homebrew.mjs +++ b/module/data/settings/Homebrew.mjs @@ -1,5 +1,4 @@ import { defaultRestOptions } from '../../config/generalConfig.mjs'; -import { resetAndRerenderActors } from '../../helpers/utils.mjs'; import { ActionsField } from '../fields/actionField.mjs'; const currencyField = (initial, label, icon) => @@ -210,7 +209,7 @@ export default class DhHomebrew extends foundry.abstract.DataModel { } this.refreshConfig(); - resetAndRerenderActors(); + this.#resetActors(); } /** Update config values based on homebrew data. Make sure the references don't change */ @@ -231,6 +230,29 @@ export default class DhHomebrew extends foundry.abstract.DataModel { }); } } + + /** + * Triggers a reset and non-forced re-render on all given actors (if given) + * or all world actors and actors in all scenes to show immediate results for a changed setting. + */ + #resetActors() { + const actors = new Set( + [ + game.actors.contents, + game.scenes.contents.flatMap(s => s.tokens.contents).flatMap(t => t.actor ?? []) + ].flat() + ); + for (const actor of actors) { + for (const app of Object.values(actor.apps)) { + for (const element of app.element?.querySelectorAll('prose-mirror.active')) { + element.open = false; // This triggers a save + } + } + + actor.reset(); + actor.render(); + } + } } export class Resource extends foundry.abstract.DataModel { diff --git a/module/data/settings/Metagaming.mjs b/module/data/settings/Metagaming.mjs index 3694e09e..2bb5afdf 100644 --- a/module/data/settings/Metagaming.mjs +++ b/module/data/settings/Metagaming.mjs @@ -1,5 +1,3 @@ -import { resetAndRerenderActors } from '../../helpers/utils.mjs'; - export default class DhMetagaming extends foundry.abstract.DataModel { static defineSchema() { const fields = foundry.data.fields; @@ -8,24 +6,7 @@ export default class DhMetagaming extends foundry.abstract.DataModel { initial: false, label: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hideObserverPermissionInChat.label', hint: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hideObserverPermissionInChat.hint' - }), - hidePartyStats: new fields.StringField({ - initial: 'never', - label: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hidePartyStats.label', - hint: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hidePartyStats.hint', - required: true, - nullable: false, - choices: { - never: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hidePartyStats.choices.never', - players: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hidePartyStats.choices.players', - always: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hidePartyStats.choices.always' - } }) }; } - - /** Invoked by the setting when data changes */ - handleChange() { - resetAndRerenderActors(); - } } diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs index d6975f71..83dbbaf2 100644 --- a/module/dice/dhRoll.mjs +++ b/module/dice/dhRoll.mjs @@ -141,8 +141,8 @@ export default class DHRoll extends Roll { const metagamingSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Metagaming); const chatData = await this._prepareChatRenderContext({ flavor, isPrivate, ...options }); return foundry.applications.handlebars.renderTemplate(template, { - roll: this, ...chatData, + roll: this, parent: chatData.parent, targetMode: chatData.targetMode, areas: chatData.action?.areas, diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index 90937db4..faa046ff 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -793,26 +793,6 @@ export function getArmorSources(actor) { }); } -/** - * Triggers a reset and non-forced re-render on all given actors (if given) - * or all world actors and actors in all scenes to show immediate results for a changed setting. - */ -export function resetAndRerenderActors() { - const actors = new Set( - [game.actors.contents, game.scenes.contents.flatMap(s => s.tokens.contents).flatMap(t => t.actor ?? [])].flat() - ); - for (const actor of actors) { - for (const app of Object.values(actor.apps)) { - for (const element of app.element?.querySelectorAll('prose-mirror.active')) { - element.open = false; // This triggers a save - } - } - - actor.reset(); - actor.render(); - } -} - /** * Returns an array sorted by a function that returns a thing to compare, or an array to compare in order * Similar to lodash's sortBy function. @@ -861,11 +841,3 @@ export function createShallowProxy(obj) { } }); } - -export function camelize(str) { - return str - .replace(/(?:^\w|[A-Z]|\b\w)/g, (part, index) => { - return index === 0 ? part.toLowerCase() : part.toUpperCase(); - }) - .replace(/\s+/g, ''); -} diff --git a/module/systemRegistration/settings.mjs b/module/systemRegistration/settings.mjs index a66323c7..41cab011 100644 --- a/module/systemRegistration/settings.mjs +++ b/module/systemRegistration/settings.mjs @@ -91,10 +91,7 @@ const registerMenuSettings = () => { game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Metagaming, { scope: 'world', config: false, - type: DhMetagaming, - onChange: value => { - value.handleChange(); - } + type: DhMetagaming }); game.settings.register(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew, { diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index ff668bfd..afd56057 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -251,7 +251,8 @@ a:hover, a.active { - text-shadow: 0 0 1px currentColor, 0 0 1px currentColor, 0 0 8px light-dark(@dark-blue, @golden); + font-weight: bold; + text-shadow: 0 0 8px light-dark(@dark-blue, @golden); } fieldset { diff --git a/styles/less/global/feature-section.less b/styles/less/global/feature-section.less index 7d5099e1..13feb92c 100644 --- a/styles/less/global/feature-section.less +++ b/styles/less/global/feature-section.less @@ -19,36 +19,28 @@ &:last-child { margin-bottom: 0px; } - } - .feature-line { - display: grid; - align-items: center; - grid-template-columns: 1fr 4fr 1fr; - h4 { - font-weight: lighter; - color: light-dark(@dark, @beige); - } - .image { - height: 40px; - width: 40px; - object-fit: cover; - border-radius: 6px; - border: none; - } - .image-icon { - font-size: 26px; - width: 40px; - height: 40px; - display: flex; - justify-content: center; + .feature-line { + display: grid; align-items: center; - } - .controls { - display: flex; - justify-content: center; - gap: 10px; - a { - text-shadow: none; + grid-template-columns: 1fr 4fr 1fr; + h4 { + font-weight: lighter; + color: light-dark(@dark, @beige); + } + .image { + height: 40px; + width: 40px; + object-fit: cover; + border-radius: 6px; + border: none; + } + .controls { + display: flex; + justify-content: center; + gap: 10px; + a { + text-shadow: none; + } } } } diff --git a/styles/less/sheets/actors/character/header.less b/styles/less/sheets/actors/character/header.less index 21ea4846..31fd4256 100644 --- a/styles/less/sheets/actors/character/header.less +++ b/styles/less/sheets/actors/character/header.less @@ -5,12 +5,20 @@ // Theme header backgrounds .appTheme({ .character-header-sheet { + .trait { + background: url(../assets/svg/trait-shield.svg) no-repeat; + } + .character-row .domains-section img { filter: @golden-filter; } } }, { .character-header-sheet { + .trait { + background: url('../assets/svg/trait-shield-light.svg') no-repeat; + } + .character-row .domains-section img { filter: brightness(0) saturate(100%); } @@ -25,19 +33,13 @@ .name-row { display: flex; - gap: 6px; + gap: 5px; align-items: start; justify-content: space-between; padding: 0; padding-top: 5px; flex: 1; - [contenteditable], - input { - border: 1px solid @soft-shadow; - background-color: light-dark(@dark-15, @soft-white-shadow); - } - h1 { display: flex; flex: 1; @@ -63,16 +65,14 @@ .label { display: flex; - align-items: baseline; + align-items: center; gap: 4px; } input { - border: none; width: 40px; padding: 0; text-align: center; - font-weight: 600; } .level-button { @@ -101,7 +101,7 @@ display: flex; justify-content: space-between; padding: 5px 0; - margin-bottom: 8px; + margin-bottom: 10px; font-size: var(--font-size-12); color: light-dark(@dark-blue, @golden); @@ -131,7 +131,7 @@ display: flex; align-items: center; padding: 0; - margin-bottom: 12px; + margin-bottom: 15px; .resource-section { display: flex; @@ -168,7 +168,7 @@ .domains-section { position: relative; display: flex; - gap: 4px; + gap: 10px; background-color: light-dark(transparent, @dark-blue); color: light-dark(@dark-blue, @golden); padding: 5px 10px; @@ -183,7 +183,6 @@ font-weight: bold; text-transform: uppercase; color: light-dark(@dark-blue, @golden); - margin-right: 4px; } .domain { @@ -218,110 +217,37 @@ .character-traits { display: flex; + justify-content: space-between; padding: 0; margin-bottom: 15px; - justify-content: space-between; - max-width: 38.5rem; - gap: 0.5rem; - padding-left: 0.5rem; .trait { - --color-border: light-dark(@semi-transparent-dark-blue, @golden-60); + height: 60px; + width: 60px; cursor: pointer; - position: relative; - - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - min-width: 4.375rem; .trait-name { - position: relative; - background-color: light-dark(@semi-transparent-dark-blue, @golden-40); - border: 1px solid var(--color-border); - border-radius: 3px; - color: light-dark(var(--color-light-1), @golden); - font-size: var(--font-size-12); - font-weight: 600; - height: 1rem; - line-height: 1rem; - white-space: nowrap; - width: 100%; - padding: 0 0.1876px 0 0.375rem; - margin-right: 0.125rem; /* makes it center SLIGHTLY */ - text-shadow: 1px 1px 2px @light-black; - display: flex; align-items: center; + padding-top: 5px; + color: light-dark(@dark-blue, @golden); + font-size: var(--font-size-14); + font-weight: 600; + align-items: center; justify-content: center; + gap: 3px; - .tier-mark { - position: absolute; - background-color: @dark-blue; - border: 1px solid light-dark(@dark-blue, @golden); - border-radius: 50%; - width: 1rem; - height: 1rem; - right: calc(100% - 0.4375rem); - display: flex; - justify-content: center; - align-items: center; - &.marked::before { - content: ' '; - position: absolute; - width: 0.5rem; - height: 0.5rem; - border-radius: 50%; - background-color: @golden; - } + i { + line-height: 17px; + font-size: var(--font-size-10); } } - .trait-value-area { - --background: light-dark(#e8e6e3, @dark-blue); - display: flex; - position: relative; - .trait-value { - position: absolute; - inset: 0; - display: flex; - align-items: center; - - justify-content: center; - font-style: normal; - font-weight: 600; - font-size: var(--font-size-20); - text-align: center; - margin-bottom: 0.375rem; - } - - .spellcasting-mark { - position: absolute; - border: 1px solid light-dark(@dark-blue, @golden); - color: @golden; - left: 0; - right: 0; - bottom: -0.375rem; - margin-inline: auto; - border-radius: 50%; - width: 1.125rem; - height: 1.125rem; - background: radial-gradient(190.63% 190.63% at 50% -80.63%, #18152E 70%, #4D4494 80%, #A0837E 90%, var(--color-border) 100%); - font-size: var(--font-size-9); - text-shadow: 0 0 2px @light-black; - - display: flex; - align-items: center; - justify-content: center; - } - } - - &:hover { - .trait-name { - color: light-dark(@dark, @beige); - text-shadow: 0 0 8px light-dark(@dark-80, @beige-80); - } + .trait-value { + font-style: normal; + font-weight: 400; + font-size: var(--font-size-20); + text-align: center; } } } diff --git a/styles/less/sheets/actors/character/sidebar.less b/styles/less/sheets/actors/character/sidebar.less index 0e6e3d97..b159a8e8 100644 --- a/styles/less/sheets/actors/character/sidebar.less +++ b/styles/less/sheets/actors/character/sidebar.less @@ -74,6 +74,62 @@ .death-roll-btn { display: none; } + + .icons-list { + position: absolute; + display: flex; + flex-direction: column; + gap: 5px; + align-items: end; + justify-content: center; + top: 45px; + right: 10px; + + .spellcast-icon { + display: flex; + align-items: center; + justify-content: end; + text-align: center; + padding-right: 8px; + max-width: 50px; + height: 50px; + font-size: 1.2rem; + background: light-dark(@dark-blue-60, @dark-golden-80); + backdrop-filter: blur(8px); + border: 4px double light-dark(@beige, @golden); + color: light-dark(@beige, @golden); + border-radius: 999px; + transition: all 0.3s ease; + + .spellcast-label { + font-size: var(--font-size-14); + opacity: 0; + margin-right: 0.3rem; + transition: all 0.3s ease; + } + + i { + height: 24px; + width: 24px; + align-content: center; + margin-right: 3px; + } + + &:not(.no-label):hover { + max-width: 300px; + padding: 0 10px; + border-radius: 60px; + + .spellcast-label { + opacity: 1; + } + + i { + margin-right: 0px; + } + } + } + } } .info-section { diff --git a/styles/less/sheets/actors/party/party-members.less b/styles/less/sheets/actors/party/party-members.less index a29f7c88..2e2f4cf8 100644 --- a/styles/less/sheets/actors/party/party-members.less +++ b/styles/less/sheets/actors/party/party-members.less @@ -280,17 +280,6 @@ body.game:is(.performance-low, .noblur) { } } - .actors-list.limited { - .actor-resources { - display: flex; - align-items: center; - } - .actor-img-frame { - width: 3rem; - height: 3rem; - } - } - .actors-dragger { display: flex; align-items: center; diff --git a/styles/less/sheets/items/item-sheet-shared.less b/styles/less/sheets/items/item-sheet-shared.less index 5155ad70..d0a8cc48 100644 --- a/styles/less/sheets/items/item-sheet-shared.less +++ b/styles/less/sheets/items/item-sheet-shared.less @@ -10,8 +10,4 @@ font-family: @font-body; color: light-dark(@chat-blue-bg, @beige-50); } - - button.plain.inline-control { - flex: 0 0 auto; - } } diff --git a/styles/less/utils/colors.less b/styles/less/utils/colors.less index 18b981ad..8f6418bf 100755 --- a/styles/less/utils/colors.less +++ b/styles/less/utils/colors.less @@ -5,7 +5,6 @@ --golden: #f3c267; --golden-10: #f3c26710; --golden-40: #f3c26740; - --golden-60: #f3c26760; --golden-90: #f3c26790; --golden-bg: #f3c2671a; --golden-secondary: #eaaf42; @@ -90,7 +89,6 @@ @golden: var(--golden, #f3c267); @golden-10: var(--golden-10, #f3c26710); @golden-40: var(--golden-40, #f3c26740); -@golden-60: var(--golden-60, #f3c26760); @golden-90: var(--golden-90, #f3c26790); @golden-bg: var(--golden-bg, #f3c2671a); @golden-secondary: var(--golden-secondary, #eaaf42); diff --git a/styles/less/utils/fonts.less b/styles/less/utils/fonts.less index 201ea356..5c1e597a 100755 --- a/styles/less/utils/fonts.less +++ b/styles/less/utils/fonts.less @@ -5,11 +5,6 @@ --dh-font-title: 'Cinzel Decorative'; --dh-font-subtitle: 'Cinzel'; --dh-font-body: 'Montserrat'; - - /* Include missing font sizes */ - --font-size-8: 0.5rem; - --font-size-9: 0.5625rem; - --font-size-22: 1.375rem; } @font-title: ~"var(--dh-font-title, 'Cinzel Decorative'), serif"; diff --git a/system.json b/system.json index 16a1f74b..ac581343 100644 --- a/system.json +++ b/system.json @@ -2,15 +2,15 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "2.2.4", + "version": "2.2.3", "compatibility": { "minimum": "14.359", - "verified": "14.361", + "verified": "14.360", "maximum": "14" }, "url": "https://github.com/Foundryborne/daggerheart", "manifest": "https://raw.githubusercontent.com/Foundryborne/daggerheart/v14/system.json", - "download": "https://github.com/Foundryborne/daggerheart/releases/download/2.2.4/system.zip", + "download": "https://github.com/Foundryborne/daggerheart/releases/download/2.2.3/system.zip", "authors": [ { "name": "WBHarry" diff --git a/templates/settings/metagaming-settings/general.hbs b/templates/settings/metagaming-settings/general.hbs index 775ff016..7f36715e 100644 --- a/templates/settings/metagaming-settings/general.hbs +++ b/templates/settings/metagaming-settings/general.hbs @@ -1,4 +1,3 @@