From 261867a4cc475a14b4423142e14d683fc70916fb Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sat, 5 Jul 2025 13:16:39 +0200 Subject: [PATCH] Added for Class/Subclass --- lang/en.json | 3 +- module/applications/sheets/api/base-item.mjs | 1 - module/applications/sheets/items/class.mjs | 92 +++++------- module/applications/sheets/items/subclass.mjs | 132 ++++++------------ module/data/item/class.mjs | 5 +- module/data/item/subclass.mjs | 17 +-- module/systemRegistration/handlebars.mjs | 2 - templates/sheets/items/class/features.hbs | 4 +- templates/sheets/items/subclass/features.hbs | 42 ++++-- .../items/subclass/parts/subclass-feature.hbs | 30 ---- .../subclass/parts/subclass-features.hbs | 22 --- 11 files changed, 121 insertions(+), 229 deletions(-) delete mode 100644 templates/sheets/items/subclass/parts/subclass-feature.hbs delete mode 100644 templates/sheets/items/subclass/parts/subclass-features.hbs diff --git a/lang/en.json b/lang/en.json index 72985551..fe358714 100755 --- a/lang/en.json +++ b/lang/en.json @@ -26,7 +26,8 @@ "adversaryMissing": "The linked adversary doesn't exist in the world.", "beastformInapplicable": "A beastform can only be applied to a Character.", "beastformAlreadyApplied": "The character already has a beastform applied!", - "featureIsMissing": "The feature doesn't exist. You should remove it." + "featureIsMissing": "The feature doesn't exist. You should remove it.", + "featureIsFull": "You can only have 1 entry of this feature" } }, "Settings": { diff --git a/module/applications/sheets/api/base-item.mjs b/module/applications/sheets/api/base-item.mjs index 049f72e1..d786b31a 100644 --- a/module/applications/sheets/api/base-item.mjs +++ b/module/applications/sheets/api/base-item.mjs @@ -71,7 +71,6 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) { */ static async #addFeature(_event, _button) { const feature = await game.items.documentClass.create({ - id: foundry.utils.randomID(), type: 'feature', name: game.i18n.localize('DAGGERHEART.General.newFeature') }); diff --git a/module/applications/sheets/items/class.mjs b/module/applications/sheets/items/class.mjs index 2ba17346..59f483e2 100644 --- a/module/applications/sheets/items/class.mjs +++ b/module/applications/sheets/items/class.mjs @@ -1,6 +1,4 @@ import DHBaseItemSheet from '../api/base-item.mjs'; -import DHActionConfig from '../../sheets-configs/action-config.mjs'; -import { actionsTypes } from '../../../data/action/_module.mjs'; const { TextEditor } = foundry.applications.ux; @@ -169,71 +167,45 @@ export default class ClassSheet extends DHBaseItemSheet { doc.sheet.render({ force: true }); } - //TODO: redo this - async selectActionType() { - const content = await foundry.applications.handlebars.renderTemplate( - 'systems/daggerheart/templates/actionTypes/actionType.hbs', - { types: CONFIG.DH.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 - }); - } - - //TODO: redo this getActionPath(type) { return type === 'hope' ? 'hopeFeatures' : 'classFeatures'; } - //TODO: redo this static async addFeature(_, target) { const actionPath = this.getActionPath(target.dataset.type); - const actionType = await this.selectActionType(); - const cls = actionsTypes[actionType?.type] ?? actionsTypes.attack, - action = new cls( - { - _id: foundry.utils.randomID(), - systemPath: actionPath, - type: actionType.type, - name: game.i18n.localize(CONFIG.DH.ACTIONS.actionTypes[actionType.type].name), - ...cls.getSourceConfig(this.document) - }, - { - parent: this.document - } - ); - await this.document.update({ [`system.${actionPath}`]: [...this.document.system[actionPath], action] }); - } - - //TODO: redo this - static async editFeature(_, target) { - const action = this.document.system[this.getActionPath(target.dataset.type)].find( - x => x._id === target.dataset.feature - ); - await new DHActionConfig(action).render(true); - } - - //TODO: redo this - static async deleteFeature(_, target) { - const actionPath = this.getActionPath(target.dataset.type); + const feature = await game.items.documentClass.create({ + type: 'feature', + name: game.i18n.localize('DAGGERHEART.General.newFeature') + }); await this.document.update({ - [`system.${actionPath}`]: this.document.system[actionPath].filter( - action => action._id !== target.dataset.feature - ) + [`system.${actionPath}`]: [ + ...this.document.system[actionPath].filter(x => x).map(x => x.uuid), + feature.uuid + ] + }); + } + + static async editFeature(_, button) { + const target = button.closest('.feature-item'); + const actionPath = this.getActionPath(button.dataset.type); + const feature = this.document.system[actionPath].find(x => x?.id === target.dataset.featureId); + if (!feature) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.notifications.featureIsMissing')); + return; + } + + feature.sheet.render(true); + } + + static async deleteFeature(event, button) { + event.stopPropagation(); + const target = button.closest('.feature-item'); + const actionPath = this.getActionPath(button.dataset.type); + + await this.document.update({ + [`system.${actionPath}`]: this.document.system[actionPath] + .filter(feature => feature && feature.id !== target.dataset.featureId) + .map(x => x.uuid) }); } } diff --git a/module/applications/sheets/items/subclass.mjs b/module/applications/sheets/items/subclass.mjs index 3c70d84a..26e3098f 100644 --- a/module/applications/sheets/items/subclass.mjs +++ b/module/applications/sheets/items/subclass.mjs @@ -1,6 +1,4 @@ import DHBaseItemSheet from '../api/base-item.mjs'; -import DHActionConfig from '../../sheets-configs/action-config.mjs'; -import { actionsTypes } from '../../../data/action/_module.mjs'; export default class SubclassSheet extends DHBaseItemSheet { /**@inheritdoc */ @@ -39,101 +37,63 @@ export default class SubclassSheet extends DHBaseItemSheet { } }; - //TODO redo everything below this message - - static addFeature(_, target) { - if (target.dataset.type === 'action') this.addAction(target.dataset.level); - else this.addEffect(target.dataset.level); - } - - static async editFeature(_, target) { - if (target.dataset.type === 'action') this.editAction(target.dataset.level, target.dataset.feature); - else this.editEffect(target.dataset.feature); - } - - static async deleteFeature(_, target) { - if (target.dataset.type === 'action') this.removeAction(target.dataset.level, target.dataset.feature); - else this.removeEffect(target.dataset.level, target.dataset.feature); - } - - async #selectActionType() { - const content = await foundry.applications.handlebars.renderTemplate( - 'systems/daggerheart/templates/actionTypes/actionType.hbs', - { types: CONFIG.DH.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 addFeature(_, target) { + const feature = await game.items.documentClass.create({ + type: 'feature', + name: game.i18n.localize('DAGGERHEART.General.newFeature') }); - } - - async addAction(level) { - const actionType = await this.#selectActionType(); - const cls = actionsTypes[actionType?.type] ?? actionsTypes.attack, - action = new cls( - { - _id: foundry.utils.randomID(), - systemPath: `${level}.actions`, - type: actionType.type, - name: game.i18n.localize(CONFIG.DH.ACTIONS.actionTypes[actionType.type].name), - ...cls.getSourceConfig(this.document) - }, - { - parent: this.document - } - ); - await this.document.update({ [`system.${level}.actions`]: [...this.document.system[level].actions, action] }); - await new DHActionConfig( - this.document.system[level].actions[this.document.system[level].actions.length - 1] - ).render(true); - } - - async addEffect(level) { - const embeddedItems = await this.document.createEmbeddedDocuments('ActiveEffect', [ - { name: game.i18n.localize('DAGGERHEART.Feature.NewEffect') } - ]); await this.document.update({ - [`system.${level}.effects`]: [ - ...this.document.system[level].effects.map(x => x.uuid), - embeddedItems[0].uuid - ] + [`system.${target.dataset.type}`]: feature.uuid }); } - async editAction(level, id) { - const action = this.document.system[level].actions.find(x => x._id === id); - await new DHActionConfig(action).render(true); + static async editFeature(_, button) { + const feature = this.document.system[button.dataset.type]; + if (!feature) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.notifications.featureIsMissing')); + return; + } + + feature.sheet.render(true); } - async editEffect(id) { - const effect = this.document.effects.get(id); - effect.sheet.render(true); - } + static async deleteFeature(event, button) { + event.stopPropagation(); - async removeAction(level, id) { await this.document.update({ - [`system.${level}.actions`]: this.document.system[level].actions.filter(action => action._id !== id) + [`system.${button.dataset.type}`]: null }); } - async removeEffect(level, id) { - await this.document.effects.get(id).delete(); - await this.document.update({ - [`system.${level}.effects`]: this.document.system[level].effects - .filter(x => x && x.id !== id) - .map(effect => effect.uuid) - }); + async _onDragStart(event) { + const featureItem = event.currentTarget.closest('.drop-section'); + + if (featureItem) { + const feature = this.document.system[featureItem.dataset.type]; + 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); + } + } + + 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 dropSection = event.target.closest('.drop-section'); + if (this.document.system[dropSection.dataset.type]) { + ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.notifications.featureIsFull')); + return; + } + + await this.document.update({ [`system.${dropSection.dataset.type}`]: item.uuid }); + } } } diff --git a/module/data/item/class.mjs b/module/data/item/class.mjs index 46ec6ff8..efda7163 100644 --- a/module/data/item/class.mjs +++ b/module/data/item/class.mjs @@ -1,7 +1,6 @@ import BaseDataItem from './base.mjs'; import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs'; import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs'; -import ActionField from '../fields/actionField.mjs'; export default class DHClass extends BaseDataItem { /** @inheritDoc */ @@ -28,8 +27,8 @@ export default class DHClass extends BaseDataItem { label: 'DAGGERHEART.Sheets.Class.HitPoints' }), evasion: new fields.NumberField({ initial: 0, integer: true, label: 'DAGGERHEART.Sheets.Class.Evasion' }), - hopeFeatures: new foundry.data.fields.ArrayField(new ActionField()), - classFeatures: new foundry.data.fields.ArrayField(new ActionField()), + hopeFeatures: new ForeignDocumentUUIDArrayField({ type: 'Item' }), + classFeatures: new ForeignDocumentUUIDArrayField({ type: 'Item' }), subclasses: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false }), inventory: new fields.SchemaField({ take: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false }), diff --git a/module/data/item/subclass.mjs b/module/data/item/subclass.mjs index 8590468e..179cd534 100644 --- a/module/data/item/subclass.mjs +++ b/module/data/item/subclass.mjs @@ -1,15 +1,6 @@ -import ActionField from '../fields/actionField.mjs'; -import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs'; +import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs'; import BaseDataItem from './base.mjs'; -const featureSchema = () => { - return new foundry.data.fields.SchemaField({ - name: new foundry.data.fields.StringField({ required: true }), - effects: new ForeignDocumentUUIDArrayField({ type: 'ActiveEffect', required: false }), - actions: new foundry.data.fields.ArrayField(new ActionField()) - }); -}; - export default class DHSubclass extends BaseDataItem { /** @inheritDoc */ static get metadata() { @@ -31,9 +22,9 @@ export default class DHSubclass extends BaseDataItem { nullable: true, initial: null }), - foundationFeature: featureSchema(), - specializationFeature: featureSchema(), - masteryFeature: featureSchema(), + foundationFeature: new ForeignDocumentUUIDField({ type: 'Item' }), + specializationFeature: new ForeignDocumentUUIDField({ type: 'Item' }), + masteryFeature: new ForeignDocumentUUIDField({ type: 'Item' }), featureState: new fields.NumberField({ required: true, initial: 1, min: 1 }), isMulticlass: new fields.BooleanField({ initial: false }) }; diff --git a/module/systemRegistration/handlebars.mjs b/module/systemRegistration/handlebars.mjs index 4c2f7f1d..75a5aff6 100644 --- a/module/systemRegistration/handlebars.mjs +++ b/module/systemRegistration/handlebars.mjs @@ -5,8 +5,6 @@ export const preloadHandlebarsTemplates = async function () { 'systems/daggerheart/templates/sheets/global/partials/action-item.hbs', 'systems/daggerheart/templates/sheets/global/partials/domain-card-item.hbs', 'systems/daggerheart/templates/sheets/global/partials/inventory-fieldset-items.hbs', - 'systems/daggerheart/templates/sheets/items/subclass/parts/subclass-features.hbs', - 'systems/daggerheart/templates/sheets/items/subclass/parts/subclass-feature.hbs', 'systems/daggerheart/templates/components/card-preview.hbs', 'systems/daggerheart/templates/levelup/parts/selectable-card-preview.hbs', 'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs', diff --git a/templates/sheets/items/class/features.hbs b/templates/sheets/items/class/features.hbs index 5d8d8a70..811d6ce5 100644 --- a/templates/sheets/items/class/features.hbs +++ b/templates/sheets/items/class/features.hbs @@ -7,7 +7,7 @@
{{localize "DAGGERHEART.Sheets.Class.HopeFeatures"}}
- {{#each source.system.hopeFeatures as |feature index|}} + {{#each source.system.hopeFeatures as |feature|}} {{> 'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs' type='hope' feature=feature}} {{/each}}
@@ -16,7 +16,7 @@
{{localize "DAGGERHEART.Sheets.Class.ClassFeatures"}}
- {{#each source.system.classFeatures as |feature index|}} + {{#each source.system.classFeatures as |feature|}} {{> 'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs' type='class' feature=feature}} {{/each}}
diff --git a/templates/sheets/items/subclass/features.hbs b/templates/sheets/items/subclass/features.hbs index d7f7cfd0..98dcb054 100644 --- a/templates/sheets/items/subclass/features.hbs +++ b/templates/sheets/items/subclass/features.hbs @@ -3,18 +3,42 @@ data-tab='{{tabs.features.id}}' data-group='{{tabs.features.group}}' > -
- {{localize "DAGGERHEART.Sheets.Subclass.Tabs.Foundation"}} - {{> 'systems/daggerheart/templates/sheets/items/subclass/parts/subclass-features.hbs' level='foundationFeature' feature=source.system.foundationFeature}} +
+ + {{localize "DAGGERHEART.Sheets.Subclass.Tabs.Foundation"}} + + + +
+ {{#if source.system.foundationFeature}} + {{> 'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs' type='foundationFeature' feature=source.system.foundationFeature}} + {{/if}} +
-
- {{localize "DAGGERHEART.Sheets.Subclass.Tabs.Specialization"}} - {{> 'systems/daggerheart/templates/sheets/items/subclass/parts/subclass-features.hbs' level='specializationFeature' feature=source.system.specializationFeature}} +
+ + {{localize "DAGGERHEART.Sheets.Subclass.Tabs.Specialization"}} + + + +
+ {{#if source.system.specializationFeature}} + {{> 'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs' type='specializationFeature' feature=source.system.specializationFeature}} + {{/if}} +
-
- {{localize "DAGGERHEART.Sheets.Subclass.Tabs.Mastery"}} - {{> 'systems/daggerheart/templates/sheets/items/subclass/parts/subclass-features.hbs' level='masteryFeature' feature=source.system.masteryFeature}} +
+ + {{localize "DAGGERHEART.Sheets.Subclass.Tabs.Mastery"}} + + + +
+ {{#if source.system.masteryFeature}} + {{> 'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs' type='masteryFeature' feature=source.system.masteryFeature}} + {{/if}} +
\ No newline at end of file diff --git a/templates/sheets/items/subclass/parts/subclass-feature.hbs b/templates/sheets/items/subclass/parts/subclass-feature.hbs deleted file mode 100644 index e818e406..00000000 --- a/templates/sheets/items/subclass/parts/subclass-feature.hbs +++ /dev/null @@ -1,30 +0,0 @@ -
  • -
    - -

    {{feature.name}}

    - {{#unless hideContrals}} - - {{/unless}} -
    -
  • \ No newline at end of file diff --git a/templates/sheets/items/subclass/parts/subclass-features.hbs b/templates/sheets/items/subclass/parts/subclass-features.hbs deleted file mode 100644 index 7bfb1496..00000000 --- a/templates/sheets/items/subclass/parts/subclass-features.hbs +++ /dev/null @@ -1,22 +0,0 @@ -
    -
    - {{localize "DAGGERHEART.Sheets.Subclass.SubclassFeature.Actions"}} - -
    - {{#each feature.actions}} - {{> 'systems/daggerheart/templates/sheets/items/subclass/parts/subclass-feature.hbs' level=../level type="action" id=this._id feature=this}} - {{/each}} -
    -
    - -
    - {{localize "DAGGERHEART.Sheets.Subclass.SubclassFeature.Effects"}} - -
    - {{#each feature.effects}} - {{> 'systems/daggerheart/templates/sheets/items/subclass/parts/subclass-feature.hbs' level=../level type="effect" id=this.id feature=this}} - {{/each}} -
    -
    -
    -