diff --git a/module/applications/dialogs/groupRollDialog.mjs b/module/applications/dialogs/groupRollDialog.mjs index 58ed03b4..7196d848 100644 --- a/module/applications/dialogs/groupRollDialog.mjs +++ b/module/applications/dialogs/groupRollDialog.mjs @@ -483,13 +483,13 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat const resourceMap = new ResourceUpdateMap(actor); if (totalRoll.isCritical) { resourceMap.addResources([ - { key: 'stress', value: -1 }, - { key: 'hope', value: 1 } + { key: 'stress', value: -1, total: 1 }, + { key: 'hope', value: 1, total: 1 } ]); } else if (totalRoll.withHope) { - resourceMap.addResources([{ key: 'hope', value: 1 }]); + resourceMap.addResources([{ key: 'hope', value: 1, total: 1 }]); } else { - resourceMap.addResources([{ key: 'fear', value: 1 }]); + resourceMap.addResources([{ key: 'fear', value: 1, total: 1 }]); } resourceMap.updateResources(); diff --git a/module/applications/dialogs/tagTeamDialog.mjs b/module/applications/dialogs/tagTeamDialog.mjs index 5c83f075..b2ce0258 100644 --- a/module/applications/dialogs/tagTeamDialog.mjs +++ b/module/applications/dialogs/tagTeamDialog.mjs @@ -752,7 +752,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio /* Handle resource updates from the finished TagTeamRoll */ const tagTeamData = this.party.system.tagTeam; - const fearUpdate = { key: 'fear', value: null, enabled: true }; + const fearUpdate = { key: 'fear', value: null, total: null, enabled: true }; for (let memberId in tagTeamData.members) { const resourceUpdates = []; const rollGivesHope = finalRoll.isCritical || finalRoll.withHope; @@ -762,11 +762,11 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio ? 1 - tagTeamData.initiator.cost : -tagTeamData.initiator.cost : 1; - resourceUpdates.push({ key: 'hope', value: value, enabled: true }); + resourceUpdates.push({ key: 'hope', value: value, total: -value, enabled: true }); } else if (rollGivesHope) { - resourceUpdates.push({ key: 'hope', value: 1, enabled: true }); + resourceUpdates.push({ key: 'hope', value: 1, total: -1, enabled: true }); } - if (finalRoll.isCritical) resourceUpdates.push({ key: 'stress', value: -1, enabled: true }); + if (finalRoll.isCritical) resourceUpdates.push({ key: 'stress', value: -1, total: 1, enabled: true }); if (finalRoll.withFear) { fearUpdate.value = fearUpdate.value === null ? 1 : fearUpdate.value + 1; fearUpdate.total = fearUpdate.total === null ? -1 : fearUpdate.total - 1; diff --git a/module/applications/sheets-configs/adversary-settings.mjs b/module/applications/sheets-configs/adversary-settings.mjs index 583f37b7..57405675 100644 --- a/module/applications/sheets-configs/adversary-settings.mjs +++ b/module/applications/sheets-configs/adversary-settings.mjs @@ -54,7 +54,7 @@ export default class DHAdversarySettings extends DHBaseActorSettings { async _prepareContext(options) { const context = await super._prepareContext(options); - const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm); + 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) @@ -97,4 +97,32 @@ 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]); + } + } } diff --git a/module/applications/sheets-configs/environment-settings.mjs b/module/applications/sheets-configs/environment-settings.mjs index d6744eb8..6d74f9c6 100644 --- a/module/applications/sheets-configs/environment-settings.mjs +++ b/module/applications/sheets-configs/environment-settings.mjs @@ -15,7 +15,7 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings { dragDrop: [ { dragSelector: null, dropSelector: '.category-container' }, { dragSelector: null, dropSelector: '.tab.features' }, - { dragSelector: '.feature-item, .inventory-item[data-type="adversary"]', dropSelector: null } + { dragSelector: '.feature-item', dropSelector: null } ] }; @@ -110,30 +110,33 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings { } async _onDragStart(event) { - 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); + 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 doc = await fromUuid(data.uuid); - if (doc?.type === 'adversary' && event.target.closest('.category-container')) { + 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 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); - if (!current.includes(doc.uuid)) { - await this.actor.update({ [path]: [...current, doc.uuid] }); - } - return; + 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(); } - - return super._onDrop(event); } } diff --git a/module/applications/sheets-configs/npc-settings.mjs b/module/applications/sheets-configs/npc-settings.mjs index d2132a91..c187877c 100644 --- a/module/applications/sheets-configs/npc-settings.mjs +++ b/module/applications/sheets-configs/npc-settings.mjs @@ -52,4 +52,34 @@ export default class DHNPCSettings extends DHBaseActorSettings { 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]); + } + } } diff --git a/module/applications/sheets/actors/adversary.mjs b/module/applications/sheets/actors/adversary.mjs index 85380392..f39bec0c 100644 --- a/module/applications/sheets/actors/adversary.mjs +++ b/module/applications/sheets/actors/adversary.mjs @@ -103,7 +103,7 @@ export default class AdversarySheet extends DHBaseActorSheet { context.resources.stress.emptyPips = context.resources.stress.max < maxResource ? maxResource - context.resources.stress.max : 0; - const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm); + const featureForms = ['passive', 'action', 'reaction']; context.features = this.document.system.features.sort((a, b) => a.system.featureForm !== b.system.featureForm ? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm) diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index 3a60e7ca..f0f8326f 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -809,7 +809,7 @@ export default class CharacterSheet extends DHBaseActorSheet { /* This could be avoided by baking config.costs into config.resourceUpdates. Didn't feel like messing with it at the time */ const costResources = - result.costs?.filter(x => x.enabled).map(cost => ({ ...cost, value: -cost.value })) || + result.costs?.filter(x => x.enabled).map(cost => ({ ...cost, value: -cost.value, total: -cost.total })) || {}; result.resourceUpdates.addResources(costResources); await result.resourceUpdates.updateResources(); diff --git a/module/applications/sheets/actors/environment.mjs b/module/applications/sheets/actors/environment.mjs index 9a88dba6..f8ff74a6 100644 --- a/module/applications/sheets/actors/environment.mjs +++ b/module/applications/sheets/actors/environment.mjs @@ -78,6 +78,7 @@ export default class DhpEnvironment extends DHBaseActorSheet { switch (partId) { case 'header': await this._prepareHeaderContext(context, options); + break; case 'features': await this._prepareFeaturesContext(context, options); diff --git a/module/applications/sheets/api/actor-setting.mjs b/module/applications/sheets/api/actor-setting.mjs index 65497cec..738f7002 100644 --- a/module/applications/sheets/api/actor-setting.mjs +++ b/module/applications/sheets/api/actor-setting.mjs @@ -1,15 +1,13 @@ import DHApplicationMixin from './application-mixin.mjs'; -const { ActorSheetV2 } = foundry.applications.sheets; +const { DocumentSheetV2 } = foundry.applications.api; -/** - * @typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction - */ +/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */ /** * Base settings sheet for Daggerheart actors. - * @extends {DHApplicationMixin} + * @extends {DHApplicationMixin} */ -export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2) { +export default class DHBaseActorSettings extends DHApplicationMixin(DocumentSheetV2) { /**@inheritdoc */ static DEFAULT_OPTIONS = { classes: ['dialog'], @@ -36,7 +34,7 @@ export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2 return options; } - /** @returns {foundry.documents.Actor} */ + /**@returns {foundry.documents.Actor} */ get actor() { return this.document; } @@ -75,29 +73,4 @@ export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2 return context; } - - async _onDragStart(event) { - const featureItemEl = event.currentTarget.closest('.feature-item'); - const feature = this.actor.items.get(featureItemEl?.dataset.itemId); - if (feature && event.target.closest('.tab.features')) { - const featureData = { ...feature.toDragData(), fromInternal: true }; - event.dataTransfer.setData('text/plain', JSON.stringify(featureData)); - event.dataTransfer.setDragImage(featureItemEl.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 super._onDrop(event); - } - - const itemData = item.toObject(); - delete itemData._id; - await this.actor.createEmbeddedDocuments('Item', [itemData]); - } - } } diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index f3d612e9..752dc80b 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -381,35 +381,12 @@ export default function DHApplicationMixin(Base) { * @protected */ _onDrop(event) { - // Potentially handle subclasses that dont descend from actor/item sheet. + // Fallback to super, but note that config sheets don't have this option + // We still need this to avoid setting apps having issues event.stopPropagation(); return super._onDrop?.(event); } - /** @inheritdoc */ - _onSortItem(event, item) { - // If we are dragging a feature past its allowed feature form, put it in the front or in the back - const doc = this.actor.items.get(item.id); - const dropTargetEl = event.target.closest('[data-item-id]'); - const dropTarget = this.actor.items.get(dropTargetEl?.dataset.itemId); - if (doc?.type === 'feature' && dropTarget?.type === 'feature' && doc.system.featureForm !== dropTarget.system.featureForm) { - const siblings = this.actor.itemTypes.feature - .filter(f => f.system.featureForm === doc.system.featureForm) - .sort((a, b) => a.sort - b.sort); - if (siblings.length > 1) { - const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm); - const thisFeatureIdx = featureForms.indexOf(doc.system.featureForm); - const targetFeatureIdx = featureForms.indexOf(dropTarget.system.featureForm); - const target = targetFeatureIdx < thisFeatureIdx ? siblings[0] : siblings.at(-1); - const sortUpdates = foundry.utils.performIntegerSort(doc, { target, siblings }); - const updateData = sortUpdates.map(u => ({ ...u.update, _id: u.target._id })); - return this.actor.updateEmbeddedDocuments('Item', updateData); - } - } - - return super._onSortItem?.(event, item); - } - /* -------------------------------------------- */ /* Context Menu */ /* -------------------------------------------- */ diff --git a/module/data/action/baseAction.mjs b/module/data/action/baseAction.mjs index ea4361b9..c71f5ef9 100644 --- a/module/data/action/baseAction.mjs +++ b/module/data/action/baseAction.mjs @@ -459,7 +459,8 @@ export class ResourceUpdateMap extends Map { } else if (!existing?.clear) { this.set(resource.key, { ...existing, - value: existing.value + (resource.value ?? 0) + value: existing.value + (resource.value ?? 0), + total: existing.total + (resource.total ?? 0) }); } } diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 3b12da6f..8ae78ff8 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -315,12 +315,7 @@ export default class DhCharacter extends DhCreature { label: 'DAGGERHEART.ACTORS.Character.defaultDisadvantageDice' }) }) - }), - /** Accumulated armor score from all sources */ - armorScore: new fields.SchemaField({ - value: new fields.NumberField(), - max: new fields.NumberField() - }, { persisted: false }) + }) }; } diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index 70e98242..1cfed094 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -334,15 +334,15 @@ export default class DualityRoll extends D20Roll { const fear = (config.roll.result.duality === -1 ? 1 : 0) - (config.rerolledRoll.result.duality === -1 ? 1 : 0); - if (hope !== 0) updates.push({ key: 'hope', value: hope, enabled: true }); - if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, enabled: true }); - if (fear !== 0) updates.push({ key: 'fear', value: fear, enabled: true }); + if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true }); + if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true }); + if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true }); } } else { if (config.roll.isCritical || config.roll.result.duality === 1) - updates.push({ key: 'hope', value: 1, enabled: true }); - if (config.roll.isCritical) updates.push({ key: 'stress', value: -1, enabled: true }); - if (config.roll.result.duality === -1) updates.push({ key: 'fear', value: 1, enabled: true }); + updates.push({ key: 'hope', value: 1, total: -1, enabled: true }); + if (config.roll.isCritical) updates.push({ key: 'stress', value: -1, total: 1, enabled: true }); + if (config.roll.result.duality === -1) updates.push({ key: 'fear', value: 1, total: -1, enabled: true }); } if (updates.length) { diff --git a/module/dice/helpers.mjs b/module/dice/helpers.mjs index 5f8a7bbb..35adb8b7 100644 --- a/module/dice/helpers.mjs +++ b/module/dice/helpers.mjs @@ -9,9 +9,9 @@ export function updateResourcesForDualityReroll(oldDuality, newDuality, actor) { const stress = (newDuality === 0 ? 1 : 0) - (oldDuality === 0 ? 1 : 0); const fear = (newDuality === -1 ? 1 : 0) - (oldDuality === -1 ? 1 : 0); - if (hope !== 0) updates.push({ key: 'hope', value: hope, enabled: true }); - if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, enabled: true }); - if (fear !== 0) updates.push({ key: 'fear', value: fear, enabled: true }); + if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true }); + if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true }); + if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true }); const resourceUpdates = new ResourceUpdateMap(actor); resourceUpdates.addResources(updates); diff --git a/templates/sheets-settings/adversary-settings/features.hbs b/templates/sheets-settings/adversary-settings/features.hbs index 3e0ed654..2f2f5f47 100644 --- a/templates/sheets-settings/adversary-settings/features.hbs +++ b/templates/sheets-settings/adversary-settings/features.hbs @@ -10,7 +10,7 @@ {{localize tabs.features.label}}