diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index 2a557411..f40c144a 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -718,7 +718,7 @@ export default class CharacterSheet extends DHBaseActorSheet { ? { 'system.linkedClass.uuid': { key: 'system.linkedClass.uuid', - value: this.document.system.class.value?._stats.compendiumSource + value: this.document.system.class.value._stats.compendiumSource } } : undefined, diff --git a/module/data/item/subclass.mjs b/module/data/item/subclass.mjs index ecf72de3..12d85c1e 100644 --- a/module/data/item/subclass.mjs +++ b/module/data/item/subclass.mjs @@ -56,30 +56,38 @@ export default class DHSubclass extends BaseDataItem { if (allowed === false) return; if (this.actor?.type === 'character') { - const { value: actorClass, subclass: existingSubclass } = this.actor.system.class; - const { value: multiclass, subclass: existingMultisubclass } = this.actor.system.multiclass; - if (!actorClass && !multiclass) { - ui.notifications.warn('DAGGERHEART.UI.Notifications.missingClass', { localize: true }); - return false; - } - if (existingSubclass && existingMultisubclass) { - ui.notifications.warn('DAGGERHEART.UI.Notifications.subclassesAlreadyPresent', { localize: true }); - return false; - } - if (existingSubclass && !multiclass) { - ui.notifications.warn('DAGGERHEART.UI.Notifications.missingMulticlass', { localize: true }); - return false; - } + const dataUuid = data.uuid ?? data._stats.compendiumSource ?? `Item.${data._id}`; + if (this.actor.system.class.subclass) { + if (this.actor.system.multiclass.subclass) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.subclassesAlreadyPresent')); + return false; + } else { + const multiclass = this.actor.items.find(x => x.type === 'class' && x.system.isMulticlass); + if (!multiclass) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.missingMulticlass')); + return false; + } - const match = [multiclass, actorClass].find( - c => c && (c._stats.compendiumSource ?? c.uuid) === this.linkedClass - ); - if (!match) { - const key = multiclass ? 'subclassNotInMulticlass' : 'subclassNotInClass'; - ui.notifications.warn(`DAGGERHEART.UI.Notifications.${key}`, { localize: true }); - return false; - } else if (match.system.isMulticlass) { - await this.updateSource({ isMulticlass: true }); + if (multiclass.system.subclasses.every(x => x.uuid !== dataUuid)) { + ui.notifications.error( + game.i18n.localize('DAGGERHEART.UI.Notifications.subclassNotInMulticlass') + ); + return false; + } + + await this.updateSource({ isMulticlass: true }); + } + } else { + const actorClass = this.actor.items.find(x => x.type === 'class' && !x.system.isMulticlass); + if (!actorClass) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.missingClass')); + return false; + } + + if ((await actorClass.system.fetchSubclasses()).every(x => x.uuid !== dataUuid)) { + ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.subclassNotInClass')); + return false; + } } } } diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index e4c11a5c..91bf7190 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -153,13 +153,10 @@ export default class DhpActor extends Actor { async updateLevel(newLevel) { if (!['character', 'companion'].includes(this.type) || newLevel === this.system.levelData.level.changed) return; - const tiers = Object.values(game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers); - const maxLevel = tiers.reduce((acc, tier) => Math.max(acc, tier.levels.end), 0); - const multiclassMinLevel = Math.min( - maxLevel, - ...tiers.filter(t => t.options.multiclass).map(t => t.levels.start) - ); if (newLevel > this.system.levelData.level.current) { + const maxLevel = Object.values( + game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers + ).reduce((acc, tier) => Math.max(acc, tier.levels.end), 0); if (newLevel > maxLevel) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.tooHighLevel')); } @@ -234,19 +231,18 @@ export default class DhpActor extends Actor { this.system.multiclass.subclass.update({ 'system.featureState': subclassFeatureState.multiclass }); } - // Remove multiclass if we're removing a multiclass feature or if we're below the multiclass minimum level - // Multclasses cannot be manually removed on the sheet, so this allows recovering in the case of errors - if (multiclass || newLevel < multiclassMinLevel) { - const multiclassItems = this.items.filter( - x => - x.uuid === multiclass?.itemUuid || - x.system.isMulticlass || - (['class', 'subclass'].includes(x.system.originItemType) && x.system.multiclassOrigin) + if (multiclass) { + const multiclassItem = this.items.find(x => x.uuid === multiclass.itemUuid); + const multiclassFeatures = this.items.filter( + x => x.system.originItemType === 'class' && x.system.multiclassOrigin + ); + const subclassFeatures = this.items.filter( + x => x.system.originItemType === 'subclass' && x.system.multiclassOrigin ); this.deleteEmbeddedDocuments( 'Item', - multiclassItems.map(x => x.id) + [multiclassItem, ...multiclassFeatures, ...subclassFeatures].map(x => x.id) ); this.update({ @@ -285,7 +281,6 @@ export default class DhpActor extends Actor { async levelUp(levelupData) { const levelupAuto = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).levelupAuto; - const getStatsWithSource = document => ({ ...(document._stats ?? {}), compendiumSource: document.uuid }); const levelups = {}; for (var levelKey of Object.keys(levelupData)) { @@ -398,8 +393,8 @@ export default class DhpActor extends Actor { const embeddedItem = await this.createEmbeddedDocuments('Item', [ { ...multiclassData, - uuid: multiclassItem.uuid, // todo: replace with setting an id and using keepId - _stats: getStatsWithSource(multiclassItem), + uuid: multiclassItem.uuid, + _stats: multiclassItem._stats, system: { ...multiclassData.system, features: multiclassData.system.features.filter(x => x.type !== 'hope'), @@ -412,8 +407,8 @@ export default class DhpActor extends Actor { await this.createEmbeddedDocuments('Item', [ { ...subclassData, - uuid: subclassItem.uuid, // todo: replace with setting an id and using keepId - _stats: getStatsWithSource(subclassItem), + uuid: subclassItem.uuid, + _stats: subclassItem._stats, system: { ...subclassData.system, isMulticlass: true @@ -433,8 +428,8 @@ export default class DhpActor extends Actor { const embeddedItem = await this.createEmbeddedDocuments('Item', [ { ...cardData, - uuid: cardItem.uuid, // todo: replace with setting an id and using keepId - _stats: getStatsWithSource(cardItem), + uuid: cardItem.uuid, + _stats: cardItem._stats, system: { ...cardData.system, inVault: true @@ -455,7 +450,8 @@ export default class DhpActor extends Actor { const embeddedItem = await this.createEmbeddedDocuments('Item', [ { ...cardData, - _stats: getStatsWithSource(cardItem), + uuid: cardItem.uuid, + _stats: cardItem._stats, system: { ...cardData.system, inVault: true diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index 7d46d627..181bd0d3 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -7,12 +7,12 @@ input[type='text'], input[type='number'], textarea, - file-picker, .input[contenteditable] { background: light-dark(transparent, transparent); border-radius: 6px; box-shadow: 0 4px 30px @soft-shadow; backdrop-filter: blur(9.5px); + -webkit-backdrop-filter: blur(9.5px); outline: 2px solid transparent; color: light-dark(@dark-blue, @golden); border: 1px solid light-dark(@dark, @beige); @@ -98,7 +98,7 @@ color: light-dark(@dark, @beige); } - button:where(:not(.plain, color-picker *, file-picker *)) { + button:where(:not(.plain)) { background: light-dark(transparent, @golden); border: 1px solid light-dark(@dark-blue, @dark-blue); color: light-dark(@dark-blue, @dark-blue); @@ -252,15 +252,6 @@ text-shadow: 0 0 1px currentColor, 0 0 1px currentColor, 0 0 8px light-dark(@dark-blue, @golden); } - file-picker, color-picker { - > input[type=text] { - background: transparent; - border: none; - outline: none; - backdrop-filter: unset; - } - } - fieldset { align-items: center; margin-top: 5px; @@ -606,6 +597,59 @@ } } +.application.setting.dh-style { + h2, + h3, + h4 { + margin: 8px 0 4px; + text-align: center; + } + + footer { + margin-top: 8px; + display: flex; + gap: 8px; + + button { + flex: 1; + } + } + + .form-group { + display: flex; + justify-content: space-between; + align-items: center; + gap: 0.25rem 0.5rem; + flex-wrap: wrap; + + label { + font-size: var(--font-size-14); + font-weight: normal; + } + + .form-fields { + display: flex; + gap: 4px; + align-items: center; + } + + &.setting-two-values { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 0.25rem 0.5rem; + + .form-group { + justify-content: end; + flex-wrap: nowrap; + } + + .hint { + grid-column: 1 / -1; + } + } + } +} + .system-daggerheart { .tagify { background: light-dark(transparent, transparent); diff --git a/styles/less/ui/settings/homebrew-settings/resources.less b/styles/less/ui/settings/homebrew-settings/resources.less index 1184904b..5333e54d 100644 --- a/styles/less/ui/settings/homebrew-settings/resources.less +++ b/styles/less/ui/settings/homebrew-settings/resources.less @@ -24,7 +24,7 @@ .resource-icons-container { display: flex; justify-content: space-between; - gap: 10px; + gap: 8px; width: 100%; .resource-icon-container { diff --git a/styles/less/ui/settings/settings.less b/styles/less/ui/settings/settings.less index d08f74e6..34f17d53 100644 --- a/styles/less/ui/settings/settings.less +++ b/styles/less/ui/settings/settings.less @@ -1,67 +1,6 @@ @import '../../utils/colors.less'; .daggerheart.dh-style.setting { - --color-form-label: var(--color-text-primary); - - h2, - h3, - h4 { - margin: 8px 0 4px; - text-align: center; - } - - footer { - margin-top: 8px; - display: flex; - gap: 8px; - - button { - flex: 1; - } - } - - .standard-form { - gap: var(--spacer-8); - .form-group .form-fields { - width: unset; - } - } - - .form-group { - display: flex; - justify-content: space-between; - align-items: center; - gap: 0.25rem 0.5rem; - flex-wrap: wrap; - - label { - font-size: var(--font-size-14); - font-weight: normal; - line-height: var(--input-height); - } - - .form-fields { - display: flex; - gap: 4px; - align-items: center; - } - - &.setting-two-values { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 0.25rem 0.5rem; - - .form-group { - justify-content: end; - flex-wrap: nowrap; - } - - .hint { - grid-column: 1 / -1; - } - } - } - fieldset { display: flex; flex-direction: column; @@ -80,10 +19,7 @@ &.three-columns { display: grid; grid-template-columns: 1fr 1fr 1fr; - gap: 4px; - .form-group label { - line-height: unset; - } + gap: 2px; } &.six-columns { diff --git a/templates/settings/metagaming-settings/general.hbs b/templates/settings/metagaming-settings/general.hbs index 9f5bd514..775ff016 100644 --- a/templates/settings/metagaming-settings/general.hbs +++ b/templates/settings/metagaming-settings/general.hbs @@ -1,4 +1,4 @@ -
+
{{formGroup settingFields.schema.fields.hideObserverPermissionInChat value=settingFields._source.hideObserverPermissionInChat localize=true}} - {{formGroup settingFields.schema.fields.hidePartyStats value=settingFields._source.hidePartyStats localize=true}} -
+ {{formGroup settingFields.schema.fields.hidePartyStats value=settingFields._source.hidePartyStats localize=true}} +
\ No newline at end of file diff --git a/templates/sheets/actors/character/sidebar.hbs b/templates/sheets/actors/character/sidebar.hbs index 313c81f9..91779e9c 100644 --- a/templates/sheets/actors/character/sidebar.hbs +++ b/templates/sheets/actors/character/sidebar.hbs @@ -44,7 +44,7 @@ {{else}}
- + / {{document.system.armorScore.max}}