Fixed Weapon/Armor features. Fixed Feature actions

This commit is contained in:
WBHarry 2025-07-23 00:37:25 +02:00
parent 5243260b4d
commit 920ab3fd76
10 changed files with 84 additions and 63 deletions

View file

@ -82,7 +82,6 @@ export default function DHApplicationMixin(Base) {
deleteDoc: DHSheetV2.#deleteDoc, deleteDoc: DHSheetV2.#deleteDoc,
toChat: DHSheetV2.#toChat, toChat: DHSheetV2.#toChat,
useItem: DHSheetV2.#useItem, useItem: DHSheetV2.#useItem,
useAction: DHSheetV2.#useAction,
toggleEffect: DHSheetV2.#toggleEffect, toggleEffect: DHSheetV2.#toggleEffect,
toggleExtended: DHSheetV2.#toggleExtended toggleExtended: DHSheetV2.#toggleExtended
}, },
@ -378,9 +377,15 @@ export default function DHApplicationMixin(Base) {
static async #createDoc(event, target) { static async #createDoc(event, target) {
const { documentClass, type, inVault, disabled } = target.dataset; const { documentClass, type, inVault, disabled } = target.dataset;
const parentIsItem = this.document.documentName === 'Item'; const parentIsItem = this.document.documentName === 'Item';
const parent = parentIsItem && documentClass === 'Item' ? (type === 'action' ? this.document.system : null) : this.document; const parent =
parentIsItem && documentClass === 'Item'
? type === 'action'
? this.document.system
: null
: this.document;
const cls = type === 'action' ? game.system.api.models.actions.actionsTypes.base : getDocumentClass(documentClass); const cls =
type === 'action' ? game.system.api.models.actions.actionsTypes.base : getDocumentClass(documentClass);
const data = { const data = {
name: cls.defaultName({ type, parent }), name: cls.defaultName({ type, parent }),
type type
@ -436,15 +441,6 @@ export default function DHApplicationMixin(Base) {
await doc.use(event); await doc.use(event);
} }
/**
* Use a item
* @type {ApplicationClickAction}
*/
static async #useAction(event, target) {
const doc = getDocFromElement(target);
await action.use(event);
}
/** /**
* Toggle a ActiveEffect * Toggle a ActiveEffect
* @type {ApplicationClickAction} * @type {ApplicationClickAction}

View file

@ -294,7 +294,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
const action = message.system.actions[Number.parseInt(event.currentTarget.dataset.index)]; const action = message.system.actions[Number.parseInt(event.currentTarget.dataset.index)];
const actor = game.actors.get(message.system.source.actor); const actor = game.actors.get(message.system.source.actor);
await actor.useAction(action); await actor.use(action);
}; };
actionUseButton = async (event, message) => { actionUseButton = async (event, message) => {

View file

@ -1,3 +1,4 @@
export { ActionCollection } from './actionField.mjs';
export { default as FormulaField } from './formulaField.mjs'; export { default as FormulaField } from './formulaField.mjs';
export { default as ForeignDocumentUUIDField } from './foreignDocumentUUIDField.mjs'; export { default as ForeignDocumentUUIDField } from './foreignDocumentUUIDField.mjs';
export { default as ForeignDocumentUUIDArrayField } from './foreignDocumentUUIDArrayField.mjs'; export { default as ForeignDocumentUUIDArrayField } from './foreignDocumentUUIDArrayField.mjs';

View file

@ -1,7 +1,6 @@
import AttachableItem from './attachableItem.mjs'; import AttachableItem from './attachableItem.mjs';
import { ActionField } from '../fields/actionField.mjs'; import { ActionsField } from '../fields/actionField.mjs';
import { armorFeatures } from '../../config/itemConfig.mjs'; import { armorFeatures } from '../../config/itemConfig.mjs';
import { actionsTypes } from '../action/_module.mjs';
export default class DHArmor extends AttachableItem { export default class DHArmor extends AttachableItem {
/** @inheritDoc */ /** @inheritDoc */
@ -40,7 +39,7 @@ export default class DHArmor extends AttachableItem {
major: new fields.NumberField({ integer: true, initial: 0 }), major: new fields.NumberField({ integer: true, initial: 0 }),
severe: new fields.NumberField({ integer: true, initial: 0 }) severe: new fields.NumberField({ integer: true, initial: 0 })
}), }),
actions: new fields.ArrayField(new ActionField()) actions: new ActionsField()
}; };
} }
@ -65,7 +64,10 @@ export default class DHArmor extends AttachableItem {
actionIds.push(...feature.actionIds); actionIds.push(...feature.actionIds);
} }
await this.parent.deleteEmbeddedDocuments('ActiveEffect', effectIds); await this.parent.deleteEmbeddedDocuments('ActiveEffect', effectIds);
changes.system.actions = this.actions.filter(x => !actionIds.includes(x._id)); changes.system.actions = actionIds.reduce((acc, id) => {
acc[`-=${id}`] = null;
return acc;
}, {});
for (var feature of added) { for (var feature of added) {
const featureData = armorFeatures[feature.value]; const featureData = armorFeatures[feature.value];
@ -79,18 +81,39 @@ export default class DHArmor extends AttachableItem {
]); ]);
feature.effectIds = embeddedItems.map(x => x.id); feature.effectIds = embeddedItems.map(x => x.id);
} }
const newActions = {};
if (featureData.actions?.length > 0) { if (featureData.actions?.length > 0) {
const newActions = featureData.actions.map(action => { for (let action of featureData.actions) {
const cls = actionsTypes[action.type]; const embeddedEffects = await this.parent.createEmbeddedDocuments(
return new cls( 'ActiveEffect',
{ ...action, _id: foundry.utils.randomID(), name: game.i18n.localize(action.name) }, (action.effects ?? []).map(effect => ({
...effect,
transfer: false,
name: game.i18n.localize(effect.name),
description: game.i18n.localize(effect.description)
}))
);
const cls = game.system.api.models.actions.actionsTypes[action.type];
const actionId = foundry.utils.randomID();
newActions[actionId] = new cls(
{
...cls.getSourceConfig(this),
...action,
_id: actionId,
name: game.i18n.localize(action.name),
description: game.i18n.localize(action.description),
effects: embeddedEffects.map(x => ({ _id: x.id }))
},
{ parent: this } { parent: this }
); );
});
changes.system.actions = [...this.actions, ...newActions];
feature.actionIds = newActions.map(x => x._id);
} }
} }
changes.system.actions = newActions;
feature.actionIds = Object.keys(newActions);
}
} }
} }
} }

