mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-04-21 15:03:37 +02:00
Fix editing homebrew resources with a custom ResourcesField
This commit is contained in:
parent
f298b2160a
commit
859263e2fd
9 changed files with 109 additions and 83 deletions
|
|
@ -44,8 +44,32 @@ export default class DHBaseActorSettings extends DHApplicationMixin(DocumentShee
|
|||
const context = await super._prepareContext(options);
|
||||
context.isNPC = this.actor.isNPC;
|
||||
|
||||
if (context.systemFields.attack)
|
||||
if (context.systemFields.attack) {
|
||||
context.systemFields.attack.fields = this.actor.system.attack.schema.fields;
|
||||
}
|
||||
|
||||
// Create fake fields for actor configurable max resource value.
|
||||
const resourceConfig = CONFIG.DH.RESOURCE[this.actor.type]?.all;
|
||||
if (resourceConfig) {
|
||||
const relevant = ['hitPoints', 'stress'].filter(r => r in resourceConfig);
|
||||
context.resources = relevant.map(key => {
|
||||
const data = this.actor._source.system.resources[key];
|
||||
const config = resourceConfig[key];
|
||||
return {
|
||||
label: config.label,
|
||||
name: `system.resources.${key}.max`,
|
||||
value: data.max ?? config.max,
|
||||
tooltip: key === 'hitPoints' ? game.i18n.localize('DAGGERHEART.UI.Tooltip.maxHPClassBound') : null,
|
||||
field: new foundry.data.fields.NumberField({
|
||||
initial: config.max,
|
||||
integer: true,
|
||||
label: game.i18n.format('DAGGERHEART.GENERAL.maxWithThing', {
|
||||
thing: game.i18n.localize(config.label)
|
||||
})
|
||||
})
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ const characterBaseResources = Object.freeze({
|
|||
hope: {
|
||||
id: 'hope',
|
||||
initial: 2,
|
||||
min: 0,
|
||||
reverse: false,
|
||||
label: 'DAGGERHEART.GENERAL.hope'
|
||||
}
|
||||
|
|
@ -65,7 +64,6 @@ const companionBaseResources = Object.freeze({
|
|||
hope: {
|
||||
id: 'hope',
|
||||
initial: 0,
|
||||
min: 0,
|
||||
reverse: false,
|
||||
label: 'DAGGERHEART.GENERAL.hope'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -587,6 +587,7 @@ export default class DhCharacter extends DhCreature {
|
|||
}
|
||||
|
||||
prepareBaseData() {
|
||||
super.prepareBaseData();
|
||||
this.evasion += this.class.value?.system?.evasion ?? 0;
|
||||
|
||||
const currentLevel = this.levelData.level.current;
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ export default class DhCompanion extends DhCreature {
|
|||
}
|
||||
|
||||
prepareBaseData() {
|
||||
super.prepareBaseData();
|
||||
this.attack.roll.bonus = this.partner?.system?.spellcastModifier ?? 0;
|
||||
|
||||
for (let levelKey in this.levelData.levelups) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { resourceField } from '../fields/actorField.mjs';
|
||||
import { ResourcesField } from '../fields/actorField.mjs';
|
||||
import BaseDataActor from './base.mjs';
|
||||
|
||||
export default class DhCreature extends BaseDataActor {
|
||||
|
|
@ -8,36 +8,7 @@ export default class DhCreature extends BaseDataActor {
|
|||
|
||||
return {
|
||||
...super.defineSchema(),
|
||||
resources: new fields.SchemaField({
|
||||
...Object.values(CONFIG.DH.RESOURCE[this.metadata.type].all).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;
|
||||
},
|
||||
{}
|
||||
)
|
||||
}),
|
||||
resources: new ResourcesField(this.metadata.type),
|
||||
advantageSources: new fields.ArrayField(new fields.StringField(), {
|
||||
label: 'DAGGERHEART.ACTORS.Character.advantageSources.label',
|
||||
hint: 'DAGGERHEART.ACTORS.Character.advantageSources.hint'
|
||||
|
|
@ -56,17 +27,6 @@ export default class DhCreature extends BaseDataActor {
|
|||
return !vulnerableAppliedByOther;
|
||||
}
|
||||
|
||||
prepareDerivedData() {
|
||||
super.prepareDerivedData();
|
||||
const resources = CONFIG.DH.RESOURCE[this.metadata.type].all;
|
||||
if (resources) {
|
||||
for (const [key, value] of Object.entries(this.resources)) {
|
||||
value.label = resources[key]?.label;
|
||||
value.isReversed = resources[key]?.reverse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async _preUpdate(changes, options, userId) {
|
||||
const allowed = await super._preUpdate(changes, options, userId);
|
||||
if (allowed === false) return;
|
||||
|
|
|
|||
|
|
@ -6,21 +6,6 @@ const attributeField = label =>
|
|||
tierMarked: new fields.BooleanField({ initial: false })
|
||||
});
|
||||
|
||||
const resourceField = (max = 0, initial = 0, label, maxLabel) =>
|
||||
new fields.SchemaField(
|
||||
{
|
||||
value: new fields.NumberField({ initial: initial, min: 0, integer: true, label }),
|
||||
max: new fields.NumberField({
|
||||
initial: max,
|
||||
integer: true,
|
||||
label:
|
||||
maxLabel ??
|
||||
game.i18n.format('DAGGERHEART.GENERAL.maxWithThing', { thing: game.i18n.localize(label) })
|
||||
})
|
||||
},
|
||||
{ label }
|
||||
);
|
||||
|
||||
const stressDamageReductionRule = localizationPath =>
|
||||
new fields.SchemaField({
|
||||
cost: new fields.NumberField({
|
||||
|
|
@ -36,4 +21,67 @@ const bonusField = label =>
|
|||
dice: new fields.ArrayField(new fields.StringField(), { label: `${game.i18n.localize(label)} Dice` })
|
||||
});
|
||||
|
||||
export { attributeField, resourceField, stressDamageReductionRule, bonusField };
|
||||
/**
|
||||
* Field used for actor resources. It is a resource that validates dynamically based on the config.
|
||||
* Because "max" may be defined during runtime, we don't attempt to clamp the maximum value.
|
||||
*/
|
||||
class ResourcesField extends fields.TypedObjectField {
|
||||
constructor(actorType) {
|
||||
super(
|
||||
new fields.SchemaField({
|
||||
value: new fields.NumberField({ min: 0, initial: 0, integer: true }),
|
||||
// Some resources allow changing max. A null max means its the default
|
||||
max: new fields.NumberField({ initial: null, integer: true, nullable: true })
|
||||
})
|
||||
);
|
||||
this.actorType = actorType;
|
||||
}
|
||||
|
||||
getInitialValue() {
|
||||
const resources = CONFIG.DH.RESOURCE[this.actorType].all;
|
||||
return Object.values(resources).reduce((result, resource) => {
|
||||
result[resource.id] = {
|
||||
value: resource.initial,
|
||||
max: null
|
||||
};
|
||||
return result;
|
||||
}, {});
|
||||
}
|
||||
|
||||
_validateKey(key) {
|
||||
return key in CONFIG.DH.RESOURCE[this.actorType].all;
|
||||
}
|
||||
|
||||
_cleanType(value, options) {
|
||||
value = super._cleanType(value, options);
|
||||
|
||||
// If not partial, ensure all data exists
|
||||
if (!options.partial) {
|
||||
value = foundry.utils.mergeObject(this.getInitialValue(), value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/** Initializes the original source data, returning prepared data */
|
||||
initialize(...args) {
|
||||
const data = super.initialize(...args);
|
||||
const resources = CONFIG.DH.RESOURCE[this.actorType].all;
|
||||
for (const [key, value] of Object.entries(data)) {
|
||||
// TypedObjectField only calls _validateKey when persisting, so we also call it here
|
||||
if (!this._validateKey(key)) {
|
||||
delete value[key];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add basic prepared data.
|
||||
const resource = resources[key];
|
||||
value.label = resource.label;
|
||||
value.isReversed = resources[key].reverse;
|
||||
value.max = typeof resource.max === 'number' ? value.max ?? resource.max : null;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
export { attributeField, ResourcesField, stressDamageReductionRule, bonusField };
|
||||
|
|
|
|||
|
|
@ -20,15 +20,11 @@
|
|||
|
||||
<div class="fieldsets-section">
|
||||
<fieldset class="flex">
|
||||
<legend>{{localize "DAGGERHEART.GENERAL.HitPoints.plural"}}</legend>
|
||||
{{formGroup systemFields.resources.fields.hitPoints.fields.value value=document._source.system.resources.hitPoints.value label=(localize "DAGGERHEART.ACTORS.Adversary.FIELDS.resources.hitPoints.value.label")}}
|
||||
{{formGroup systemFields.resources.fields.hitPoints.fields.max value=document._source.system.resources.hitPoints.max label=(localize "DAGGERHEART.ACTORS.Adversary.FIELDS.resources.hitPoints.max.label")}}
|
||||
</fieldset>
|
||||
<fieldset class="flex">
|
||||
<legend>{{localize "DAGGERHEART.GENERAL.stress"}}</legend>
|
||||
{{formGroup systemFields.resources.fields.stress.fields.value value=document._source.system.resources.stress.value label=(localize "DAGGERHEART.ACTORS.Adversary.FIELDS.resources.stress.value.label")}}
|
||||
{{formGroup systemFields.resources.fields.stress.fields.max value=document._source.system.resources.stress.max label=(localize "DAGGERHEART.ACTORS.Adversary.FIELDS.resources.stress.max.label")}}
|
||||
</fieldset>
|
||||
<legend>{{localize "DAGGERHEART.GENERAL.Resource.plural"}}</legend>
|
||||
{{#each resources as |resource|}}
|
||||
{{formGroup resource.field value=resource.value name=resource.name}}
|
||||
{{/each}}
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<fieldset class="flex">
|
||||
|
|
@ -36,4 +32,4 @@
|
|||
{{formGroup systemFields.damageThresholds.fields.major value=document._source.system.damageThresholds.major label=(localize "DAGGERHEART.GENERAL.DamageThresholds.majorThreshold")}}
|
||||
{{formGroup systemFields.damageThresholds.fields.severe value=document._source.system.damageThresholds.severe label=(localize "DAGGERHEART.GENERAL.DamageThresholds.severeThreshold")}}
|
||||
</fieldset>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -22,15 +22,12 @@
|
|||
<legend>{{localize 'DAGGERHEART.GENERAL.basics'}}</legend>
|
||||
|
||||
<div class="two-columns even">
|
||||
{{formGroup systemFields.resources.fields.hitPoints.fields.value value=document._source.system.resources.hitPoints.value localize=true}}
|
||||
<span data-tooltip-text="{{localize "DAGGERHEART.UI.Tooltip.maxHPClassBound"}}">
|
||||
{{formGroup systemFields.resources.fields.hitPoints.fields.max value=document._source.system.resources.hitPoints.max localize=true}}
|
||||
</span>
|
||||
{{#each resources as |resource|}}
|
||||
<span {{#if resource.tooltip}}data-tooltip-text="{{resource.tooltip}}"{{/if}}>
|
||||
{{formGroup resource.field value=resource.value name=resource.name}}
|
||||
</span>
|
||||
{{/each}}
|
||||
|
||||
{{formGroup systemFields.resources.fields.stress.fields.value value=document._source.system.resources.stress.value localize=true}}
|
||||
{{formGroup systemFields.resources.fields.stress.fields.max value=document._source.system.resources.stress.max localize=true}}
|
||||
|
||||
{{formGroup systemFields.resources.fields.hope.fields.value value=document._source.system.resources.hope.value localize=true}}
|
||||
{{formGroup systemFields.scars value=document._source.system.scars localize=true}}
|
||||
|
||||
{{formGroup systemFields.proficiency value=document._source.system.proficiency localize=true}}
|
||||
|
|
@ -39,4 +36,4 @@
|
|||
</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@
|
|||
<legend>{{localize 'DAGGERHEART.GENERAL.basics'}}</legend>
|
||||
<div class="nest-inputs">
|
||||
{{formGroup systemFields.evasion value=document._source.system.evasion localize=true}}
|
||||
{{formGroup systemFields.resources.fields.stress.fields.value value=document._source.system.resources.stress.value label='DAGGERHEART.ACTORS.Companion.FIELDS.resources.stress.currentStress.label' localize=true}}
|
||||
{{formGroup systemFields.resources.fields.stress.fields.max value=document._source.system.resources.stress.max label='DAGGERHEART.ACTORS.Companion.FIELDS.resources.stress.maxStress.label' localize=true}}
|
||||
{{#each resources as |resource|}}
|
||||
{{formGroup resource.field value=resource.value name=resource.name}}
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-fields">
|
||||
|
|
@ -19,4 +20,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue