Merge branch 'main' into feature/granular-action-outcomes

This commit is contained in:
WBHarry 2026-06-30 20:49:37 +02:00
commit 2e9dede678
207 changed files with 2666 additions and 1798 deletions

View file

@ -290,7 +290,7 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
};
}
if (this.action.parent.metadata.isInventoryItem) {
if (this.action.parent.metadata?.isInventoryItem) {
options.quantity = {
label: 'DAGGERHEART.GENERAL.itemQuantity',
group: 'Global'

View file

@ -10,11 +10,7 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
actions: {
addExperience: DHAdversarySettings.#addExperience,
removeExperience: DHAdversarySettings.#removeExperience
},
dragDrop: [
{ dragSelector: null, dropSelector: '.tab.features' },
{ dragSelector: '.feature-item', dropSelector: null }
]
}
};
/**@override */
@ -38,7 +34,8 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
},
features: {
id: 'features',
template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/features.hbs'
template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/features.hbs',
scrollable: ['']
}
};
@ -54,12 +51,16 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
async _prepareContext(options) {
const context = await super._prepareContext(options);
const featureForms = ['passive', 'action', 'reaction'];
context.features = context.document.system.features.sort((a, b) =>
a.system.featureForm !== b.system.featureForm
? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
: a.sort - b.sort
);
// Get feature groups. Uncategorized go to actions
const featureFormsTypes = ['passive', 'action', 'reaction'];
const features = this.document.system.features.sort((a, b) => a.sort - b.sort);
const featureGroups = featureFormsTypes.map(t => ({
featureForm: t,
label: _loc(CONFIG.DH.ITEM.featureForm[t]),
features: features.filter(f => f.system.featureForm === t)
}));
featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm)));
context.featureGroups = featureGroups;
return context;
}
@ -97,32 +98,4 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
await this.actor.update({ [`system.experiences.${target.dataset.experience}`]: _del });
}
async _onDragStart(event) {
const featureItem = event.currentTarget.closest('.feature-item');
if (featureItem) {
const feature = this.actor.items.get(featureItem.id);
const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true };
event.dataTransfer.setData('text/plain', JSON.stringify(featureData));
event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0);
}
}
async _onDrop(event) {
event.stopPropagation();
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
const item = await fromUuid(data.uuid);
if (item?.type === 'feature') {
if (data.fromInternal && item.parent?.uuid === this.actor.uuid) {
return;
}
const itemData = item.toObject();
delete itemData._id;
await this.actor.createEmbeddedDocuments('Item', [itemData]);
}
}
}

View file

@ -15,7 +15,7 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
dragDrop: [
{ dragSelector: null, dropSelector: '.category-container' },
{ dragSelector: null, dropSelector: '.tab.features' },
{ dragSelector: '.feature-item', dropSelector: null }
{ dragSelector: '.feature-item, .inventory-item[data-type="adversary"]', dropSelector: null }
]
};
@ -32,11 +32,13 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
},
features: {
id: 'features',
template: 'systems/daggerheart/templates/sheets-settings/environment-settings/features.hbs'
template: 'systems/daggerheart/templates/sheets-settings/environment-settings/features.hbs',
scrollable: ['']
},
adversaries: {
id: 'adversaries',
template: 'systems/daggerheart/templates/sheets-settings/environment-settings/adversaries.hbs'
template: 'systems/daggerheart/templates/sheets-settings/environment-settings/adversaries.hbs',
scrollable: ['']
}
};
@ -52,12 +54,16 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
async _prepareContext(options) {
const context = await super._prepareContext(options);
const featureForms = ['passive', 'action', 'reaction'];
context.features = context.document.system.features.sort((a, b) =>
a.system.featureForm !== b.system.featureForm
? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
: a.sort - b.sort
);
// Get feature groups. Uncategorized go to actions
const featureFormsTypes = ['passive', 'action', 'reaction'];
const features = this.document.system.features.sort((a, b) => a.sort - b.sort);
const featureGroups = featureFormsTypes.map(t => ({
featureForm: t,
label: _loc(CONFIG.DH.ITEM.featureForm[t]),
features: features.filter(f => f.system.featureForm === t)
}));
featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm)));
context.featureGroups = featureGroups;
return context;
}
@ -110,33 +116,30 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
}
async _onDragStart(event) {
const featureItem = event.currentTarget.closest('.feature-item');
if (featureItem) {
const feature = this.actor.items.get(featureItem.id);
const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true };
event.dataTransfer.setData('text/plain', JSON.stringify(featureData));
event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0);
const element = event.currentTarget.closest('.inventory-item[data-type=adversary]');
if (element) {
const adversaryData = { type: 'Actor', uuid: element.dataset.itemUuid };
event.dataTransfer.setData('text/plain', JSON.stringify(adversaryData));
event.dataTransfer.setDragImage(element, 60, 0);
} else {
return super._onDragStart(event);
}
}
async _onDrop(event) {
event.stopPropagation();
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
const item = await fromUuid(data.uuid);
if (data.fromInternal && item?.parent?.uuid === this.actor.uuid) return;
if (item.type === 'adversary' && event.target.closest('.category-container')) {
const doc = await fromUuid(data.uuid);
if (doc?.type === 'adversary' && event.target.closest('.category-container')) {
const target = event.target.closest('.category-container');
const path = `system.potentialAdversaries.${target.dataset.potentialAdversary}.adversaries`;
const current = foundry.utils.getProperty(this.actor, path).map(x => x.uuid);
await this.actor.update({
[path]: [...current, item.uuid]
});
this.render();
} else if (item.type === 'feature' && event.target.closest('.tab.features')) {
await this.actor.createEmbeddedDocuments('Item', [item]);
this.render();
if (!current.includes(doc.uuid)) {
await this.actor.update({ [path]: [...current, doc.uuid] });
}
return;
}
return super._onDrop(event);
}
}

