[Feature] Custom Homebrew Resources (#1718)

* Added resources to the Homebrew Menu

* Fixed translations

* .

* Inverted from isImage to isIcon. Should be more logical for users
This commit is contained in:
WBHarry 2026-03-10 18:46:19 +01:00 committed by GitHub
parent 023dda6806
commit 270345ee12
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 518 additions and 139 deletions

View file

@ -9,31 +9,34 @@ export default class DhCreature extends BaseDataActor {
return {
...super.defineSchema(),
resources: new fields.SchemaField({
...Object.values(CONFIG.DH.ACTOR[`${this.metadata.type}Resources`]).reduce((acc, resource) => {
if (resource.max !== undefined) {
acc[resource.id] = resourceField(
resource.max,
resource.initial,
resource.label,
resource.maxLabel
);
} else {
acc[resource.id] = new fields.SchemaField(
{
value: new fields.NumberField({
initial: resource.initial,
min: resource.min,
integer: true,
label: resource.label
}),
isReversed: new fields.BooleanField({ initial: resource.reverse })
},
{ label: resource.label }
);
}
...Object.values(CONFIG.DH.RESOURCE[`all${this.metadata.type.capitalize()}Resources`]()).reduce(
(acc, resource) => {
if (resource.max !== undefined) {
acc[resource.id] = resourceField(
resource.max,
resource.initial,
resource.label,
resource.maxLabel
);
} else {
acc[resource.id] = new fields.SchemaField(
{
value: new fields.NumberField({
initial: resource.initial,
min: resource.min,
integer: true,
label: resource.label
}),
isReversed: new fields.BooleanField({ initial: resource.reverse })
},
{ label: resource.label }
);
}
return acc;
}, {})
return acc;
},
{}
)
}),
advantageSources: new fields.ArrayField(new fields.StringField(), {
label: 'DAGGERHEART.ACTORS.Character.advantageSources.label',
@ -55,7 +58,7 @@ export default class DhCreature extends BaseDataActor {
prepareDerivedData() {
super.prepareDerivedData();
const resources = CONFIG.DH.ACTOR[`${this.parent.type}Resources`];
const resources = CONFIG.DH.RESOURCE[`all${this.parent.type.capitalize()}Resources`]();
if (resources) {
for (const [key, value] of Object.entries(this.resources)) {
value.label = resources[key]?.label;

View file

@ -16,7 +16,7 @@ const resourceField = (max = 0, initial = 0, label, maxLabel) =>
label:
maxLabel ??
game.i18n.format('DAGGERHEART.GENERAL.maxWithThing', { thing: game.i18n.localize(label) })
}),
})
},
{ label }
);

View file

@ -224,11 +224,7 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
const armorChanged =
changed.system?.marks?.value !== undefined && changed.system.marks.value !== this.marks.value;
if (armorChanged && autoSettings.resourceScrollTexts && this.parent.parent?.type === 'character') {
const armorData = getScrollTextData(
this.parent.parent,
changed.system.marks,
'armor',
);
const armorData = getScrollTextData(this.parent.parent, changed.system.marks, 'armor');
options.scrollingTextData = [armorData];
}

View file

@ -145,6 +145,16 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
description: new fields.StringField()
})
),
resources: new fields.TypedObjectField(
new fields.SchemaField({
resources: new fields.TypedObjectField(new fields.EmbeddedDataField(Resource))
}),
{
initial: {
character: { resources: {} }
}
}
),
itemFeatures: new fields.SchemaField({
weaponFeatures: new fields.TypedObjectField(
new fields.SchemaField({
@ -186,3 +196,64 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
return source;
}
}
export class Resource extends foundry.abstract.DataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
initial: new fields.NumberField({
required: true,
integer: true,
initial: 0,
min: 0,
label: 'DAGGERHEART.GENERAL.initial'
}),
max: new fields.NumberField({
nullable: true,
initial: null,
min: 0,
label: 'DAGGERHEART.GENERAL.max'
}),
label: new fields.StringField({ label: 'DAGGERHEART.GENERAL.label' }),
images: new fields.SchemaField({
full: imageIconField('fa solid fa-circle'),
empty: imageIconField('fa-regular fa-circle')
})
};
}
static getDefaultResourceData = label => {
const images = Resource.schema.fields.images.getInitialValue();
return {
initial: 0,
max: 0,
label: label ?? '',
images
};
};
static getDefaultImageData = imageKey => {
return Resource.schema.fields.images.fields[imageKey].getInitialValue();
};
}
const imageIconField = defaultValue =>
new foundry.data.fields.SchemaField(
{
value: new foundry.data.fields.StringField({
initial: defaultValue,
label: 'DAGGERHEART.SETTINGS.Homebrew.FIELDS.resources.resources.value.label'
}),
isIcon: new foundry.data.fields.BooleanField({
required: true,
initial: true,
label: 'DAGGERHEART.SETTINGS.Homebrew.FIELDS.resources.resources.isIcon.label'
}),
noColorFilter: new foundry.data.fields.BooleanField({
required: true,
initial: false,
label: 'DAGGERHEART.SETTINGS.Homebrew.FIELDS.resources.resources.noColorFilter.label'
})
},
{ required: true }
);