View file

@ -1,5 +1,5 @@
import BaseDataItem from './base.mjs'; import BaseDataItem from './base.mjs';
import { ActionField } from '../fields/actionField.mjs'; import { ActionField, ActionsField } from '../fields/actionField.mjs';
export default class DHFeature extends BaseDataItem { export default class DHFeature extends BaseDataItem {
/** @inheritDoc */ /** @inheritDoc */
@ -25,7 +25,7 @@ export default class DHFeature extends BaseDataItem {
subType: new fields.StringField({ choices: CONFIG.DH.ITEM.featureSubTypes, nullable: true, initial: null }), subType: new fields.StringField({ choices: CONFIG.DH.ITEM.featureSubTypes, nullable: true, initial: null }),
originId: new fields.StringField({ nullable: true, initial: null }), originId: new fields.StringField({ nullable: true, initial: null }),
identifier: new fields.StringField(), identifier: new fields.StringField(),
actions: new fields.ArrayField(new ActionField()) actions: new ActionsField()
}; };
} }

View file

@ -1,5 +1,4 @@
import AttachableItem from './attachableItem.mjs'; import AttachableItem from './attachableItem.mjs';
import { actionsTypes } from '../action/_module.mjs';
import { ActionsField, ActionField } from '../fields/actionField.mjs'; import { ActionsField, ActionField } from '../fields/actionField.mjs';
export default class DHWeapon extends AttachableItem { export default class DHWeapon extends AttachableItem {
@ -66,7 +65,6 @@ export default class DHWeapon extends AttachableItem {
} }
}), }),
actions: new ActionsField() actions: new ActionsField()
// actions: new fields.ArrayField(new ActionField())
}; };
} }
@ -96,7 +94,10 @@ export default class DHWeapon extends AttachableItem {
} }
await this.parent.deleteEmbeddedDocuments('ActiveEffect', removedEffectsUpdate); await this.parent.deleteEmbeddedDocuments('ActiveEffect', removedEffectsUpdate);
changes.system.actions = this.actions.filter(x => !removedActionsUpdate.includes(x._id)); changes.system.actions = removedActionsUpdate.reduce((acc, id) => {
acc[`-=${id}`] = null;
return acc;
}, {});
for (let weaponFeature of added) { for (let weaponFeature of added) {
const featureData = CONFIG.DH.ITEM.weaponFeatures[weaponFeature.value]; const featureData = CONFIG.DH.ITEM.weaponFeatures[weaponFeature.value];
@ -111,7 +112,7 @@ export default class DHWeapon extends AttachableItem {
weaponFeature.effectIds = embeddedItems.map(x => x.id); weaponFeature.effectIds = embeddedItems.map(x => x.id);
} }
const newActions = []; const newActions = {};
if (featureData.actions?.length > 0) { if (featureData.actions?.length > 0) {
for (let action of featureData.actions) { for (let action of featureData.actions) {
const embeddedEffects = await this.parent.createEmbeddedDocuments( const embeddedEffects = await this.parent.createEmbeddedDocuments(
@ -123,24 +124,25 @@ export default class DHWeapon extends AttachableItem {
description: game.i18n.localize(effect.description) description: game.i18n.localize(effect.description)
})) }))
); );
const cls = actionsTypes[action.type];
newActions.push( const cls = game.system.api.models.actions.actionsTypes[action.type];
new cls( const actionId = foundry.utils.randomID();
newActions[actionId] = new cls(
{ {
...cls.getSourceConfig(this),
...action, ...action,
_id: foundry.utils.randomID(), _id: actionId,
name: game.i18n.localize(action.name), name: game.i18n.localize(action.name),
description: game.i18n.localize(action.description), description: game.i18n.localize(action.description),
effects: embeddedEffects.map(x => ({ _id: x.id })) effects: embeddedEffects.map(x => ({ _id: x.id }))
}, },
{ parent: this } { parent: this }
)
); );
} }
} }
changes.system.actions = [...this.actions, ...newActions]; changes.system.actions = newActions;
weaponFeature.actionIds = newActions.map(x => x._id); weaponFeature.actionIds = Object.keys(newActions);
} }
} }
} }

