diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index e99c6ff1..9e88d7a7 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -586,6 +586,16 @@ export const abilityCosts = { id: 'fear', label: 'Fear', group: 'TYPES.Actor.adversary' + }, + resource: { + id: 'resource', + label: 'DAGGERHEART.GENERAL.resource', + group: 'Global' + }, + quantity: { + id: 'quantity', + label: 'DAGGERHEART.GENERAL.quantity', + group: 'Global' } }; diff --git a/module/data/fields/action/costField.mjs b/module/data/fields/action/costField.mjs index ca942909..5a23d167 100644 --- a/module/data/fields/action/costField.mjs +++ b/module/data/fields/action/costField.mjs @@ -5,7 +5,7 @@ export default class CostField extends fields.ArrayField { * Action Workflow order */ static order = 150; - + /** @inheritDoc */ constructor(options = {}, context = {}) { const element = new fields.SchemaField({ @@ -14,7 +14,7 @@ export default class CostField extends fields.ArrayField { required: true, initial: 'hope' }), - keyIsID: new fields.BooleanField(), + itemId: new fields.StringField({ nullable: true, initial: null }), value: new fields.NumberField({ nullable: true, initial: 1, min: 0 }), scalable: new fields.BooleanField({ initial: false }), step: new fields.NumberField({ nullable: true, initial: null }), @@ -34,17 +34,17 @@ export default class CostField extends fields.ArrayField { * @param {boolean} [successCost=false] Consume only resources configured as "On Success only" if not already consumed. */ static async execute(config, successCost = false) { - const actor= this.actor.system.partner ?? this.actor, + const actor = this.actor.system.partner ?? this.actor, usefulResources = { - ...foundry.utils.deepClone(actor.system.resources), - fear: { - value: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear), - max: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).maxFear, - reversed: false - } - }; + ...foundry.utils.deepClone(actor.system.resources), + fear: { + value: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear), + max: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).maxFear, + reversed: false + } + }; - if(this.parent?.parent) { + if (this.parent?.parent) { for (var cost of config.costs) { if (cost.keyIsID) { usefulResources[cost.key] = { @@ -52,6 +52,11 @@ export default class CostField extends fields.ArrayField { target: this.parent.parent, keyIsID: true }; + } else if (cost.key === 'quantity') { + usefulResources[cost.key] = { + value: cost.value, + target: this.parent.parent + }; } } } @@ -74,7 +79,7 @@ export default class CostField extends fields.ArrayField { return a; } }, []); - + await actor.modifyResource(resources); } @@ -95,10 +100,10 @@ export default class CostField extends fields.ArrayField { } /** - * + * * Must be called within Action context. - * @param {*} costs - * @returns + * @param {*} costs + * @returns */ static calcCosts(costs) { const resources = CostField.getResources.call(this, costs); @@ -121,7 +126,7 @@ export default class CostField extends fields.ArrayField { /** * Check if the current Actor currently has all needed resources. * Must be called within Action context. - * @param {*} costs + * @param {*} costs * @returns {boolean} */ static hasCost(costs) { @@ -153,8 +158,8 @@ export default class CostField extends fields.ArrayField { /** * Get all Actor resources + parent Item potential one. * Must be called within Action context. - * @param {*} costs - * @returns + * @param {*} costs + * @returns */ static getResources(costs) { const actorResources = foundry.utils.deepClone(this.actor.system.resources); @@ -168,6 +173,12 @@ export default class CostField extends fields.ArrayField { max: CostField.formatMax.call(this, this.parent?.resource?.max) }; } + if (itemResource.key === 'quantity') { + itemResources[itemResource.key] = { + value: this.parent.quantity ?? 0, + max: null + }; + } } return { @@ -177,9 +188,9 @@ export default class CostField extends fields.ArrayField { } /** - * - * @param {*} costs - * @returns + * + * @param {*} costs + * @returns */ static getRealCosts(costs) { const realCosts = costs?.length ? costs.filter(c => c.enabled) : []; diff --git a/module/systemRegistration/migrations.mjs b/module/systemRegistration/migrations.mjs index 134c8714..820dfed9 100644 --- a/module/systemRegistration/migrations.mjs +++ b/module/systemRegistration/migrations.mjs @@ -96,5 +96,60 @@ export async function runMigrations() { lastMigrationVersion = '1.1.1'; } + if (foundry.utils.isNewerVersion('1.2.0', lastMigrationVersion)) { + const lockedPacks = []; + const compendiumItems = []; + for (let pack of game.packs) { + if (pack.locked) { + lockedPacks.push(pack.collection); + await pack.configure({ locked: false }); + } + const documents = await pack.getDocuments(); + + compendiumItems.push(...documents.filter(x => x.system.metadata.hasActions)); + compendiumItems.push( + ...documents + .filter(x => x.items) + .flatMap(actor => actor.items.filter(x => x.system.metadata.hasActions)) + ); + } + + const worldItems = game.items.filter(x => x.system.metadata.hasActions); + const worldActorItems = Array.from(game.actors).flatMap(actor => + actor.items.filter(x => x.system.metadata.hasActions) + ); + + const validCostKeys = Object.keys(CONFIG.DH.GENERAL.abilityCosts); + for (let item of [...worldItems, ...worldActorItems, ...compendiumItems]) { + for (let action of item.system.actions) { + const resourceCostIndexes = Object.keys(action.cost).reduce( + (acc, index) => (!validCostKeys.includes(action.cost[index].key) ? [...acc, Number(index)] : acc), + [] + ); + if (resourceCostIndexes.length === 0) continue; + + await action.update({ + cost: action.cost.map((cost, index) => { + const { keyIsID, ...rest } = cost; + if (!resourceCostIndexes.includes(index)) return { ...rest }; + + return { + ...rest, + key: 'resource', + itemId: key + }; + }) + }); + } + } + + for (let packId of lockedPacks) { + const pack = game.packs.get(packId); + await pack.configure({ locked: true }); + } + + lastMigrationVersion = '1.2.0'; + } + await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LastMigrationVersion, lastMigrationVersion); } diff --git a/system.json b/system.json index 8e5a7610..4eeeff1a 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "id": "daggerheart", "title": "Daggerheart", "description": "An unofficial implementation of the Daggerheart system", - "version": "1.1.2", + "version": "1.2.0", "compatibility": { "minimum": "13", "verified": "13.347",