From a0358c4730aa6667ef8a6700c6e61250128ffda0 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sun, 15 Jun 2025 10:54:32 +0200 Subject: [PATCH] Added actions and effects to Ancestry and Community --- lang/en.json | 5 +- module/applications/sheets/items/ancestry.mjs | 83 +--------- .../applications/sheets/items/community.mjs | 83 +--------- module/applications/sheets/items/heritage.mjs | 147 ++++++++++++++++++ module/data/item/ancestry.mjs | 9 +- module/data/item/community.mjs | 10 +- styles/daggerheart.css | 35 +++++ styles/daggerheart.less | 1 + styles/less/global/tab-effects.less | 46 ++++++ templates/sheets/global/tabs/tab-actions.hbs | 2 +- templates/sheets/global/tabs/tab-effects.hbs | 21 +++ 11 files changed, 272 insertions(+), 170 deletions(-) create mode 100644 module/applications/sheets/items/heritage.mjs create mode 100644 styles/less/global/tab-effects.less create mode 100644 templates/sheets/global/tabs/tab-effects.hbs diff --git a/lang/en.json b/lang/en.json index 0b43ee8f..cfd1bb9e 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1185,8 +1185,9 @@ } } }, - "Heritage": { - "Title": "Abilities" + "Global": { + "Actions": "Actions", + "Effects": "Effects" }, "DomainCard": { "Type": "Type", diff --git a/module/applications/sheets/items/ancestry.mjs b/module/applications/sheets/items/ancestry.mjs index e6a92e1e..3d20df7a 100644 --- a/module/applications/sheets/items/ancestry.mjs +++ b/module/applications/sheets/items/ancestry.mjs @@ -1,88 +1,13 @@ -import DaggerheartSheet from '../daggerheart-sheet.mjs'; +import DHHeritageSheetV2 from './heritage.mjs'; const { ItemSheetV2 } = foundry.applications.sheets; -export default class AncestrySheet extends DaggerheartSheet(ItemSheetV2) { +export default class AncestrySheet extends DHHeritageSheetV2(ItemSheetV2) { static DEFAULT_OPTIONS = { - tag: 'form', - classes: ['daggerheart', 'sheet', 'item', 'dh-style', 'ancestry'], - position: { width: 450, height: 700 }, - actions: { - editFeature: this.editFeature, - deleteFeature: this.deleteFeature - }, - form: { - handler: this.updateForm, - submitOnChange: true, - closeOnSubmit: false - }, - dragDrop: [{ dragSelector: null, dropSelector: null }] + classes: ['ancestry'] }; static PARTS = { header: { template: 'systems/daggerheart/templates/sheets/items/ancestry/header.hbs' }, - tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, - description: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-description.hbs' }, - features: { - template: 'systems/daggerheart/templates/sheets/global/tabs/tab-feature-section.hbs', - scrollable: ['.features'] - } + ...super.PARTS }; - - static TABS = { - description: { - active: true, - cssClass: '', - group: 'primary', - id: 'description', - icon: null, - label: 'DAGGERHEART.Sheets.Feature.Tabs.Description' - }, - features: { - active: false, - cssClass: '', - group: 'primary', - id: 'features', - icon: null, - label: 'DAGGERHEART.Sheets.Feature.Tabs.Features' - } - }; - - async _prepareContext(_options) { - const context = await super._prepareContext(_options); - context.document = this.document; - context.tabs = super._getTabs(this.constructor.TABS); - - return context; - } - - static async updateForm(event, _, formData) { - await this.document.update(formData.object); - this.render(); - } - - static async editFeature(_, target) { - const feature = await fromUuid(target.dataset.feature); - feature.sheet.render(true); - } - - static async deleteFeature(event, target) { - event.preventDefault(); - event.stopPropagation(); - await this.item.update({ - 'system.abilities': this.item.system.abilities.filter(x => x.uuid !== target.dataset.feature) - }); - } - - async _onDrop(event) { - const data = TextEditor.getDragEventData(event); - const item = await fromUuid(data.uuid); - if (item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.ancestry.id) { - await this.document.update({ - 'system.abilities': [ - ...this.document.system.abilities, - { img: item.img, name: item.name, uuid: item.uuid } - ] - }); - } - } } diff --git a/module/applications/sheets/items/community.mjs b/module/applications/sheets/items/community.mjs index 0c15e97e..890ff605 100644 --- a/module/applications/sheets/items/community.mjs +++ b/module/applications/sheets/items/community.mjs @@ -1,88 +1,13 @@ -import DaggerheartSheet from '../daggerheart-sheet.mjs'; +import DHHeritageSheetV2 from './heritage.mjs'; const { ItemSheetV2 } = foundry.applications.sheets; -export default class CommunitySheet extends DaggerheartSheet(ItemSheetV2) { +export default class CommunitySheet extends DHHeritageSheetV2(ItemSheetV2) { static DEFAULT_OPTIONS = { - tag: 'form', - classes: ['daggerheart', 'sheet', 'item', 'dh-style', 'community'], - position: { width: 450, height: 700 }, - actions: { - editFeature: this.editFeature, - deleteFeature: this.deleteFeature - }, - form: { - handler: this.updateForm, - submitOnChange: true, - closeOnSubmit: false - }, - dragDrop: [{ dragSelector: null, dropSelector: null }] + classes: ['community'] }; static PARTS = { header: { template: 'systems/daggerheart/templates/sheets/items/community/header.hbs' }, - tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, - description: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-description.hbs' }, - features: { - template: 'systems/daggerheart/templates/sheets/global/tabs/tab-feature-section.hbs', - scrollable: ['.features'] - } + ...super.PARTS }; - - static TABS = { - description: { - active: true, - cssClass: '', - group: 'primary', - id: 'description', - icon: null, - label: 'DAGGERHEART.Sheets.Feature.Tabs.Description' - }, - features: { - active: false, - cssClass: '', - group: 'primary', - id: 'features', - icon: null, - label: 'DAGGERHEART.Sheets.Feature.Tabs.Features' - } - }; - - async _prepareContext(_options) { - const context = await super._prepareContext(_options); - context.document = this.document; - context.tabs = super._getTabs(this.constructor.TABS); - - return context; - } - - static async updateForm(event, _, formData) { - await this.document.update(formData.object); - this.render(); - } - - static async editFeature(_, target) { - const feature = await fromUuid(target.dataset.feature); - feature.sheet.render(true); - } - - static async deleteFeature(event, target) { - event.preventDefault(); - event.stopPropagation(); - await this.item.update({ - 'system.abilities': this.item.system.abilities.filter(x => x.uuid !== target.dataset.feature) - }); - } - - async _onDrop(event) { - const data = TextEditor.getDragEventData(event); - const item = await fromUuid(data.uuid); - if (item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.community.id) { - await this.document.update({ - 'system.abilities': [ - ...this.document.system.abilities, - { img: item.img, name: item.name, uuid: item.uuid } - ] - }); - } - } } diff --git a/module/applications/sheets/items/heritage.mjs b/module/applications/sheets/items/heritage.mjs new file mode 100644 index 00000000..44d950ca --- /dev/null +++ b/module/applications/sheets/items/heritage.mjs @@ -0,0 +1,147 @@ +import { actionsTypes } from '../../../data/_module.mjs'; +import DHActionConfig from '../../config/Action.mjs'; +import DHItemMixin from '../item.mjs'; + +export default function DHHeritageMixin(Base) { + return class DHHeritageSheetV2 extends DHItemMixin(Base) { + static DEFAULT_OPTIONS = { + tag: 'form', + position: { width: 450, height: 700 }, + actions: { + addAction: this.addAction, + editAction: this.editAction, + removeAction: this.removeAction, + addEffect: this.addEffect, + editEffect: this.editEffect, + removeEffect: this.removeEffect + }, + form: { + handler: this.updateForm, + submitOnChange: true, + closeOnSubmit: false + } + }; + + static PARTS = { + tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, + description: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-description.hbs' }, + actions: { + template: 'systems/daggerheart/templates/sheets/global/tabs/tab-actions.hbs', + scrollable: ['.actions'] + }, + effects: { + template: 'systems/daggerheart/templates/sheets/global/tabs/tab-effects.hbs', + scrollable: ['.effects'] + } + }; + + static TABS = { + description: { + active: true, + cssClass: '', + group: 'primary', + id: 'description', + icon: null, + label: 'DAGGERHEART.Sheets.Feature.Tabs.Description' + }, + actions: { + active: false, + cssClass: '', + group: 'primary', + id: 'actions', + icon: null, + label: 'DAGGERHEART.Sheets.Feature.Tabs.Actions' + }, + effects: { + active: false, + cssClass: '', + group: 'primary', + id: 'effects', + icon: null, + label: 'DAGGERHEART.Sheets.Feature.Tabs.Effects' + } + }; + + async _prepareContext(_options) { + const context = await super._prepareContext(_options); + context.document = this.document; + context.tabs = super._getTabs(this.constructor.TABS); + + return context; + } + + static async updateForm(event, _, formData) { + await this.document.update(formData.object); + this.render(); + } + + async selectActionType() { + const content = await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/views/actionType.hbs', + { types: SYSTEM.ACTIONS.actionTypes } + ), + title = 'Select Action Type', + type = 'form', + data = {}; + return Dialog.prompt({ + title, + label: title, + content, + type, + callback: html => { + const form = html[0].querySelector('form'), + fd = new foundry.applications.ux.FormDataExtended(form); + foundry.utils.mergeObject(data, fd.object, { inplace: true }); + return data; + }, + rejectClose: false + }); + } + + static async addAction() { + const actionType = await this.selectActionType(); + const cls = actionsTypes[actionType?.type] ?? actionsTypes.attack, + action = new cls( + { + _id: foundry.utils.randomID(), + type: actionType.type, + name: game.i18n.localize(SYSTEM.ACTIONS.actionTypes[actionType.type].name), + ...cls.getSourceConfig(this.document) + }, + { + parent: this.document + } + ); + await this.document.update({ 'system.actions': [...this.document.system.actions, action] }); + } + + static async editAction(_, button) { + const action = this.document.system.actions[button.dataset.index]; + await new DHActionConfig(action).render(true); + } + + static async removeAction(event, button) { + event.stopPropagation(); + await this.document.update({ + 'system.actions': this.document.system.actions.filter( + (_, index) => index !== Number.parseInt(button.dataset.index) + ) + }); + } + + static async addEffect() { + await this.document.createEmbeddedDocuments('ActiveEffect', [ + { name: game.i18n.localize('DAGGERHEART.Feature.NewEffect') } + ]); + } + + static async editEffect(_, target) { + const effect = this.document.effects.get(target.dataset.effect); + effect.sheet.render(true); + } + + static async removeEffect(_, target) { + await this.document.effects.get(target.dataset.effect).delete(); + } + }; +} diff --git a/module/data/item/ancestry.mjs b/module/data/item/ancestry.mjs index 0359e9fc..8af6e081 100644 --- a/module/data/item/ancestry.mjs +++ b/module/data/item/ancestry.mjs @@ -1,12 +1,13 @@ +import ActionField from '../fields/actionField.mjs'; import BaseDataItem from './base.mjs'; export default class DHAncestry extends BaseDataItem { /** @inheritDoc */ static get metadata() { return foundry.utils.mergeObject(super.metadata, { - label: "TYPES.Item.ancestry", - type: "ancestry", - hasDescription: true, + label: 'TYPES.Item.ancestry', + type: 'ancestry', + hasDescription: true }); } @@ -15,7 +16,7 @@ export default class DHAncestry extends BaseDataItem { const fields = foundry.data.fields; return { ...super.defineSchema(), - //TODO: add features field + actions: new fields.ArrayField(new ActionField()) }; } } diff --git a/module/data/item/community.mjs b/module/data/item/community.mjs index ffa6f921..d0ede69a 100644 --- a/module/data/item/community.mjs +++ b/module/data/item/community.mjs @@ -1,22 +1,22 @@ +import ActionField from '../fields/actionField.mjs'; import BaseDataItem from './base.mjs'; export default class DHCommunity extends BaseDataItem { /** @inheritDoc */ static get metadata() { return foundry.utils.mergeObject(super.metadata, { - label: "TYPES.Item.community", - type: "community", - hasDescription: true, + label: 'TYPES.Item.community', + type: 'community', + hasDescription: true }); } - /** @inheritDoc */ static defineSchema() { const fields = foundry.data.fields; return { ...super.defineSchema(), - //TODO: add features field + actions: new fields.ArrayField(new ActionField()) }; } } diff --git a/styles/daggerheart.css b/styles/daggerheart.css index abdd8ac0..c39c6df6 100755 --- a/styles/daggerheart.css +++ b/styles/daggerheart.css @@ -3415,6 +3415,41 @@ div.daggerheart.views.multiclass { .sheet.daggerheart.dh-style .tab.actions .actions-list .action-item .controls a { text-shadow: none; } +.sheet.daggerheart.dh-style .tab.effects .effects-list { + display: flex; + flex-direction: column; + list-style: none; + padding: 0; + margin: 0; + width: 100%; + gap: 5px; +} +.sheet.daggerheart.dh-style .tab.effects .effects-list .effect-item { + display: grid; + align-items: center; + grid-template-columns: 1fr 4fr 1fr; + cursor: pointer; +} +.sheet.daggerheart.dh-style .tab.effects .effects-list .effect-item h4 { + font-family: 'Montserrat', sans-serif; + font-weight: lighter; + color: #efe6d8; +} +.sheet.daggerheart.dh-style .tab.effects .effects-list .effect-item .image { + height: 40px; + width: 40px; + object-fit: cover; + border-radius: 6px; + border: none; +} +.sheet.daggerheart.dh-style .tab.effects .effects-list .effect-item .controls { + display: flex; + justify-content: center; + gap: 10px; +} +.sheet.daggerheart.dh-style .tab.effects .effects-list .effect-item .controls a { + text-shadow: none; +} .application.sheet.daggerheart.dh-style .item-sheet-header { display: flex; } diff --git a/styles/daggerheart.less b/styles/daggerheart.less index bb603548..0b0f3926 100755 --- a/styles/daggerheart.less +++ b/styles/daggerheart.less @@ -29,6 +29,7 @@ @import './less/global/tab-navigation.less'; @import './less/global/tab-form-footer.less'; @import './less/global/tab-actions.less'; +@import './less/global/tab-effects.less'; @import './less/global/item-header.less'; @import './less/global/feature-section.less'; diff --git a/styles/less/global/tab-effects.less b/styles/less/global/tab-effects.less new file mode 100644 index 00000000..c926f5d1 --- /dev/null +++ b/styles/less/global/tab-effects.less @@ -0,0 +1,46 @@ +@import '../utils/colors.less'; +@import '../utils/fonts.less'; + +.sheet.daggerheart.dh-style { + .tab.effects { + .effects-list { + display: flex; + flex-direction: column; + list-style: none; + padding: 0; + margin: 0; + width: 100%; + gap: 5px; + + .effect-item { + display: grid; + align-items: center; + grid-template-columns: 1fr 4fr 1fr; + cursor: pointer; + + h4 { + font-family: @font-body; + font-weight: lighter; + color: @beige; + } + + .image { + height: 40px; + width: 40px; + object-fit: cover; + border-radius: 6px; + border: none; + } + + .controls { + display: flex; + justify-content: center; + gap: 10px; + a { + text-shadow: none; + } + } + } + } + } +} diff --git a/templates/sheets/global/tabs/tab-actions.hbs b/templates/sheets/global/tabs/tab-actions.hbs index be986927..6cc1b652 100644 --- a/templates/sheets/global/tabs/tab-actions.hbs +++ b/templates/sheets/global/tabs/tab-actions.hbs @@ -4,7 +4,7 @@ data-group='{{tabs.actions.group}}' >
- {{localize "Actions"}} + {{localize "DAGGERHEART.Sheets.Global.Actions"}}
{{#each document.system.actions as |action index|}}
diff --git a/templates/sheets/global/tabs/tab-effects.hbs b/templates/sheets/global/tabs/tab-effects.hbs new file mode 100644 index 00000000..e6191c80 --- /dev/null +++ b/templates/sheets/global/tabs/tab-effects.hbs @@ -0,0 +1,21 @@ +
+
+ {{localize "DAGGERHEART.Sheets.Global.Effects"}} +
+ {{#each document.effects as |effect|}} +
+ + {{effect.name}} +
+ + +
+
+ {{/each}} +
+
+
\ No newline at end of file