diff --git a/lang/en.json b/lang/en.json index d3d707d6..8e60a81b 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1983,6 +1983,7 @@ "inactiveEffects": "Inactive Effects", "inventory": "Inventory", "itemResource": "Item Resource", + "itemQuantity": "Item Quantity", "items": "Items", "label": "Label", "level": "Level", diff --git a/module/applications/dialogs/d20RollDialog.mjs b/module/applications/dialogs/d20RollDialog.mjs index ed8fd6a1..6c227152 100644 --- a/module/applications/dialogs/d20RollDialog.mjs +++ b/module/applications/dialogs/d20RollDialog.mjs @@ -1,4 +1,4 @@ -import { abilities } from "../../config/actorConfig.mjs"; +import { abilities } from '../../config/actorConfig.mjs'; const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api; @@ -83,7 +83,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio ); context.costs = updatedCosts.map(x => ({ ...x, - label: x.keyIsID + label: x.itemId ? this.action.parent.parent.name : game.i18n.localize(CONFIG.DH.GENERAL.abilityCosts[x.key].label) })); @@ -115,7 +115,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio context.isLite = this.config.roll?.lite; context.extraFormula = this.config.extraFormula; context.formula = this.roll.constructFormula(this.config); - if(this.actor.system.traits) context.abilities = this.getTraitModifiers(); + if (this.actor.system.traits) context.abilities = this.getTraitModifiers(); context.showReaction = !this.config.roll?.type && context.rollType === 'DualityRoll'; context.reactionOverride = this.reactionOverride; @@ -124,12 +124,15 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio } getTraitModifiers() { - return Object.values(abilities).map(a => ({ id: a.id, label: `${game.i18n.localize(a.label)} (${this.actor.system.traits[a.id]?.value.signedString() ?? 0})` })) + return Object.values(abilities).map(a => ({ + id: a.id, + label: `${game.i18n.localize(a.label)} (${this.actor.system.traits[a.id]?.value.signedString() ?? 0})` + })); } static updateRollConfiguration(event, _, formData) { const { ...rest } = foundry.utils.expandObject(formData.object); - + this.config.selectedRollMode = rest.selectedRollMode; if (this.config.costs) { @@ -141,7 +144,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio this.roll[key] = value; }); } - if(rest.hasOwnProperty("trait")) { + if (rest.hasOwnProperty('trait')) { this.config.roll.trait = rest.trait; this.config.title = game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { ability: game.i18n.localize(abilities[this.config.roll.trait]?.label) @@ -169,14 +172,14 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio this.config.costs.indexOf(this.config.costs.find(c => c.extKey === button.dataset.key)) > -1 ? this.config.costs.filter(x => x.extKey !== button.dataset.key) : [ - ...this.config.costs, - { - extKey: button.dataset.key, - key: this.config?.data?.parent?.isNPC ? 'fear' : 'hope', - value: 1, - name: this.config.data?.experiences?.[button.dataset.key]?.name - } - ]; + ...this.config.costs, + { + extKey: button.dataset.key, + key: this.config?.data?.parent?.isNPC ? 'fear' : 'hope', + value: 1, + name: this.config.data?.experiences?.[button.dataset.key]?.name + } + ]; this.render(); } diff --git a/module/applications/sheets-configs/action-config.mjs b/module/applications/sheets-configs/action-config.mjs index ea3c6f31..96b6cc48 100644 --- a/module/applications/sheets-configs/action-config.mjs +++ b/module/applications/sheets-configs/action-config.mjs @@ -132,12 +132,19 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) { const options = foundry.utils.deepClone(CONFIG.DH.GENERAL.abilityCosts); const resource = this.action.parent.resource; if (resource) { - options[this.action.parent.parent.id] = { + options.resource = { label: 'DAGGERHEART.GENERAL.itemResource', group: 'Global' }; } + if (this.action.parent.metadata.isQuantifiable) { + options.quantity = { + label: 'DAGGERHEART.GENERAL.itemQuantity', + group: 'Global' + }; + } + return options; } @@ -164,13 +171,14 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) { _prepareSubmitData(_event, formData) { const submitData = foundry.utils.expandObject(formData.object); + + const itemAbilityCostKeys = Object.keys(CONFIG.DH.GENERAL.itemAbilityCosts); for (const keyPath of this.constructor.CLEAN_ARRAYS) { const data = foundry.utils.getProperty(submitData, keyPath); const dataValues = data ? Object.values(data) : []; if (keyPath === 'cost') { for (var value of dataValues) { - const item = this.action.parent.parent.id === value.key; - value.keyIsID = Boolean(item); + value.itemId = itemAbilityCostKeys.includes(value.key) ? this.action.parent.parent.id : null; } } diff --git a/module/applications/sheets/actors/companion.mjs b/module/applications/sheets/actors/companion.mjs index 82aee312..b353adbb 100644 --- a/module/applications/sheets/actors/companion.mjs +++ b/module/applications/sheets/actors/companion.mjs @@ -84,8 +84,7 @@ export default class DhCompanionSheet extends DHBaseActorSheet { return { key: c.key, value: (c.total ?? c.value) * (resource.isReversed ? 1 : -1), - target: resource.target, - keyIsID: resource.keyIsID + target: resource.target }; }); diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index 9e88d7a7..d4e6318e 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -561,6 +561,19 @@ export const refreshTypes = { } }; +export const itemAbilityCosts = { + resource: { + id: 'resource', + label: 'DAGGERHEART.GENERAL.resource', + group: 'Global' + }, + quantity: { + id: 'quantity', + label: 'DAGGERHEART.GENERAL.quantity', + group: 'Global' + } +}; + export const abilityCosts = { hitPoints: { id: 'hitPoints', @@ -587,16 +600,7 @@ export const abilityCosts = { label: 'Fear', group: 'TYPES.Actor.adversary' }, - resource: { - id: 'resource', - label: 'DAGGERHEART.GENERAL.resource', - group: 'Global' - }, - quantity: { - id: 'quantity', - label: 'DAGGERHEART.GENERAL.quantity', - group: 'Global' - } + resource: itemAbilityCosts.resource }; export const countdownTypes = { diff --git a/module/data/fields/action/costField.mjs b/module/data/fields/action/costField.mjs index 5a23d167..2371323f 100644 --- a/module/data/fields/action/costField.mjs +++ b/module/data/fields/action/costField.mjs @@ -46,16 +46,11 @@ export default class CostField extends fields.ArrayField { if (this.parent?.parent) { for (var cost of config.costs) { - if (cost.keyIsID) { + if (cost.itemId) { usefulResources[cost.key] = { value: cost.value, target: this.parent.parent, - keyIsID: true - }; - } else if (cost.key === 'quantity') { - usefulResources[cost.key] = { - value: cost.value, - target: this.parent.parent + itemId: cost.itemId }; } } @@ -74,7 +69,7 @@ export default class CostField extends fields.ArrayField { key: c.key, value: (c.total ?? c.value) * (resource.isReversed ? 1 : -1), target: resource.target, - keyIsID: resource.keyIsID + itemId: resource.itemId }); return a; } @@ -107,7 +102,12 @@ export default class CostField extends fields.ArrayField { */ static calcCosts(costs) { const resources = CostField.getResources.call(this, costs); - return costs.map(c => { + let filteredCosts = costs; + if (this.parent.metadata.isQuantifiable && this.parent.consumeOnUse === false) { + filteredCosts = filteredCosts.filter(c => c.key !== 'quantity'); + } + + return filteredCosts.map(c => { c.scale = c.scale ?? 0; c.step = c.step ?? 1; c.total = c.value + c.scale * c.step; @@ -167,17 +167,8 @@ export default class CostField extends fields.ArrayField { actorResources.hope = foundry.utils.deepClone(this.actor.system.partner.system.resources.hope); const itemResources = {}; for (let itemResource of costs) { - if (itemResource.keyIsID) { - itemResources[itemResource.key] = { - value: this.parent.resource.value ?? 0, - max: CostField.formatMax.call(this, this.parent?.resource?.max) - }; - } - if (itemResource.key === 'quantity') { - itemResources[itemResource.key] = { - value: this.parent.quantity ?? 0, - max: null - }; + if (itemResource.itemId) { + itemResources[itemResource.key] = CostField.getItemIdCostResource.bind(this)(itemResource); } } @@ -187,6 +178,38 @@ export default class CostField extends fields.ArrayField { }; } + static getItemIdCostResource(itemResource) { + switch (itemResource.key) { + case CONFIG.DH.GENERAL.itemAbilityCosts.resource.id: + return { + value: this.parent.resource.value ?? 0, + max: CostField.formatMax.call(this, this.parent?.resource?.max) + }; + case CONFIG.DH.GENERAL.itemAbilityCosts.quantity.id: + return { + value: this.parent.quantity ?? 0, + max: this.parent.quantity ?? 0 + }; + default: + return { value: 0, max: 0 }; + } + } + + static getItemIdCostUpdate(r) { + switch (r.key) { + case CONFIG.DH.GENERAL.itemAbilityCosts.resource.id: + return { + 'system.resource.value': r.target.system.resource.value + r.value + }; + case CONFIG.DH.GENERAL.itemAbilityCosts.quantity.id: + return { + 'system.quantity': r.target.system.quantity + r.value + }; + default: + return {}; + } + } + /** * * @param {*} costs diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 950ed621..f6c6a676 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -659,12 +659,10 @@ export default class DhpActor extends Actor { }; resources.forEach(r => { - if (r.keyIsID) { + if (r.itemId) { updates.items[r.key] = { target: r.target, - resources: { - 'system.resource.value': r.target.system.resource.value + r.value - } + resources: game.system.api.fields.ActionFields.CostField.getItemIdCostUpdate(r) }; } else { switch (r.key) {