diff --git a/README.md b/README.md index 6c90e73e..177636c7 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,11 @@ ## Table of Contents -- [Foundryborne Daggerheart](#foundryborne-daggerheart) - - [Table of Contents](#table-of-contents) - - [Overview](#overview) - - [User Install](#user-install) - - [Documentation](#documentation) - - [Development Setup](#development-setup) - - [Available Scripts](#available-scripts) - - [Notes](#notes) - - [Contributing](#contributing) - - [AI Policy](#ai-policy) - - [Disclaimer](#disclaimer) +- [Overview](#overview) +- [User Install Guide](#user-install) +- [Documentation](#documentation) +- [Developer Setup](#development-setup) +- [Contribution Info](#contributing) ## Overview @@ -78,7 +72,7 @@ Looking to contribute to the project? Look no further, check out our [contributi The Foundryborne Daggerheart system does not make use of AI (generative or otherwise) for any area of its implementation. We expect all contributors to follow this same policy when contributing with a pull request; contributions made using AI will be rejected outright. -## Disclaimer +## Disclaimer: **Daggerheart System** Daggerheart is a trademark of Darrington Press LLC. All original content, mechanics, and intellectual property related to the Daggerheart roleplaying game are © Darrington Press LLC. diff --git a/daggerheart.d.ts b/daggerheart.d.ts index 891a3a2a..1641faa8 100644 --- a/daggerheart.d.ts +++ b/daggerheart.d.ts @@ -4,15 +4,6 @@ import '@common/primitives/global.mjs'; import Canvas from '@client/canvas/board.mjs'; import { ResourceUpdateMap } from './module/data/action/baseAction.mjs'; -import * as applications from './module/applications/_module.mjs'; -import * as data from './module/data/_module.mjs'; -import * as models from './module/data/_module.mjs'; -import * as documents from './module/documents/_module.mjs'; -import { macros } from './module/_module.mjs'; -import * as dice from './module/dice/_module.mjs'; -import * as fields from './module/data/fields/_module.mjs'; - - // Foundry's use of `Object.assign(globalThis) means many globally available objects are not read as such // This declare global hopefully fixes that // Note: eslint is not aware of these, whatever is added here should go in the eslint's globals list @@ -89,17 +80,3 @@ declare global { damageOptions: object; } } - -declare module '@client/packages/system.mjs' { - export default interface System { - api: { - applications: typeof applications, - data: typeof data, - models: typeof models, - documents: typeof documents, - macros: typeof macros, - dice: typeof dice, - fields: typeof fields - }; - } -} diff --git a/lang/en.json b/lang/en.json index b9a81b29..0180b085 100755 --- a/lang/en.json +++ b/lang/en.json @@ -84,7 +84,6 @@ "transformActorMissing": "The assigned actor to transform into does not exist. It was probably deleted or moved in/out of a compendium", "canvasError": "There is no active scene.", "prototypeError": "You can only use a transform action from a Token", - "linkedSelectedError": "To transform a linked actor there either needs to be only a single token of it on the canvas, or you need to left-click select only one of them.", "actorLinkError": "You cannot transform a token with Actor Link set to true" } }, diff --git a/module/applications/sheets/actors/adversary.mjs b/module/applications/sheets/actors/adversary.mjs index b6e17ddd..bcfe3cbb 100644 --- a/module/applications/sheets/actors/adversary.mjs +++ b/module/applications/sheets/actors/adversary.mjs @@ -7,7 +7,7 @@ export default class AdversarySheet extends DHBaseActorSheet { /** @inheritDoc */ static DEFAULT_OPTIONS = { classes: ['adversary'], - position: { width: 645, height: 750 }, + position: { width: 645, height: 760 }, window: { resizable: true }, actions: { toggleHitPoints: AdversarySheet.#toggleHitPoints, diff --git a/module/applications/ui/effectsDisplay.mjs b/module/applications/ui/effectsDisplay.mjs index c9739f56..a64b1b22 100644 --- a/module/applications/ui/effectsDisplay.mjs +++ b/module/applications/ui/effectsDisplay.mjs @@ -39,12 +39,6 @@ export default class DhEffectsDisplay extends HandlebarsApplicationMixin(Applica } }; - /** - * Debounce and slightly delayed request to re-render this panel. Necessary for situations where it is not possible - * to properly wait for promises to resolve before refreshing the UI. - */ - refresh = foundry.utils.debounce(this.render.bind(this), 50); - get element() { return document.body.querySelector('.daggerheart.dh-style.effects-display'); } diff --git a/module/data/action/baseAction.mjs b/module/data/action/baseAction.mjs index be7224cd..58be672b 100644 --- a/module/data/action/baseAction.mjs +++ b/module/data/action/baseAction.mjs @@ -114,10 +114,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel return this._id; } - /** - * Returns true if the current user is the owner of the containing item. - * @returns {boolean} - */ + /** Returns true if the current user is the owner of the containing item */ get isOwner() { return this.item?.isOwner ?? true; } @@ -146,7 +143,6 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel /** * Return the first Actor parent found. - * @returns {DhpActor | null} */ get actor() { return this.item instanceof DhpActor @@ -159,7 +155,6 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel /** * Returns true if the action is usable. * An action is usable on any actor type. For example, an adversary might have a base attack action. - * @returns {boolean} */ get usable() { const actor = this.actor; diff --git a/module/data/actor/tierAdjustment.mjs b/module/data/actor/tierAdjustment.mjs index 8b9e5bdc..bc6ad176 100644 --- a/module/data/actor/tierAdjustment.mjs +++ b/module/data/actor/tierAdjustment.mjs @@ -2,14 +2,8 @@ import { calculateExpectedValue, parseTermsFromSimpleFormula } from '../../helpe import { adversaryExpectedDamage, adversaryScalingData } from '../../config/actorConfig.mjs'; import { parseInlineParams } from '../../enrichers/parser.mjs'; -/** - * Accepts source data for an adversary and a target tier, and returns new source data - * @type {object} source - * @type {number} tier - * @returns {object} adjusted source data - */ export function getTierAdjustedAdversary(source, tier) { - const currentTier = source.system.tier ?? 1; + const currentTier = source.tier ?? 1; /** @type {(2 | 3 | 4)[]} */ const tiers = new Array(Math.abs(tier - currentTier)) @@ -41,7 +35,7 @@ export function getTierAdjustedAdversary(source, tier) { // Store initial attack damage for abilities that have you deal a "standard attack" const initialAttack = { type: source.system.attack.damage?.parts.hitPoints?.type?.toSorted(), - value: getFormula(source.system.attack.damage?.parts.hitPoints?.value) + value: getDamagePartsFormula(source.system.attack.damage?.parts.hitPoints?.value) }; // Update damage of base attack. @@ -51,9 +45,9 @@ export function getTierAdjustedAdversary(source, tier) { for (const property of ['value', 'valueAlt']) { const data = damage.parts.hitPoints[property]; - const previousFormula = getFormula(data); - const value = calculateAdjustedDamage(previousFormula, 'attack', damageMeta); - applyAdjustedDamage(data, value); + const previousFormula = getDamagePartsFormula(data); + const { value, formula } = calculateAdjustedDamage(previousFormula, 'attack', damageMeta); + applyAdjustedDamage(data, value, formula); } } catch (err) { ui.notifications.warn('Failed to convert attack damage of adversary'); @@ -71,7 +65,7 @@ export function getTierAdjustedAdversary(source, tier) { if (!formula) return match; try { - const newFormula = getFormula(calculateAdjustedDamage(formula, 'action', damageMeta)); + const newFormula = calculateAdjustedDamage(formula, 'action', damageMeta)?.formula; descriptionFormulas.push(formula); return match.replace(formula, newFormula); } catch { @@ -88,15 +82,15 @@ export function getTierAdjustedAdversary(source, tier) { const result = []; for (const property of ['value', 'valueAlt']) { const { [property]: data, type: damageType } = action.damage.parts.hitPoints; - const previousFormula = getFormula(data); + const previousFormula = getDamagePartsFormula(data); const isActuallyAttack = previousFormula === initialAttack.value && foundry.utils.equals(damageType.toSorted(), initialAttack.type) && !descriptionFormulas.includes(previousFormula); const type = isActuallyAttack ? 'attack' : 'action'; - const value = calculateAdjustedDamage(previousFormula, type, damageMeta); - applyAdjustedDamage(data, value); - result.push({ previousFormula, formula: getFormula(value) }); + const { value, formula } = calculateAdjustedDamage(previousFormula, type, damageMeta); + applyAdjustedDamage(data, value, formula); + result.push({ previousFormula, formula }); } // Override text in the description with those values @@ -195,30 +189,24 @@ function calculateAdjustedDamage(formula, type, { currentDamageRange, newDamageR value.bonus = Math.round(expected - getBaseAverage()); } - return value; + const newFormula = [value.diceQuantity ? `${value.diceQuantity}d${value.faces}` : null, value.bonus] + .filter(p => !!p) + .join('+'); + return { value, formula: newFormula }; } -/** - * Get formula from either damage parts *or* a simple formula object. - * @returns {string} the new formula data - */ -function getFormula(data) { - if (data.custom?.enabled) { - return data.custom.formula; - } - - const diceQuantity = data.flatMultiplier ?? data.diceQuantity; - const dice = data.faces ? `d${data.faces}` : data.dice; - const mod = data.bonus; - return [diceQuantity ? `${diceQuantity}${dice}` : 0, mod].filter(p => !!p).join('+'); +function getDamagePartsFormula(data) { + return data.custom.enabled + ? data.custom.formula + : [data.flatMultiplier ? `${data.flatMultiplier}${data.dice}` : 0, data.bonus ?? 0].filter(p => !!p).join('+'); } /** * Updates damage to reflect a specific value. - * @param {object} diceData - * @param {object} value + * @throws if damage structure is invalid for conversion + * @returns the converted formula and value as a simplified term, or null if it doesn't deal HP damage */ -function applyAdjustedDamage(diceData, value) { +function applyAdjustedDamage(diceData, value, formula) { if (value.diceQuantity) { diceData.custom.enabled = false; diceData.bonus = value.bonus; @@ -226,6 +214,6 @@ function applyAdjustedDamage(diceData, value) { diceData.flatMultiplier = value.diceQuantity; } else if (!value.diceQuantity) { diceData.custom.enabled = true; - diceData.custom.formula = getFormula(value); + diceData.custom.formula = formula; } } diff --git a/module/data/fields/action/transformField.mjs b/module/data/fields/action/transformField.mjs index 0fc35742..07b32166 100644 --- a/module/data/fields/action/transformField.mjs +++ b/module/data/fields/action/transformField.mjs @@ -1,11 +1,5 @@ -import { getWorldActor } from '../../../helpers/utils.mjs'; - const fields = foundry.data.fields; -/** - * @import DHSummonAction from '../../action/summonAction.mjs' - */ - export default class DHSummonField extends fields.SchemaField { /** * Action Workflow order @@ -26,11 +20,6 @@ export default class DHSummonField extends fields.SchemaField { super(transformFields, options, context); } - /** - * Runs the execute. This is run on behalf of DHSummonAction. - * @todo move this function to be on the summon action. - * @this DHSummonAction - */ static async execute() { if (!this.transform.actorUUID) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.noTransformActor')); @@ -48,37 +37,26 @@ export default class DHSummonField extends fields.SchemaField { return false; } - const activeTokens = this.actor.getActiveTokens(false, true); - const controlledMatchingTokens = canvas.tokens.controlled - .filter(x => x.actor && x.actor.uuid === this.actor.uuid) - .map(x => x.document); - /** @type {typeof game.system.api.documents.DhToken | null} */ - const token = this.actor.token ?? ( - activeTokens.length === 1 ? activeTokens[0] : - (controlledMatchingTokens.length === 1 ? controlledMatchingTokens[0] : null) - ); - - if (!this.actor.token && !token) { - ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.linkedSelectedError')); + if (this.actor.prototypeToken.actorLink) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.actorLinkError')); return false; } - if (!token) { + if (!this.actor.token) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.prototypeError')); return false; } - const actor = await getWorldActor(baseActor); + const actor = await DHSummonField.getWorldActor(baseActor); const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes; const tokenSize = actor?.system.metadata.usesSize ? tokenSizes[actor.system.size] : actor.prototypeToken.width; - // Update token. Avoid using recursive: false, since that prevents animations - await token.update( - { ...actor.prototypeToken.toObject(), actorId: actor.id, width: tokenSize, height: tokenSize }, - { diff: false, noHook: true } + await this.actor.token.update( + { ...actor.prototypeToken.toJSON(), actorId: actor.id, width: tokenSize, height: tokenSize }, + { diff: false, recursive: false, noHook: true } ); - if (token.combatant) { + if (this.actor.token.combatant) { this.actor.token.combatant.update({ actorId: actor.id, img: actor.prototypeToken.texture.src }); } @@ -86,17 +64,17 @@ export default class DHSummonField extends fields.SchemaField { if (!this.transform.resourceRefresh.hitPoints) { marks.hitPoints = Math.min( this.actor.system.resources.hitPoints.value, - token.actor.system.resources.hitPoints.max - 1 + this.actor.token.actor.system.resources.hitPoints.max - 1 ); } if (!this.transform.resourceRefresh.stress) { marks.stress = Math.min( this.actor.system.resources.stress.value, - token.actor.system.resources.stress.max - 1 + this.actor.token.actor.system.resources.stress.max - 1 ); } if (marks.hitPoints || marks.stress) { - token.actor.update({ + this.actor.token.actor.update({ 'system.resources': { hitPoints: { value: marks.hitPoints }, stress: { value: marks.stress } @@ -106,9 +84,20 @@ export default class DHSummonField extends fields.SchemaField { const prevPosition = { ...this.actor.sheet.position }; this.actor.sheet.close(); - token.actor.sheet.render({ force: true, position: prevPosition }); - if (token.object.controlled) { - ui.effectsDisplay.refresh(); + this.actor.token.actor.sheet.render({ force: true, position: prevPosition }); + } + + /* Check for any available instances of the actor present in the world, or create a world actor based on compendium */ + static async getWorldActor(baseActor) { + if (!baseActor.inCompendium) return baseActor; + + const dataType = game.system.api.data.actors[`Dh${baseActor.type.capitalize()}`]; + if (dataType && baseActor.img === dataType.DEFAULT_ICON) { + const worldActorCopy = game.actors.find(x => x.name === baseActor.name); + if (worldActorCopy) return worldActorCopy; } + + const worldActor = await game.system.api.documents.DhpActor.create(baseActor.toObject()); + return worldActor; } } diff --git a/module/data/item/weapon.mjs b/module/data/item/weapon.mjs index 42326f93..39c0fc8e 100644 --- a/module/data/item/weapon.mjs +++ b/module/data/item/weapon.mjs @@ -9,8 +9,7 @@ export default class DHWeapon extends AttachableItem { type: 'weapon', hasDescription: true, isInventoryItem: true, - hasActions: true, - hasResource: true + hasActions: true }); } diff --git a/module/documents/_types.d.ts b/module/documents/_types.d.ts index a3af1b33..a94d6395 100644 --- a/module/documents/_types.d.ts +++ b/module/documents/_types.d.ts @@ -3,26 +3,17 @@ import DHItem from './item.mjs'; import BaseDataItem from '../data/item/base.mjs'; import DhActiveEffect from './activeEffect.mjs'; import EmbeddedCollection from '@common/abstract/embedded-collection.mjs'; -import DHToken from './token.mjs'; -import Actor from '@client/documents/actor.mjs'; -import Item from '@client/documents/item.mjs'; declare module './actor.mjs' { - export default interface DhpActor extends Actor { + export default interface DhpActor { system: T; items: EmbeddedCollection; effects: EmbeddedCollection; - get token(): DHToken | null; - - /** @inheritdoc */ - getActiveTokens(linked?: boolean, document?: boolean): (DHToken | foundry.canvas.placeables.Token)[]; - getActiveTokens(linked?: boolean, document: true): DHToken[]; - getActiveTokens(linked?: boolean, document: false): foundry.canvas.placeables.Token[]; } } declare module './item.mjs' { - export default interface DHItem extends Item { + export default interface DHItem { parent: DhpActor; actor: DhpActor; system: T; diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 30901374..8ef64f65 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -34,14 +34,12 @@ export default class DhpActor extends Actor { super.prepareData(); // Update effects if it is the user's character or is controlled - // A timeout avoids an infinite loop when accessing token actors before the delta is finished constructing - window.setTimeout(() => { - if (!canvas.ready) return; + if (canvas.ready) { const controlled = canvas.tokens.controlled.some(t => t.actor === this); if (game.user.character === this || controlled) { - ui.effectsDisplay.refresh(); + ui.effectsDisplay.render(); } - }, 0); + } } /* -------------------------------------------- */ diff --git a/module/documents/token.mjs b/module/documents/token.mjs index d70480db..8e91d4f0 100644 --- a/module/documents/token.mjs +++ b/module/documents/token.mjs @@ -38,8 +38,7 @@ export default class DHToken extends CONFIG.Token.documentClass { tokens.filter(x => x.actor).map(x => x.actor) ); } - - await super.createCombatants(tokens, combat ?? {}); + super.createCombatants(tokens, combat ?? {}); } /**@inheritdoc */ diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index 84bcacf2..71f43997 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -1,10 +1,6 @@ import { diceTypes, getDiceSoNicePresets, getDiceSoNicePreset, range } from '../config/generalConfig.mjs'; import Tagify from '@yaireo/tagify'; -/** - * @import DhpActor from '../documents/actor.mjs'; - */ - export const capitalize = string => { return string.charAt(0).toUpperCase() + string.slice(1); }; @@ -895,13 +891,6 @@ export function shouldUseHopeFearAutomation(options = { gmAsPlayer: true }) { return (!game.user.isGM || options.gmAsPlayer) ? hopeFear.players : hopeFear.gm; } -/** - * Returns the given actor if its a world actor, - * finds a world actor equivalent, - * or imports the actor and returns the imported actor. - * @param {DhpActor} baseActor - * @returns {Promise} a world actor - */ export async function getWorldActor(baseActor) { if (baseActor.inCompendium) { const worldActorCandidates = game.actors.filter(x => diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index d570c08c..f7934b71 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -261,7 +261,7 @@ fieldset { align-items: center; - margin: 5px 0 0 0; + margin-top: 5px; border-radius: 6px; border-color: @color-fieldset-border; padding-inline: 0.625rem; diff --git a/styles/less/global/sheet.less b/styles/less/global/sheet.less index 8381c7c3..e3072da1 100755 --- a/styles/less/global/sheet.less +++ b/styles/less/global/sheet.less @@ -54,7 +54,7 @@ body.game:is(.performance-low, .noblur) { position: relative; min-height: -webkit-fill-available; transition: opacity 0.3s ease; - padding-bottom: 16px; + padding-bottom: 20px; .tab { padding: 0 10px; diff --git a/styles/less/sheets/actors/actor-sheet-shared.less b/styles/less/sheets/actors/actor-sheet-shared.less index 3e233013..5eb5b43c 100644 --- a/styles/less/sheets/actors/actor-sheet-shared.less +++ b/styles/less/sheets/actors/actor-sheet-shared.less @@ -39,20 +39,6 @@ .window-header > .attribution-header-label { margin-right: var(--spacer-4); - pointer-events: none; - } - - .tab-navigation { - margin-bottom: 0; - } - - .tab { - flex: 1; - padding: 0; - overflow: hidden; - .search-section { - padding: 12px 14px var(--spacer-8) 12px; - } } .tab.inventory { @@ -60,7 +46,7 @@ display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; gap: 10px; - padding: var(--spacer-8) 16px var(--spacer-8) 16px; + padding: 10px 10px 0; .input { color: light-dark(@dark, @beige); @@ -71,6 +57,7 @@ .tab.notes.active { padding: 0; margin: 0; + margin-top: -10px; // will be removed once tab-navigation bottom margin is removed on all actor sheets scrollbar-gutter: unset; // Add padding around top level level prosemirrors used for note tabs @@ -79,7 +66,6 @@ .editor-content { scrollbar-gutter: stable; padding-right: @right-padding; - padding-bottom: 4px; } &.inactive { button.toggle { @@ -90,7 +76,7 @@ } } &.active { - padding: 8px 0 0 16px; + padding: 8px 0 4px 16px; } } diff --git a/styles/less/sheets/actors/adversary/effects.less b/styles/less/sheets/actors/adversary/effects.less index f489bee6..4aa44e51 100644 --- a/styles/less/sheets/actors/adversary/effects.less +++ b/styles/less/sheets/actors/adversary/effects.less @@ -7,8 +7,9 @@ display: flex; flex-direction: column; gap: 10px; - padding: 7px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + overflow-y: auto; + padding-bottom: 20px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/adversary/features.less b/styles/less/sheets/actors/adversary/features.less index 49289d36..447d050e 100644 --- a/styles/less/sheets/actors/adversary/features.less +++ b/styles/less/sheets/actors/adversary/features.less @@ -5,8 +5,12 @@ .application.sheet.daggerheart.actor.dh-style.adversary { .tab.features { .feature-section { - padding: 16px calc(16px - var(--scrollbar-width)) 4px 16px; - .stable-scroll-container(); + display: flex; + flex-direction: column; + gap: 10px; + overflow-y: auto; + padding-bottom: 20px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/adversary/sheet.less b/styles/less/sheets/actors/adversary/sheet.less index 1eb7d423..639af98b 100644 --- a/styles/less/sheets/actors/adversary/sheet.less +++ b/styles/less/sheets/actors/adversary/sheet.less @@ -30,9 +30,9 @@ grid-row: 2; grid-column: 2; &.active { + overflow: hidden; display: flex; flex-direction: column; - margin: 0 0 10px 0; } } } \ No newline at end of file diff --git a/styles/less/sheets/actors/character/biography.less b/styles/less/sheets/actors/character/biography.less index 9782a588..8548a2fb 100644 --- a/styles/less/sheets/actors/character/biography.less +++ b/styles/less/sheets/actors/character/biography.less @@ -8,14 +8,17 @@ display: flex; flex-direction: column; gap: 10px; - height: 100%; - padding: 12px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + height: 100%; + overflow-y: auto; + padding-top: 8px; + padding-bottom: 20px; + height: 100%; + .with-scroll-shadows(); } .characteristics-section { gap: 20px; - padding: 0 4px; + padding: 0 10px; } .biography-section { diff --git a/styles/less/sheets/actors/character/effects.less b/styles/less/sheets/actors/character/effects.less index 8fac301c..0ab1007d 100644 --- a/styles/less/sheets/actors/character/effects.less +++ b/styles/less/sheets/actors/character/effects.less @@ -8,8 +8,9 @@ display: flex; flex-direction: column; gap: 10px; - padding: 7px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + overflow-y: auto; + padding-bottom: 20px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/character/features.less b/styles/less/sheets/actors/character/features.less index fcde3e38..52b41826 100644 --- a/styles/less/sheets/actors/character/features.less +++ b/styles/less/sheets/actors/character/features.less @@ -8,8 +8,9 @@ display: flex; flex-direction: column; gap: 10px; - padding: 7px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + overflow-y: auto; + padding-bottom: 20px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/character/header.less b/styles/less/sheets/actors/character/header.less index 81345715..91b3545a 100644 --- a/styles/less/sheets/actors/character/header.less +++ b/styles/less/sheets/actors/character/header.less @@ -19,19 +19,16 @@ .application.sheet.daggerheart.actor.dh-style.character { .character-header-sheet { + padding: 0 15px; padding-top: var(--header-height); width: 100%; - > *:not(line-div, .tab-navigation) { - padding-left: 15px; - padding-right: 15px; - } - .name-row { display: flex; gap: 6px; align-items: start; justify-content: space-between; + padding: 0; padding-top: 5px; flex: 1; @@ -103,8 +100,8 @@ .character-details { display: flex; justify-content: space-between; - margin-top: 5px; - margin-bottom: 10px; + padding: 5px 0; + margin-bottom: 8px; font-size: var(--font-size-12); color: @color-text-emphatic; @@ -133,6 +130,7 @@ .character-row { display: flex; align-items: center; + padding: 0; margin-bottom: 12px; .resource-section { @@ -220,11 +218,12 @@ .character-traits { display: flex; + padding: 0; margin-bottom: 15px; justify-content: space-between; max-width: 38.5rem; gap: 0.5rem; - margin-left: 0.5rem; + padding-left: 0.5rem; .trait { cursor: pointer; @@ -326,9 +325,5 @@ } } } - - .tab-navigation button[data-action="openSettings"] { - margin-right: 12px; - } } } diff --git a/styles/less/sheets/actors/character/index.less b/styles/less/sheets/actors/character/index.less index f196d5bf..edefe0a1 100644 --- a/styles/less/sheets/actors/character/index.less +++ b/styles/less/sheets/actors/character/index.less @@ -1,8 +1,8 @@ -@import './sheet.less'; @import './biography.less'; @import './effects.less'; @import './features.less'; @import './header.less'; @import './inventory.less'; @import './loadout.less'; +@import './sheet.less'; @import './sidebar.less'; diff --git a/styles/less/sheets/actors/character/inventory.less b/styles/less/sheets/actors/character/inventory.less index ce7a8cdb..fcfbbee9 100644 --- a/styles/less/sheets/actors/character/inventory.less +++ b/styles/less/sheets/actors/character/inventory.less @@ -7,9 +7,11 @@ .items-section { display: flex; flex-direction: column; - gap: 10px; - padding: 8px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + gap: 10px; + overflow-y: auto; + margin-top: 20px; + padding-bottom: 20px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/character/loadout.less b/styles/less/sheets/actors/character/loadout.less index cb1baaa6..fa3e0176 100644 --- a/styles/less/sheets/actors/character/loadout.less +++ b/styles/less/sheets/actors/character/loadout.less @@ -50,8 +50,11 @@ display: flex; flex-direction: column; gap: 10px; - padding: 8px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + height: 100%; + overflow-y: auto; + margin-top: 20px; + padding-bottom: 20px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/character/sheet.less b/styles/less/sheets/actors/character/sheet.less index 43401b19..68792c99 100644 --- a/styles/less/sheets/actors/character/sheet.less +++ b/styles/less/sheets/actors/character/sheet.less @@ -30,7 +30,7 @@ &.active { display: flex; flex-direction: column; - margin: 0 0 10px 0; + overflow: hidden; } } } diff --git a/styles/less/sheets/actors/companion/details.less b/styles/less/sheets/actors/companion/details.less index e10e7680..2e43cac4 100644 --- a/styles/less/sheets/actors/companion/details.less +++ b/styles/less/sheets/actors/companion/details.less @@ -1,10 +1,7 @@ @import '../../../utils/colors.less'; @import '../../../utils/fonts.less'; -.application.sheet.daggerheart.actor.dh-style.companion .tab.details.active { - padding: 12px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); - +.application.sheet.daggerheart.actor.dh-style.companion { .partner-section, .attack-section, .experience-list { diff --git a/styles/less/sheets/actors/companion/effects.less b/styles/less/sheets/actors/companion/effects.less index ffe66da8..c0cac669 100644 --- a/styles/less/sheets/actors/companion/effects.less +++ b/styles/less/sheets/actors/companion/effects.less @@ -6,8 +6,9 @@ display: flex; flex-direction: column; gap: 10px; - padding: 7px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + overflow-y: auto; + padding-bottom: 20px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/environment/features.less b/styles/less/sheets/actors/environment/features.less index c6fe3750..84cf26f8 100644 --- a/styles/less/sheets/actors/environment/features.less +++ b/styles/less/sheets/actors/environment/features.less @@ -5,8 +5,12 @@ .application.sheet.daggerheart.actor.dh-style.environment { .tab.features { .feature-section { - padding: 16px calc(16px - var(--scrollbar-width)) 4px 16px; - .stable-scroll-container(); + display: flex; + flex-direction: column; + gap: 10px; + overflow-y: auto; + padding-bottom: 4px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/environment/index.less b/styles/less/sheets/actors/environment/index.less index df7e6fc2..211c8e60 100644 --- a/styles/less/sheets/actors/environment/index.less +++ b/styles/less/sheets/actors/environment/index.less @@ -1,4 +1,4 @@ -@import './sheet.less'; @import './features.less'; @import './header.less'; @import './potentialAdversaries.less'; +@import './sheet.less'; diff --git a/styles/less/sheets/actors/environment/potentialAdversaries.less b/styles/less/sheets/actors/environment/potentialAdversaries.less index 07dc5f92..f112c0d2 100644 --- a/styles/less/sheets/actors/environment/potentialAdversaries.less +++ b/styles/less/sheets/actors/environment/potentialAdversaries.less @@ -6,8 +6,9 @@ display: flex; flex-direction: column; gap: 10px; - padding: 7px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + overflow-y: auto; + padding-bottom: 4px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/environment/sheet.less b/styles/less/sheets/actors/environment/sheet.less index ef9d542a..2d9cc188 100644 --- a/styles/less/sheets/actors/environment/sheet.less +++ b/styles/less/sheets/actors/environment/sheet.less @@ -14,7 +14,9 @@ .application.sheet.daggerheart.actor.dh-style.environment { .tab { + flex: 1; overflow-y: auto; + &.active { overflow: hidden; display: flex; diff --git a/styles/less/sheets/actors/npc/features.less b/styles/less/sheets/actors/npc/features.less index f68df8a8..a579d9f8 100644 --- a/styles/less/sheets/actors/npc/features.less +++ b/styles/less/sheets/actors/npc/features.less @@ -7,8 +7,12 @@ } .feature-section { - padding: 16px calc(16px - var(--scrollbar-width)) 4px 16px; - .stable-scroll-container(); + display: flex; + flex-direction: column; + gap: 10px; + overflow-y: auto; + padding-bottom: 4px; + .with-scroll-shadows(); } } } diff --git a/styles/less/sheets/actors/party/party-members.less b/styles/less/sheets/actors/party/party-members.less index ca384322..3d882345 100644 --- a/styles/less/sheets/actors/party/party-members.less +++ b/styles/less/sheets/actors/party/party-members.less @@ -3,8 +3,7 @@ @import '../../../utils/mixin.less'; .application.sheet.daggerheart.actor.dh-style.party .tab.partyMembers { - padding: 12px calc(12px - var(--scrollbar-width)) 4px 12px; - .stable-scroll-container(); + overflow: auto; .actions-section { display: flex; diff --git a/styles/less/sheets/actors/party/sheet.less b/styles/less/sheets/actors/party/sheet.less index bf589696..d24c712c 100644 --- a/styles/less/sheets/actors/party/sheet.less +++ b/styles/less/sheets/actors/party/sheet.less @@ -17,8 +17,15 @@ }); .application.sheet.daggerheart.actor.dh-style.party { - .tab.active { - display: flex; - flex-direction: column; + .tab { + flex: 1; + overflow-y: auto; + scrollbar-gutter: stable; + + &.active { + overflow: auto; + display: flex; + flex-direction: column; + } } } diff --git a/styles/less/utils/mixin.less b/styles/less/utils/mixin.less index 2ce85166..e2ef85ef 100644 --- a/styles/less/utils/mixin.less +++ b/styles/less/utils/mixin.less @@ -174,10 +174,10 @@ --fade-start: 0; } 10%, 100% { - --fade-start: 14px; + --fade-start: 12px; } 0%, 90% { - --fade-end: 14px; + --fade-end: 12px; } 100% { --fade-end: 0; @@ -198,9 +198,3 @@ transparent 100% ); } - -.stable-scroll-container() { - overflow-y: auto; - scrollbar-gutter: stable; - .with-scroll-shadows(); -} \ No newline at end of file diff --git a/system.json b/system.json index d754b8bf..0ecc2e75 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "2.5.0", + "version": "2.4.2", "compatibility": { "minimum": "14.364", "verified": "14.364", @@ -10,7 +10,7 @@ }, "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.5.0/system.zip", + "download": "https://github.com/Foundryborne/daggerheart/releases/download/2.4.2/system.zip", "authors": [ { "name": "WBHarry" diff --git a/templates/sheets/actors/adversary/features.hbs b/templates/sheets/actors/adversary/features.hbs index 05e95737..3b495e74 100644 --- a/templates/sheets/actors/adversary/features.hbs +++ b/templates/sheets/actors/adversary/features.hbs @@ -1,15 +1,14 @@
-
- {{#each @root.features as |item|}} - {{> "daggerheart.inventory-item" - item=item - type="feature" - actorType=@root.document.type - hideContextMenu=true - hideModifyControls=true - showActions=@root.editable - }} - {{/each}} +
+ {{> 'daggerheart.inventory-items' + title=tabs.features.label + type='feature' + collection=@root.features + hideContextMenu=true + hideModifyControls=true + canCreate=@root.editable + showActions=@root.editable + }}
\ No newline at end of file diff --git a/templates/sheets/actors/character/features.hbs b/templates/sheets/actors/character/features.hbs index c96ab623..b2760900 100644 --- a/templates/sheets/actors/character/features.hbs +++ b/templates/sheets/actors/character/features.hbs @@ -1,26 +1,26 @@ -
-
- {{#each document.system.sheetLists as |category|}} - {{#if (eq category.type 'feature' )}} - {{> 'daggerheart.inventory-items' - title=category.title - type='feature' - actorType='character' - collection=category.values - canCreate=@root.editable - showActions=@root.editable - }} - {{else if category.values}} - {{> 'daggerheart.inventory-items' - title=category.title - type='feature' - actorType='character' - collection=category.values - canCreate=false - showActions=@root.editable - }} - {{/if}} - {{/each}} -
+
+
+ {{#each document.system.sheetLists as |category|}} + {{#if (eq category.type 'feature' )}} + {{> 'daggerheart.inventory-items' + title=category.title + type='feature' + actorType='character' + collection=category.values + canCreate=@root.editable + showActions=@root.editable + }} + {{else if category.values}} + {{> 'daggerheart.inventory-items' + title=category.title + type='feature' + actorType='character' + collection=category.values + canCreate=false + showActions=@root.editable + }} + {{/if}} + {{/each}} +
\ No newline at end of file diff --git a/templates/sheets/actors/character/header.hbs b/templates/sheets/actors/character/header.hbs index a40c336a..459911af 100644 --- a/templates/sheets/actors/character/header.hbs +++ b/templates/sheets/actors/character/header.hbs @@ -1,163 +1,165 @@ -
- -
-

{{source.name}}

-
-

- {{#if @root.editable}} - {{#if document.system.needsCharacterSetup}} - - {{else if document.system.levelData.canLevelUp}} - - {{/if}} - {{/if}} - {{#unless document.system.needsCharacterSetup}} - {{localize 'DAGGERHEART.GENERAL.level'}} - - {{/unless}} -

-
-
-
-
- {{#if document.system.class.value}} - {{document.system.class.value.name}} - {{else}} - {{localize 'TYPES.Item.class'}} - {{/if}} - - {{#if document.system.class.subclass}} - {{document.system.class.subclass.name}} - {{else}} - {{localize 'TYPES.Item.subclass'}} - {{/if}} - - {{#if document.system.community}} - {{document.system.community.name}} - {{else}} - {{localize 'TYPES.Item.community'}} - {{/if}} - - {{#if document.system.ancestry}} - {{document.system.ancestry.name}} - {{else}} - {{localize 'TYPES.Item.ancestry'}} - {{/if}} -
- - {{#if (or document.system.multiclass.value document.system.multiclass.subclass)}} -
- {{#if document.system.multiclass.value}} - {{document.system.multiclass.value.name}} - {{else}} - {{localize 'DAGGERHEART.GENERAL.multiclass'}} - {{/if}} - - {{#if document.system.multiclass.subclass}} - {{document.system.multiclass.subclass.name}} - {{else}} - {{localize 'TYPES.Item.subclass'}} - {{/if}} -
- {{/if}} -
- -
-
-
-

{{localize "DAGGERHEART.GENERAL.hope"}}

- {{#times document.system.resources.hope.max}} - - {{#if (gte ../document.system.resources.hope.value (add this 1))}} - - {{else}} - - {{/if}} - - {{/times}} - {{#times document.system.scars}} - - - - {{/times}} - {{#if hasExtraResources}}{{/if}} -
-
- {{#if document.system.class.value}} -
- {{#each document.system.domainData as |data|}} -
- -
- {{/each}} -
- {{/if}} -
- {{#if document.parties.size}} - - {{/if}} - {{#if @root.editable}} - - - {{/if}} -
-
- -
- {{#each this.attributes as |attribute key|}} -
-
-
- {{attribute.label}} -
-
- - - - -
- {{#if (gt attribute.value 0)}} - +{{attribute.value}} - {{else}} - {{attribute.value}} - {{/if}} -
- {{#if isSpellcasting}} -
- -
- {{/if}} -
-
- {{/each}} -
- - {{#> 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }} - - {{/'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}} +
+ +
+

{{source.name}}

+
+

+ {{#if @root.editable}} + {{#if document.system.needsCharacterSetup}} + + {{else if document.system.levelData.canLevelUp}} + + {{/if}} + {{/if}} + {{#unless document.system.needsCharacterSetup}} + {{localize 'DAGGERHEART.GENERAL.level'}} + + {{/unless}} +

+
+
+
+
+ {{#if document.system.class.value}} + {{document.system.class.value.name}} + {{else}} + {{localize 'TYPES.Item.class'}} + {{/if}} + + {{#if document.system.class.subclass}} + {{document.system.class.subclass.name}} + {{else}} + {{localize 'TYPES.Item.subclass'}} + {{/if}} + + {{#if document.system.community}} + {{document.system.community.name}} + {{else}} + {{localize 'TYPES.Item.community'}} + {{/if}} + + {{#if document.system.ancestry}} + {{document.system.ancestry.name}} + {{else}} + {{localize 'TYPES.Item.ancestry'}} + {{/if}} +
+ + {{#if (or document.system.multiclass.value document.system.multiclass.subclass)}} +
+ {{#if document.system.multiclass.value}} + {{document.system.multiclass.value.name}} + {{else}} + {{localize 'DAGGERHEART.GENERAL.multiclass'}} + {{/if}} + + {{#if document.system.multiclass.subclass}} + {{document.system.multiclass.subclass.name}} + {{else}} + {{localize 'TYPES.Item.subclass'}} + {{/if}} +
+ {{/if}} + + +
+ +
+
+
+

{{localize "DAGGERHEART.GENERAL.hope"}}

+ {{#times document.system.resources.hope.max}} + + {{#if (gte ../document.system.resources.hope.value (add this 1))}} + + {{else}} + + {{/if}} + + {{/times}} + {{#times document.system.scars}} + + + + {{/times}} + {{#if hasExtraResources}}{{/if}} +
+
+ {{#if document.system.class.value}} +
+ {{#each document.system.domainData as |data|}} +
+ +
+ {{/each}} +
+ {{/if}} +
+ {{#if document.parties.size}} + + {{/if}} + {{#if @root.editable}} + + + {{/if}} +
+
+ +
+ {{#each this.attributes as |attribute key|}} +
+
+
+ {{attribute.label}} +
+
+ + + + +
+ {{#if (gt attribute.value 0)}} + +{{attribute.value}} + {{else}} + {{attribute.value}} + {{/if}} +
+ {{#if isSpellcasting}} +
+ +
+ {{/if}} +
+
+ {{/each}} +
+ + {{#> 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }} + + {{/'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
\ No newline at end of file diff --git a/templates/sheets/actors/character/inventory.hbs b/templates/sheets/actors/character/inventory.hbs index 61f98ab5..c3ddb0ad 100644 --- a/templates/sheets/actors/character/inventory.hbs +++ b/templates/sheets/actors/character/inventory.hbs @@ -23,6 +23,7 @@ collection=@root.inventory.weapons isGlassy=true canCreate=@root.editable + hideResources=true }} {{> 'daggerheart.inventory-items' title='TYPES.Item.armor' diff --git a/templates/sheets/actors/environment/features.hbs b/templates/sheets/actors/environment/features.hbs index 85fa7066..35fcb038 100644 --- a/templates/sheets/actors/environment/features.hbs +++ b/templates/sheets/actors/environment/features.hbs @@ -3,16 +3,15 @@ data-tab='{{tabs.features.id}}' data-group='{{tabs.features.group}}' > -
- {{#each @root.features as |item|}} - {{> "daggerheart.inventory-item" - item=item - type="feature" - actorType=@root.document.type - hideContextMenu=true - hideModifyControls=true - showActions=@root.editable - }} - {{/each}} +
+ {{> 'daggerheart.inventory-items' + title=tabs.features.label + type='feature' + collection=@root.features + hideContextMenu=true + hideModifyControls=true + canCreate=@root.editable + showActions=@root.editable + }}
\ No newline at end of file diff --git a/templates/sheets/actors/npc/features.hbs b/templates/sheets/actors/npc/features.hbs index 05e95737..3b495e74 100644 --- a/templates/sheets/actors/npc/features.hbs +++ b/templates/sheets/actors/npc/features.hbs @@ -1,15 +1,14 @@
-
- {{#each @root.features as |item|}} - {{> "daggerheart.inventory-item" - item=item - type="feature" - actorType=@root.document.type - hideContextMenu=true - hideModifyControls=true - showActions=@root.editable - }} - {{/each}} +
+ {{> 'daggerheart.inventory-items' + title=tabs.features.label + type='feature' + collection=@root.features + hideContextMenu=true + hideModifyControls=true + canCreate=@root.editable + showActions=@root.editable + }}
\ No newline at end of file diff --git a/templates/sheets/items/weapon/settings.hbs b/templates/sheets/items/weapon/settings.hbs index c9805e7c..ef47b323 100644 --- a/templates/sheets/items/weapon/settings.hbs +++ b/templates/sheets/items/weapon/settings.hbs @@ -45,5 +45,4 @@ {{localize "TYPES.Item.feature"}} - {{> "systems/daggerheart/templates/sheets/global/partials/resource-section/resource-section.hbs" }} \ No newline at end of file