View file

@ -12,15 +12,15 @@ export default class DHItem extends foundry.documents.Item {
/** @inheritDoc */ /** @inheritDoc */
getEmbeddedDocument(embeddedName, id, options) { getEmbeddedDocument(embeddedName, id, options) {
let doc; let doc;
switch ( embeddedName ) { switch (embeddedName) {
case "Action": case 'Action':
doc = this.system.actions?.get(id); doc = this.system.actions?.get(id);
if(!doc && this.system.attack?.id === id) doc = this.system.attack; if (!doc && this.system.attack?.id === id) doc = this.system.attack;
break; break;
default: default:
return super.getEmbeddedDocument(embeddedName, id, options); return super.getEmbeddedDocument(embeddedName, id, options);
} }
if ( options?.strict && !doc ) { if (options?.strict && !doc) {
throw new Error(`The key ${id} does not exist in the ${embeddedName} Collection`); throw new Error(`The key ${id} does not exist in the ${embeddedName} Collection`);
} }
return doc; return doc;
@ -124,9 +124,9 @@ export default class DHItem extends foundry.documents.Item {
async use(event) { async use(event) {
const actions = this.system.actionsList; const actions = this.system.actionsList;
if (actions?.length) { if (actions?.size) {
let action = actions[0]; let action = actions.contents[0];
if (actions.length > 1 && !event?.shiftKey) { if (actions.size > 1 && !event?.shiftKey) {
// Actions Choice Dialog // Actions Choice Dialog
action = await this.selectActionDialog(event); action = await this.selectActionDialog(event);
} }

View file

@ -4,19 +4,18 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti
let html = options.html; let html = options.html;
if (element.dataset.tooltip?.startsWith('#item#')) { if (element.dataset.tooltip?.startsWith('#item#')) {
const splitValues = element.dataset.tooltip.slice(6).split('#action#'); const itemUuid = element.dataset.tooltip.slice(6);
const itemUuid = splitValues[0]; const item = await foundry.utils.fromUuid(itemUuid);
const actionId = splitValues.length > 1 ? splitValues[1] : null;
const baseItem = await foundry.utils.fromUuid(itemUuid);
const item = actionId ? baseItem.system.actions.get(actionId) : baseItem;
if (item) { if (item) {
const type = actionId ? 'action' : item.type; const isAction = item instanceof game.system.api.models.actions.actionsTypes.base;
const description = await TextEditor.enrichHTML(item.system.description); const description = await TextEditor.enrichHTML(isAction ? item.description : item.system.description);
if (item.system?.features) {
for (let feature of item.system.features) { for (let feature of item.system.features) {
feature.system.enrichedDescription = await TextEditor.enrichHTML(feature.system.description); feature.system.enrichedDescription = await TextEditor.enrichHTML(feature.system.description);
} }
}
const type = isAction ? 'action' : item.type;
html = await foundry.applications.handlebars.renderTemplate( html = await foundry.applications.handlebars.renderTemplate(
`systems/daggerheart/templates/ui/tooltip/${type}.hbs`, `systems/daggerheart/templates/ui/tooltip/${type}.hbs`,
{ {

View file

@ -96,7 +96,7 @@ export const tagifyElement = (element, options, onChange, tagifyOptions = {}) =>
mapValueTo: 'name', mapValueTo: 'name',
searchKeys: ['name'], searchKeys: ['name'],
enabled: 0, enabled: 0,
maxItems: 20, maxItems: 100,
closeOnSelect: true, closeOnSelect: true,
highlightFirst: false highlightFirst: false
}, },

View file

@ -249,7 +249,7 @@ Parameters:
{{#if (and showActions (eq item.type 'feature'))}} {{#if (and showActions (eq item.type 'feature'))}}
<div class="item-buttons"> <div class="item-buttons">
{{#each item.system.actions as | action |}} {{#each item.system.actions as | action |}}
<button type="button" data-action="useAction" data-item-uuid="{{action.uuid}}"> <button type="button" data-action="useItem" data-item-uuid="{{action.uuid}}">
{{action.name}} {{action.name}}
</button> </button>
{{/each}} {{/each}}