View file

@ -27,7 +27,8 @@ export default class DHNPCSettings extends DHBaseActorSettings {
},
features: {
id: 'features',
template: 'systems/daggerheart/templates/sheets-settings/npc-settings/features.hbs'
template: 'systems/daggerheart/templates/sheets-settings/npc-settings/features.hbs',
scrollable: ['']
}
};
@ -43,43 +44,17 @@ export default class DHNPCSettings extends DHBaseActorSettings {
async _prepareContext(options) {
const context = await super._prepareContext(options);
const featureForms = ['passive', 'action', 'reaction'];
context.features = context.document.system.features.sort((a, b) =>
a.system.featureForm !== b.system.featureForm
? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
: a.sort - b.sort
);
// Get feature groups. Uncategorized go to actions
const featureFormsTypes = ['passive', 'action', 'reaction'];
const features = this.document.system.features.sort((a, b) => a.sort - b.sort);
const featureGroups = featureFormsTypes.map(t => ({
featureForm: t,
label: _loc(CONFIG.DH.ITEM.featureForm[t]),
features: features.filter(f => f.system.featureForm === t)
}));
featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm)));
context.featureGroups = featureGroups;
return context;
}
/* -------------------------------------------- */
async _onDragStart(event) {
const featureItem = event.currentTarget.closest('.feature-item');
if (featureItem) {
const feature = this.actor.items.get(featureItem.id);
const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true };
event.dataTransfer.setData('text/plain', JSON.stringify(featureData));
event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0);
}
}
async _onDrop(event) {
event.stopPropagation();
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
const item = await fromUuid(data.uuid);
if (item?.type === 'feature') {
if (data.fromInternal && item.parent?.uuid === this.actor.uuid) {
return;
}
const itemData = item.toObject();
delete itemData._id;
await this.actor.createEmbeddedDocuments('Item', [itemData]);
}
}
}

View file

@ -168,8 +168,8 @@ export default class SettingFeatureConfig extends HandlebarsApplicationMixin(App
updatedEffects = deleteEffect
? currentEffects.filter(x => x.id !== effectData.id)
: existingEffectIndex === -1
? [...currentEffects, effectData]
: currentEffects.with(existingEffectIndex, effectData);
? [...currentEffects, effectData]
: currentEffects.with(existingEffectIndex, effectData);
await this.updateMove({
[`${this.movePath}.effects`]: updatedEffects
});
@ -235,9 +235,9 @@ export default class SettingFeatureConfig extends HandlebarsApplicationMixin(App
return this.hasEffects
? tabs
: Object.keys(tabs).reduce((acc, key) => {
if (key !== 'effects') acc[key] = tabs[key];
return acc;
}, {});
if (key !== 'effects') acc[key] = tabs[key];
return acc;
}, {});
}
/** @override */