264 - Action Feature Swap (#265)

* Removed action fields on Adversary/Environment in favor of using Feature Items

* Added drag/drop for features onto adversary/environment settings

* Added Drag of features from Adversary/Environment settings to anywhere in Foundry

* Updated all item types except Class/Subclass

* Added for Class/Subclass

* Items now copy over their features to Character

* Corrected back to actions for right items

* Fixed adversary/environment features display

* PR Fixes
This commit is contained in:
WBHarry 2025-07-05 22:35:05 +02:00 committed by GitHub
parent eac58c1386
commit e9ad9c539a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
58 changed files with 1146 additions and 1114 deletions

View file

@ -1,6 +1,5 @@
import DHApplicationMixin from './application-mixin.mjs';
import DHActionConfig from '../../sheets-configs/action-config.mjs';
import { actionsTypes } from '../../../data/action/_module.mjs';
import DHApplicationMixin from './application-mixin.mjs';
const { ItemSheetV2 } = foundry.applications.sheets;
@ -20,8 +19,15 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
actions: {
addAction: DHBaseItemSheet.#addAction,
editAction: DHBaseItemSheet.#editAction,
removeAction: DHBaseItemSheet.#removeAction
}
removeAction: DHBaseItemSheet.#removeAction,
addFeature: DHBaseItemSheet.#addFeature,
editFeature: DHBaseItemSheet.#editFeature,
removeFeature: DHBaseItemSheet.#removeFeature
},
dragDrop: [
{ dragSelector: null, dropSelector: '.tab.features .drop-section' },
{ dragSelector: '.feature-item', dropSelector: null }
]
};
/* -------------------------------------------- */
@ -93,7 +99,9 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
const actionType = await DHBaseItemSheet.selectActionType();
if (!actionType) return;
try {
const cls = actionsTypes[actionType] ?? actionsTypes.attack,
const cls =
game.system.api.models.actions.actionsTypes[actionType] ??
game.system.api.models.actions.actionsTypes.attack,
action = new cls(
{
_id: foundry.utils.randomID(),
@ -136,4 +144,90 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
'system.actions': this.document.system.actions.filter((_, index) => index !== Number.parseInt(actionIndex))
});
}
/**
* Add a new feature to the item, prompting the user for its type.
* @param {PointerEvent} _event - The originating click event
* @param {HTMLElement} _button - The capturing HTML element which defines the [data-action="addFeature"]
*/
static async #addFeature(_event, _button) {
const feature = await game.items.documentClass.create({
type: 'feature',
name: game.i18n.format('DOCUMENT.New', { type: game.i18n.localize('TYPES.Item.feature') })
});
await this.document.update({
'system.features': [...this.document.system.features.filter(x => x).map(x => x.uuid), feature.uuid]
});
}
/**
* Edit an existing feature on the item
* @param {PointerEvent} _event - The originating click event
* @param {HTMLElement} button - The capturing HTML element which defines the [data-action="editFeature"]
*/
static async #editFeature(_event, button) {
const target = button.closest('.feature-item');
const feature = this.document.system.features.find(x => x?.id === target.id);
if (!feature) {
ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.notifications.featureIsMissing'));
return;
}
feature.sheet.render(true);
}
/**
* Remove a feature from the item.
* @param {PointerEvent} event - The originating click event
* @param {HTMLElement} button - The capturing HTML element which defines the [data-action="removeFeature"]
*/
static async #removeFeature(event, button) {
event.stopPropagation();
const target = button.closest('.feature-item');
await this.document.update({
'system.features': this.document.system.features
.filter(feature => feature && feature.id !== target.id)
.map(x => x.uuid)
});
}
/* -------------------------------------------- */
/* Application Drag/Drop */
/* -------------------------------------------- */
/**
* On dragStart on the item.
* @param {DragEvent} event - The drag event
*/
async _onDragStart(event) {
const featureItem = event.currentTarget.closest('.feature-item');
if (featureItem) {
const feature = this.document.system.features.find(x => x?.id === featureItem.id);
if (!feature) {
ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.notifications.featureIsMissing'));
return;
}
const featureData = { type: 'Item', data: { ...feature.toObject(), _id: null }, fromInternal: true };
event.dataTransfer.setData('text/plain', JSON.stringify(featureData));
event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0);
}
}
/**
* On drop on the item.
* @param {DragEvent} event - The drag event
*/
async _onDrop(event) {
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
if (data.fromInternal) return;
const item = await fromUuid(data.uuid);
if (item?.type === 'feature') {
const current = this.document.system.features.map(x => x.uuid);
await this.document.update({ 'system.features': [...current, item.uuid] });
}
}
}