This commit is contained in:
WBHarry 2026-01-10 14:48:45 +00:00 committed by GitHub
commit aa159444f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 129 additions and 19 deletions

View file

@ -211,7 +211,7 @@ export default function DHApplicationMixin(Base) {
const step = event.key === 'ArrowUp' ? 1 : event.key === 'ArrowDown' ? -1 : 0; const step = event.key === 'ArrowUp' ? 1 : event.key === 'ArrowDown' ? -1 : 0;
if (step !== 0) { if (step !== 0) {
handleUpdate(step); handleUpdate(step);
deltaInput.dispatchEvent(new Event("change", { bubbles: true })); deltaInput.dispatchEvent(new Event('change', { bubbles: true }));
} }
}); });
@ -222,7 +222,7 @@ export default function DHApplicationMixin(Base) {
if (deltaInput === document.activeElement) { if (deltaInput === document.activeElement) {
event.preventDefault(); event.preventDefault();
handleUpdate(Math.sign(-1 * event.deltaY)); handleUpdate(Math.sign(-1 * event.deltaY));
deltaInput.dispatchEvent(new Event("change", { bubbles: true })); deltaInput.dispatchEvent(new Event('change', { bubbles: true }));
} }
}, },
{ passive: false } { passive: false }
@ -236,7 +236,7 @@ export default function DHApplicationMixin(Base) {
// Handle contenteditable // Handle contenteditable
for (const input of htmlElement.querySelectorAll('[contenteditable][data-property]')) { for (const input of htmlElement.querySelectorAll('[contenteditable][data-property]')) {
const property = input.dataset.property; const property = input.dataset.property;
input.addEventListener("blur", () => { input.addEventListener('blur', () => {
const selection = document.getSelection(); const selection = document.getSelection();
if (input.contains(selection.anchorNode)) { if (input.contains(selection.anchorNode)) {
selection.empty(); selection.empty();
@ -244,12 +244,12 @@ export default function DHApplicationMixin(Base) {
this.document.update({ [property]: input.textContent }); this.document.update({ [property]: input.textContent });
}); });
input.addEventListener("keydown", event => { input.addEventListener('keydown', event => {
if (event.key === "Enter") input.blur(); if (event.key === 'Enter') input.blur();
}); });
// Chrome sometimes add <br>, which aren't a problem for the value but are for the placeholder // Chrome sometimes add <br>, which aren't a problem for the value but are for the placeholder
input.addEventListener("input", () => input.querySelectorAll("br").forEach((i) => i.remove())); input.addEventListener('input', () => input.querySelectorAll('br').forEach(i => i.remove()));
} }
} }
@ -585,7 +585,9 @@ export default function DHApplicationMixin(Base) {
if (!doc || !descriptionElement) continue; if (!doc || !descriptionElement) continue;
// localize the description (idk if it's still necessary) // localize the description (idk if it's still necessary)
const description = game.i18n.localize(doc.system?.description ?? doc.description); const description = doc.system?.getEnrichedDescription
? await doc.system.getEnrichedDescription()
: game.i18n.localize(doc.system?.description ?? doc.description);
// Enrich the description and attach it; // Enrich the description and attach it;
const isAction = doc.documentName === 'Action'; const isAction = doc.documentName === 'Action';
@ -736,7 +738,7 @@ export default function DHApplicationMixin(Base) {
}; };
if (inVault) data['system.inVault'] = true; if (inVault) data['system.inVault'] = true;
if (disabled) data.disabled = true; if (disabled) data.disabled = true;
if (type === "domainCard" && parent?.system.domains?.length) { if (type === 'domainCard' && parent?.system.domains?.length) {
data.system.domain = parent.system.domains[0]; data.system.domain = parent.system.domains[0];
} }

View file

@ -76,15 +76,11 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
/**@inheritdoc */ /**@inheritdoc */
async _preparePartContext(partId, context, options) { async _preparePartContext(partId, context, options) {
await super._preparePartContext(partId, context, options); await super._preparePartContext(partId, context, options);
const { TextEditor } = foundry.applications.ux;
switch (partId) { switch (partId) {
case 'description': case 'description':
const value = foundry.utils.getProperty(this.document, 'system.description') ?? ''; context.enrichedDescription = await this.document.system.getEnrichedDescription({
context.enrichedDescription = await TextEditor.enrichHTML(value, { headerStyle: 'large'
relativeTo: this.item,
rollData: this.item.getRollData(),
secrets: this.item.isOwner
}); });
break; break;
case 'effects': case 'effects':

View file

@ -54,6 +54,22 @@ export default class DHArmor extends AttachableItem {
); );
} }
/**@inheritdoc */
async getDescriptionData(options = {}) {
const baseDescription = await super.getDescriptionData();
const allFeatures = CONFIG.DH.ITEM.allArmorFeatures();
const features = this.armorFeatures.map(x => allFeatures[x.value]);
if (!features.length) return baseDescription;
const prepend = await foundry.applications.handlebars.renderTemplate(
'systems/daggerheart/templates/sheets/items/armor/description.hbs',
{ features, headerStyle: options.headerStyle }
);
const mainDescription = baseDescription ? `\n<hr>\n${baseDescription}` : '';
return `${prepend}${mainDescription}`;
}
/**@inheritdoc */ /**@inheritdoc */
async _preUpdate(changes, options, user) { async _preUpdate(changes, options, user) {
const allowed = await super._preUpdate(changes, options, user); const allowed = await super._preUpdate(changes, options, user);

View file

@ -8,7 +8,7 @@
* @property {boolean} isInventoryItem- Indicates whether items of this type is a Inventory Item * @property {boolean} isInventoryItem- Indicates whether items of this type is a Inventory Item
*/ */
import { addLinkedItemsDiff, createScrollText, getScrollTextData, updateLinkedItemApps } from '../../helpers/utils.mjs'; import { addLinkedItemsDiff, getScrollTextData, updateLinkedItemApps } from '../../helpers/utils.mjs';
import { ActionsField } from '../fields/actionField.mjs'; import { ActionsField } from '../fields/actionField.mjs';
import FormulaField from '../fields/formulaField.mjs'; import FormulaField from '../fields/formulaField.mjs';
@ -124,6 +124,31 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
return [source, page ? `pg ${page}.` : null].filter(x => x).join('. '); return [source, page ? `pg ${page}.` : null].filter(x => x).join('. ');
} }
/**
* Augments the description for the item with type specific info to display. Implemented in applicable item subtypes.
* @param {object} [options] - Options that modify the styling of the rendered template. { headerStyle: undefined|'none'|'large' }
* @returns {string}
*/
async getDescriptionData(_options) {
return this.description;
}
/**
* Gets the enriched and augmented description for the item.
* @param {object} [options] - Options that modify the styling of the rendered template. { headerStyle: undefined|'none'|'large' }
* @returns {string}
*/
async getEnrichedDescription(options) {
if (!this.metadata.hasDescription) return '';
const description = await this.getDescriptionData(options);
return await foundry.applications.ux.TextEditor.implementation.enrichHTML(description, {
relativeTo: this,
rollData: this.getRollData(),
secrets: this.isOwner
});
}
/** /**
* Obtain a data object used to evaluate any dice rolls associated with this Item Type * Obtain a data object used to evaluate any dice rolls associated with this Item Type
* @param {object} [options] - Options which modify the getRollData method. * @param {object} [options] - Options which modify the getRollData method.

View file

@ -110,6 +110,22 @@ export default class DHWeapon extends AttachableItem {
); );
} }
/**@inheritdoc */
async getDescriptionData(options = {}) {
const baseDescription = await super.getDescriptionData();
const allFeatures = CONFIG.DH.ITEM.allWeaponFeatures();
const features = this.weaponFeatures.map(x => allFeatures[x.value]);
if (!features.length) return baseDescription;
const prepend = await foundry.applications.handlebars.renderTemplate(
'systems/daggerheart/templates/sheets/items/weapon/description.hbs',
{ features, headerStyle: options.headerStyle }
);
const mainDescription = baseDescription ? `\n<hr>\n${baseDescription}` : '';
return `${prepend}${mainDescription}`;
}
prepareDerivedData() { prepareDerivedData() {
this.attack.roll.trait = this.rules.attack.roll.trait ?? this.attack.roll.trait; this.attack.roll.trait = this.rules.attack.roll.trait ?? this.attack.roll.trait;
} }

View file

@ -220,12 +220,16 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti
for (const [index, itemValue] of pathValue.entries()) { for (const [index, itemValue] of pathValue.entries()) {
const itemIsAction = itemValue instanceof game.system.api.models.actions.actionsTypes.base; const itemIsAction = itemValue instanceof game.system.api.models.actions.actionsTypes.base;
const value = itemIsAction || !itemValue?.item ? itemValue : itemValue.item; const value = itemIsAction || !itemValue?.item ? itemValue : itemValue.item;
const enrichedValue = await TextEditor.enrichHTML(value.system?.description ?? value.description); const enrichedValue =
(await value.system?.getEnrichedDescription?.({ headerStyle: 'none' })) ??
(await TextEditor.enrichHTML(value.system?.description ?? value.description));
if (itemIsAction) value.enrichedDescription = enrichedValue; if (itemIsAction) value.enrichedDescription = enrichedValue;
else foundry.utils.setProperty(item, `${basePath}.${index}.enrichedDescription`, enrichedValue); else foundry.utils.setProperty(item, `${basePath}.${index}.enrichedDescription`, enrichedValue);
} }
} else { } else {
const enrichedValue = await TextEditor.enrichHTML(pathValue); const enrichedValue =
(await item.system?.getEnrichedDescription?.({ headerStyle: 'none' })) ??
(await TextEditor.enrichHTML(pathValue));
foundry.utils.setProperty( foundry.utils.setProperty(
item, item,
`${data.path ? `${data.path}.` : ''}enriched${data.name.capitalize()}`, `${data.path ? `${data.path}.` : ''}enriched${data.name.capitalize()}`,

View file

@ -211,6 +211,18 @@
ul { ul {
list-style: disc; list-style: disc;
} }
.feature-descriptions {
.features-header {
font-size: 14px;
font-weight: bold;
text-decoration: underline;
&.large {
font-size: 18px;
}
}
}
} }
} }
.item-resources { .item-resources {

View file

@ -10,4 +10,16 @@
font-family: @font-body; font-family: @font-body;
color: light-dark(@chat-blue-bg, @beige-50); color: light-dark(@chat-blue-bg, @beige-50);
} }
.feature-descriptions {
.features-header {
font-size: 14px;
font-weight: bold;
text-decoration: underline;
&.large {
font-size: 18px;
}
}
}
} }

