merged with main

This commit is contained in:
WBHarry 2025-06-29 23:05:14 +02:00
commit 0aa08deaa3
41 changed files with 805 additions and 446 deletions

View file

@ -46,19 +46,18 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
switch (partId) {
case 'description':
const value = foundry.utils.getProperty(this.document, "system.description") ?? "";
const value = foundry.utils.getProperty(this.document, 'system.description') ?? '';
context.enrichedDescription = await TextEditor.enrichHTML(value, {
relativeTo: this.item,
rollData: this.item.getRollData(),
secrets: this.item.isOwner
})
});
break;
}
return context;
}
/* -------------------------------------------- */
/* Application Clicks Actions */
/* -------------------------------------------- */
@ -70,26 +69,18 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
*/
static async selectActionType() {
const content = await foundry.applications.handlebars.renderTemplate(
'systems/daggerheart/templates/views/actionType.hbs',
{ types: SYSTEM.ACTIONS.actionTypes }
),
title = 'Select Action Type', //useless var
type = 'form',
data = {}; //useless var
//TODO: use DialogV2
return Dialog.prompt({
title,
label: title,
'systems/daggerheart/templates/views/actionType.hbs',
{ types: SYSTEM.ACTIONS.actionTypes }
),
title = 'Select Action Type';
return foundry.applications.api.DialogV2.prompt({
window: { title },
content,
type, //this prop is useless
callback: html => {
const form = html[0].querySelector('form'),
fd = new foundry.applications.ux.FormDataExtended(form);
foundry.utils.mergeObject(data, fd.object, { inplace: true });
// if (!data.name?.trim()) data.name = game.i18n.localize(SYSTEM.ACTIONS.actionTypes[data.type].name);
return data;
},
rejectClose: false
ok: {
label: title,
callback: (event, button, dialog) => button.form.elements.type.value
}
});
}
@ -100,13 +91,14 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
*/
static async #addAction(_event, _button) {
const actionType = await DHBaseItemSheet.selectActionType();
if (!actionType) return;
try {
const cls = actionsTypes[actionType?.type] ?? actionsTypes.attack,
const cls = actionsTypes[actionType] ?? actionsTypes.attack,
action = new cls(
{
_id: foundry.utils.randomID(),
type: actionType.type,
name: game.i18n.localize(SYSTEM.ACTIONS.actionTypes[actionType.type].name),
type: actionType,
name: game.i18n.localize(SYSTEM.ACTIONS.actionTypes[actionType].name),
...cls.getSourceConfig(this.document)
},
{
@ -141,9 +133,7 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
event.stopPropagation();
const actionIndex = button.closest('[data-index]').dataset.index;
await this.document.update({
'system.actions': this.document.system.actions.filter(
(_, index) => index !== Number.parseInt(actionIndex)
)
'system.actions': this.document.system.actions.filter((_, index) => index !== Number.parseInt(actionIndex))
});
}
}

View file

@ -56,7 +56,6 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
resizable: true
},
form: {
handler: this.updateForm,
submitOnChange: true,
closeOnSubmit: false
},
@ -218,6 +217,15 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
this._createContextMenues();
}
/** @inheritDoc */
async _onRender(context, options) {
await super._onRender(context, options);
this._createSearchFilter();
}
/* -------------------------------------------- */
_createContextMenues() {
const allOptions = {
useItem: {
@ -332,12 +340,123 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
return acc;
}, {});
context.inventory = {
currency: {
title: game.i18n.localize('DAGGERHEART.Sheets.PC.Gold.Title'),
coins: game.i18n.localize('DAGGERHEART.Sheets.PC.Gold.Coins'),
handfulls: game.i18n.localize('DAGGERHEART.Sheets.PC.Gold.Handfulls'),
bags: game.i18n.localize('DAGGERHEART.Sheets.PC.Gold.Bags'),
chests: game.i18n.localize('DAGGERHEART.Sheets.PC.Gold.Chests')
}
};
const homebrewCurrency = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Homebrew).currency;
if (homebrewCurrency.enabled) {
context.inventory.currency = homebrewCurrency;
}
if (context.inventory.length === 0) {
context.inventory = Array(1).fill(Array(5).fill([]));
}
return context;
}
static async updateForm(event, _, formData) {
await this.document.update(formData.object);
this.render();
/* -------------------------------------------- */
/* Search Filter */
/* -------------------------------------------- */
/**
* The currently active search filter.
* @type {foundry.applications.ux.SearchFilter}
*/
#search = {};
/**
* Track which item IDs are currently displayed due to a search filter.
* @type {{ inventory: Set<string>, loadout: Set<string> }}
*/
#filteredItems = {
inventory: new Set(),
loadout: new Set()
};
/**
* Create and initialize search filter instances for the inventory and loadout sections.
*
* Sets up two {@link foundry.applications.ux.SearchFilter} instances:
* - One for the inventory, which filters items in the inventory grid.
* - One for the loadout, which filters items in the loadout/card grid.
* @private
*/
_createSearchFilter() {
//Filters could be a application option if needed
const filters = [
{
key: 'inventory',
input: 'input[type="search"].search-inventory',
content: '[data-application-part="inventory"] .items-section',
callback: this._onSearchFilterInventory.bind(this)
},
{
key: 'loadout',
input: 'input[type="search"].search-loadout',
content: '[data-application-part="loadout"] .items-section',
callback: this._onSearchFilterCard.bind(this)
}
];
for (const { key, input, content, callback } of filters) {
const filter = new foundry.applications.ux.SearchFilter({
inputSelector: input,
contentSelector: content,
callback
});
filter.bind(this.element);
this.#search[key] = filter;
}
}
/**
* Handle invetory items search and filtering.
* @param {KeyboardEvent} event The keyboard input event.
* @param {string} query The input search string.
* @param {RegExp} rgx The regular expression query that should be matched against.
* @param {HTMLElement} html The container to filter items from.
* @protected
*/
_onSearchFilterInventory(event, query, rgx, html) {
this.#filteredItems.inventory.clear();
for (const ul of html.querySelectorAll('.items-list')) {
for (const li of ul.querySelectorAll('.inventory-item')) {
const item = this.document.items.get(li.dataset.itemId);
const match = !query || foundry.applications.ux.SearchFilter.testQuery(rgx, item.name);
if (match) this.#filteredItems.inventory.add(item.id);
li.hidden = !match;
}
}
}
/**
* Handle card items search and filtering.
* @param {KeyboardEvent} event The keyboard input event.
* @param {string} query The input search string.
* @param {RegExp} rgx The regular expression query that should be matched against.
* @param {HTMLElement} html The container to filter items from.
* @protected
*/
_onSearchFilterCard(event, query, rgx, html) {
this.#filteredItems.loadout.clear();
const elements = html.querySelectorAll('.items-list .inventory-item, .card-list .card-item');
for (const li of elements) {
const item = this.document.items.get(li.dataset.itemId);
const match = !query || foundry.applications.ux.SearchFilter.testQuery(rgx, item.name);
if (match) this.#filteredItems.loadout.add(item.id);
li.hidden = !match;
}
}
static async rollAttribute(event, button) {
@ -543,7 +662,7 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
}
static async makeDeathMove() {
if (this.document.system.resources.hitPoints.value === this.document.system.resources.hitPoints.max) {
if (this.document.system.resources.hitPoints.value >= this.document.system.resources.hitPoints.maxTotal) {
await new DhpDeathMove(this.document).render(true);
}
}