Moved RefreshFeatures to utils and added a proper description

This commit is contained in:
WBHarry 2026-03-07 00:06:12 +01:00
parent 17aa0680d2
commit 92d8c2ca18
2 changed files with 115 additions and 92 deletions

View file

@ -1,4 +1,4 @@
import { refreshIsAllowed } from '../../../helpers/utils.mjs'; import { RefreshFeatures } from '../../../helpers/utils.mjs';
const { HandlebarsApplicationMixin } = foundry.applications.api; const { HandlebarsApplicationMixin } = foundry.applications.api;
const { AbstractSidebarTab } = foundry.applications.sidebar; const { AbstractSidebarTab } = foundry.applications.sidebar;
@ -54,73 +54,6 @@ export default class DaggerheartMenu extends HandlebarsApplicationMixin(Abstract
return context; return context;
} }
async getRefreshables(types) {
const refreshedActors = {};
for (let actor of game.actors) {
if (['character', 'adversary'].includes(actor.type) && actor.prototypeToken.actorLink) {
const updates = {};
for (let item of actor.items) {
if (item.system.metadata?.hasResource && refreshIsAllowed(types, item.system.resource?.recovery)) {
if (!refreshedActors[actor.id])
refreshedActors[actor.id] = { name: actor.name, img: actor.img, refreshed: new Set() };
refreshedActors[actor.id].refreshed.add(
game.i18n.localize(CONFIG.DH.GENERAL.refreshTypes[item.system.resource.recovery].label)
);
if (!updates[item.id]?.system) updates[item.id] = { system: {} };
const increasing =
item.system.resource.progression === CONFIG.DH.ITEM.itemResourceProgression.increasing.id;
updates[item.id].system = {
...updates[item.id].system,
'resource.value': increasing
? 0
: Roll.replaceFormulaData(item.system.resource.max, actor.getRollData())
};
}
if (item.system.metadata?.hasActions) {
const refreshTypes = new Set();
const actions = item.system.actions.filter(action => {
if (refreshIsAllowed(types, action.uses.recovery)) {
refreshTypes.add(action.uses.recovery);
return true;
}
return false;
});
if (actions.length === 0) continue;
if (!refreshedActors[actor.id])
refreshedActors[actor.id] = { name: actor.name, img: actor.img, refreshed: new Set() };
refreshedActors[actor.id].refreshed.add(
...refreshTypes.map(type => game.i18n.localize(CONFIG.DH.GENERAL.refreshTypes[type].label))
);
if (!updates[item.id]?.system) updates[item.id] = { system: {} };
updates[item.id].system = {
...updates[item.id].system,
...actions.reduce(
(acc, action) => {
acc.actions[action.id] = { 'uses.value': 0 };
return acc;
},
{ actions: updates[item.id].system.actions ?? {} }
)
};
}
}
for (let key in updates) {
const update = updates[key];
await actor.items.get(key).update(update);
}
}
}
return refreshedActors;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Application Clicks Actions */ /* Application Clicks Actions */
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -133,30 +66,9 @@ export default class DaggerheartMenu extends HandlebarsApplicationMixin(Abstract
static async #refreshActors() { static async #refreshActors() {
const refreshKeys = Object.keys(this.refreshSelections).filter(key => this.refreshSelections[key].selected); const refreshKeys = Object.keys(this.refreshSelections).filter(key => this.refreshSelections[key].selected);
await this.getRefreshables(refreshKeys); await RefreshFeatures(refreshKeys);
const types = refreshKeys.map(x => this.refreshSelections[x].label).join(', ');
ui.notifications.info(
game.i18n.format('DAGGERHEART.UI.Notifications.gmMenuRefresh', {
types: `[${types}]`
})
);
this.refreshSelections = DaggerheartMenu.defaultRefreshSelections(); this.refreshSelections = DaggerheartMenu.defaultRefreshSelections();
const cls = getDocumentClass('ChatMessage');
const msg = {
user: game.user.id,
content: await foundry.applications.handlebars.renderTemplate(
'systems/daggerheart/templates/ui/chat/refreshMessage.hbs',
{
types: types
}
),
title: game.i18n.localize('DAGGERHEART.UI.Chat.refreshMessage.title'),
speaker: cls.getSpeaker()
};
cls.create(msg);
this.render(); this.render();
} }
} }

View file

