Merge branch 'main' into feature/granular-action-outcomes

This commit is contained in:
WBHarry 2026-05-10 18:21:10 +02:00
commit f260d221a8
36 changed files with 540 additions and 348 deletions

View file

@ -200,7 +200,7 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
const features = [];
for (let f of this.features) {
const fBase = f.item ?? f;
const feature = fBase.system ? fBase : await foundry.utils.fromUuid(fBase.uuid);
const feature = fBase.pack ? await foundry.utils.fromUuid(fBase.uuid) : fBase;
features.push(
foundry.utils.mergeObject(
feature.toObject(),

View file

@ -30,7 +30,6 @@ export default class DHClass extends BaseDataItem {
}),
evasion: new fields.NumberField({ initial: 0, integer: true, label: 'DAGGERHEART.GENERAL.evasion' }),
features: new ItemLinkFields(),
subclasses: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false }),
inventory: new fields.SchemaField({
take: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false }),
choiceA: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false }),
@ -70,6 +69,24 @@ export default class DHClass extends BaseDataItem {
return this.features.filter(x => x.type === CONFIG.DH.ITEM.featureSubTypes.class).map(x => x.item);
}
async fetchSubclasses() {
const uuids = [this.parent.uuid, this.parent._stats?.compendiumSource].filter(u => !!u);
const subclasses = game.items.filter(x => x.type === 'subclass' && uuids.includes(x.system.linkedClass));
for (const pack of game.packs) {
const indexes = await pack.getIndex({ fields: ['system.linkedClass'] });
for (const index of indexes) {
if (index.type !== 'subclass') continue;
if (!uuids.includes(index.system?.linkedClass)) continue;
if (subclasses.find(x => x.uuid === index.uuid)) continue;
const subclass = await foundry.utils.fromUuid(index.uuid);
subclasses.push(subclass);
}
}
return subclasses;
}
async _preCreate(data, options, user) {
if (this.actor?.type === 'character') {
const levelupAuto = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).levelupAuto;

View file

@ -28,7 +28,7 @@ export default class DHSubclass extends BaseDataItem {
features: new ItemLinkFields(),
featureState: new fields.NumberField({ required: true, initial: 1, min: 1 }),
isMulticlass: new fields.BooleanField({ initial: false }),
linkedClass: new ForeignDocumentUUIDField({ type: 'Item', nullable: true, initial: null })
linkedClass: new fields.DocumentUUIDField({ type: 'Item', nullable: true, initial: null })
};
}
@ -83,7 +83,8 @@ export default class DHSubclass extends BaseDataItem {
ui.notifications.warn(game.i18n.localize('DAGGERHEART.UI.Notifications.missingClass'));
return false;
}
if (actorClass.system.subclasses.every(x => x.uuid !== dataUuid)) {
if ((await actorClass.system.fetchSubclasses()).every(x => x.uuid !== dataUuid)) {
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.subclassNotInClass'));
return false;
}

View file

@ -1,4 +1,5 @@
import { defaultRestOptions } from '../../config/generalConfig.mjs';
import { resetAndRerenderActors } from '../../helpers/utils.mjs';
import { ActionsField } from '../fields/actionField.mjs';
const currencyField = (initial, label, icon) =>
@ -209,7 +210,7 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
}
this.refreshConfig();
this.#resetActors();
resetAndRerenderActors();
}
/** Update config values based on homebrew data. Make sure the references don't change */
@ -230,29 +231,6 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
});
}
}
/**
* Triggers a reset and non-forced re-render on all given actors (if given)
* or all world actors and actors in all scenes to show immediate results for a changed setting.
*/
#resetActors() {
const actors = new Set(
[
game.actors.contents,
game.scenes.contents.flatMap(s => s.tokens.contents).flatMap(t => t.actor ?? [])
].flat()
);
for (const actor of actors) {
for (const app of Object.values(actor.apps)) {
for (const element of app.element?.querySelectorAll('prose-mirror.active')) {
element.open = false; // This triggers a save
}
}
actor.reset();
actor.render();
}
}
}
export class Resource extends foundry.abstract.DataModel {

View file

@ -1,3 +1,5 @@
import { resetAndRerenderActors } from '../../helpers/utils.mjs';
export default class DhMetagaming extends foundry.abstract.DataModel {
static defineSchema() {
const fields = foundry.data.fields;
@ -6,7 +8,24 @@ export default class DhMetagaming extends foundry.abstract.DataModel {
initial: false,
label: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hideObserverPermissionInChat.label',
hint: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hideObserverPermissionInChat.hint'
}),
hidePartyStats: new fields.StringField({
initial: 'never',
label: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hidePartyStats.label',
hint: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hidePartyStats.hint',
required: true,
nullable: false,
choices: {
never: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hidePartyStats.choices.never',
players: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hidePartyStats.choices.players',
always: 'DAGGERHEART.SETTINGS.Metagaming.FIELDS.hidePartyStats.choices.always'
}
})
};
}
/** Invoked by the setting when data changes */
handleChange() {
resetAndRerenderActors();
}
}