View file

@ -11,7 +11,7 @@ aside[role='tooltip']:has(div.daggerheart.dh-style.tooltip.card-style) {
width: 18rem; width: 18rem;
background-image: url('../assets/parchments/dh-parchment-dark.png'); background-image: url('../assets/parchments/dh-parchment-dark.png');
outline: 1px solid light-dark(@dark-80, @beige-80); outline: 1px solid light-dark(@dark-80, @beige-80);
box-shadow: 0 0 25px rgba(0, 0, 0, 0.80); box-shadow: 0 0 25px rgba(0, 0, 0, 0.8);
.tooltip-title { .tooltip-title {
font-size: var(--font-size-20); font-size: var(--font-size-20);
@ -235,7 +235,6 @@ aside[role='tooltip'].locked-tooltip:has(div.daggerheart.dh-style.tooltip.card-s
.theme-light aside[role='tooltip'].locked-tooltip:has(div.daggerheart.dh-style.tooltip) { .theme-light aside[role='tooltip'].locked-tooltip:has(div.daggerheart.dh-style.tooltip) {
box-shadow: 0 0 25px @dark-blue-90; box-shadow: 0 0 25px @dark-blue-90;
outline: 1px solid light-dark(@dark-blue, @golden); outline: 1px solid light-dark(@dark-blue, @golden);
} }
#tooltip, #tooltip,
@ -283,6 +282,18 @@ aside[role='tooltip'].locked-tooltip:has(div.daggerheart.dh-style.tooltip.card-s
.tooltip-description { .tooltip-description {
font-style: italic; font-style: italic;
text-align: start; text-align: start;
.feature-descriptions {
.features-header {
font-size: 14px;
font-weight: bold;
text-decoration: underline;
&.large {
font-size: 18px;
}
}
}
} }
.simple-info { .simple-info {

View file

@ -0,0 +1,8 @@
<div class="feature-descriptions">
{{#unless (eq headerStyle 'none')}}
<div class="features-header {{#if (eq headerStyle 'large')}}large{{/if}}">{{localize "DAGGERHEART.SETTINGS.Homebrew.itemFeatures"}}</div>
{{/unless}}
{{#each features as | feature |}}
<div><strong>{{localize feature.label}}</strong>: {{{localize feature.description}}}</div>
{{/each}}
</div>

View file

@ -0,0 +1,8 @@
<div class="feature-descriptions">
{{#unless (eq headerStyle 'none')}}
<div class="features-header {{#if (eq headerStyle 'large')}}large{{/if}}">{{localize "DAGGERHEART.SETTINGS.Homebrew.itemFeatures"}}</div>
{{/unless}}
{{#each features as | feature |}}
<div><strong>{{localize feature.label}}</strong>: {{{localize feature.description}}}</div>
{{/each}}
</div>