@ -472,7 +472,7 @@ export function refreshIsAllowed(allowedTypes, typeToCheck) {
case CONFIG.DH.GENERAL.refreshTypes.scene.id: case CONFIG.DH.GENERAL.refreshTypes.scene.id:
case CONFIG.DH.GENERAL.refreshTypes.session.id: case CONFIG.DH.GENERAL.refreshTypes.session.id:
case CONFIG.DH.GENERAL.refreshTypes.longRest.id: case CONFIG.DH.GENERAL.refreshTypes.longRest.id:
return allowedTypes.includes(typeToCheck); return allowedTypes.includes?.(typeToCheck) ?? allowedTypes.has(typeToCheck);
case CONFIG.DH.GENERAL.refreshTypes.shortRest.id: case CONFIG.DH.GENERAL.refreshTypes.shortRest.id:
return allowedTypes.some( return allowedTypes.some(
x => x =>
@ -557,3 +557,114 @@ export function calculateExpectedValue(formulaOrTerms) {
: [formulaOrTerms]; : [formulaOrTerms];
return terms.reduce((r, t) => r + (t.bonus ?? 0) + (t.diceQuantity ? (t.diceQuantity * (t.faces + 1)) / 2 : 0), 0); return terms.reduce((r, t) => r + (t.bonus ?? 0) + (t.diceQuantity ? (t.diceQuantity * (t.faces + 1)) / 2 : 0), 0);
} }
/**
* Refreshes character and/or adversary resources.
* @param { string[] } refreshTypes Which type of features to refresh using IDs from CONFIG.DH.GENERAL.refreshTypes
* @param { string[] = ['character', 'adversary'] } actorTypes Which actor types should refresh their features. Defaults to character and adversary.
* @param { boolean = true } sendRefreshMessage If a chat message should be created detailing the refresh
* @return { Actor[] } The actors that had their features refreshed
*/
export async function RefreshFeatures(
refreshTypes = [],
actorTypes = ['character', 'adversary'],
sendNotificationMessage = true,
sendRefreshMessage = true
) {
const refreshedActors = {};
for (let actor of game.actors) {
if (actorTypes.includes(actor.type) && actor.prototypeToken.actorLink) {
const updates = {};
for (let item of actor.items) {
if (
item.system.metadata?.hasResource &&
refreshIsAllowed(refreshTypes, item.system.resource?.recovery)
) {
if (!refreshedActors[actor.id])
refreshedActors[actor.id] = { name: actor.name, img: actor.img, refreshed: new Set() };
refreshedActors[actor.id].refreshed.add(
game.i18n.localize(CONFIG.DH.GENERAL.refreshTypes[item.system.resource.recovery].label)
);
if (!updates[item.id]?.system) updates[item.id] = { system: {} };
const increasing =
item.system.resource.progression === CONFIG.DH.ITEM.itemResourceProgression.increasing.id;
updates[item.id].system = {
...updates[item.id].system,
'resource.value': increasing
? 0
: game.system.api.documents.DhActiveEffect.effectSafeEval(
Roll.replaceFormulaData(item.system.resource.max, actor.getRollData())
)
};
}
if (item.system.metadata?.hasActions) {
const usedTypes = new Set();
const actions = item.system.actions.filter(action => {
if (refreshIsAllowed(refreshTypes, action.uses.recovery)) {
usedTypes.add(action.uses.recovery);
return true;
}
return false;
});
if (actions.length === 0) continue;
if (!refreshedActors[actor.id])
refreshedActors[actor.id] = { name: actor.name, img: actor.img, refreshed: new Set() };
refreshedActors[actor.id].refreshed.add(
...usedTypes.map(type => game.i18n.localize(CONFIG.DH.GENERAL.refreshTypes[type].label))
);
if (!updates[item.id]?.system) updates[item.id] = { system: {} };
updates[item.id].system = {
...updates[item.id].system,
...actions.reduce(
(acc, action) => {
acc.actions[action.id] = { 'uses.value': 0 };
return acc;
},
{ actions: updates[item.id].system.actions ?? {} }
)
};
}
}
for (let key in updates) {
const update = updates[key];
await actor.items.get(key).update(update);
}
}
}
const types = refreshTypes.map(x => game.i18n.localize(CONFIG.DH.GENERAL.refreshTypes[x].label)).join(', ');
if (sendNotificationMessage) {
ui.notifications.info(
game.i18n.format('DAGGERHEART.UI.Notifications.gmMenuRefresh', {
types: `[${types}]`
})
);
}
if (sendRefreshMessage) {
const cls = getDocumentClass('ChatMessage');
const msg = {
user: game.user.id,
content: await foundry.applications.handlebars.renderTemplate(
'systems/daggerheart/templates/ui/chat/refreshMessage.hbs',
{
types: types
}
),
title: game.i18n.localize('DAGGERHEART.UI.Chat.refreshMessage.title'),
speaker: cls.getSpeaker()
};
cls.create(msg);
}
return refreshedActors;
}