This commit is contained in:
Gergely Bräutigam 2026-07-18 18:33:28 +02:00 committed by GitHub
commit 01dbc14207
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 117 additions and 20 deletions

View file

@ -160,7 +160,7 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
context.allDamageTypesUsed = !getUnusedDamageTypes(this.action.damage.parts).length;
if (this.action.damage.hasOwnProperty('includeBase') && this.action.type === 'attack')
context.hasBaseDamage = !!this.action.parent.attack;
context.hasBaseDamage = !!this.action.parent.attack && !this.action.baseAction;
}
context.costOptions = this.getCostOptions();

View file

@ -5,6 +5,9 @@ export default class WeaponSheet extends ItemAttachmentSheet(DHBaseItemSheet) {
/**@inheritdoc */
static DEFAULT_OPTIONS = {
classes: ['weapon'],
actions: {
configureAttack: WeaponSheet.#configureAttack
},
tagifyConfigs: [
{
selector: '.features-input',
@ -46,6 +49,13 @@ export default class WeaponSheet extends ItemAttachmentSheet(DHBaseItemSheet) {
return context;
}
/**
* Open the action configuration sheet for the weapon's base attack.
*/
static #configureAttack() {
this.document.system.attack.sheet.render({ force: true });
}
/**
* Callback function used by `tagifyElement`.
* @param {Array<Object>} selectedOptions - The currently selected tag objects.

View file

@ -191,6 +191,11 @@ export const healingTypes = {
id: 'fear',
label: 'DAGGERHEART.CONFIG.HealingType.fear.name',
abbreviation: 'DAGGERHEART.CONFIG.HealingType.fear.abbreviation'
},
weaponResource: {
id: 'weaponResource',
label: 'DAGGERHEART.CONFIG.HealingType.weaponResource.name',
abbreviation: 'DAGGERHEART.CONFIG.HealingType.weaponResource.abbreviation'
}
};

View file

@ -197,11 +197,29 @@ export default class CostField extends fields.ArrayField {
static getItemIdCostUpdate(r) {
switch (r.key) {
case CONFIG.DH.GENERAL.itemAbilityCosts.resource.id:
case CONFIG.DH.GENERAL.itemAbilityCosts.resource.id: {
const resource = r.target.system.resource;
let max = Number(resource.max);
if (!Number.isFinite(max) && resource.max) {
try {
max = Roll.safeEval(Roll.replaceFormulaData(resource.max, r.target.getRollData()));
} catch {
max = null;
}
}
const hasMax = Number.isFinite(max) && max > 0;
if (r.clear) {
return {
path: 'system.resource.value',
value: hasMax ? max : resource.value
};
}
const newValue = resource.value + r.value;
return {
path: 'system.resource.value',
value: r.target.system.resource.value + r.value
value: Math.max(hasMax ? Math.min(newValue, max) : newValue, 0)
};
}
case CONFIG.DH.GENERAL.itemAbilityCosts.quantity.id:
return {
path: 'system.quantity',

View file

@ -45,9 +45,10 @@ export default class DamageField extends fields.SchemaField {
return;
let formulas = this.damage.parts.map(p => ({
formula: DamageField.getFormulaValue.call(this, p, config).getFormula(this.actor),
formula: p.fullRestore ? '0' : DamageField.getFormulaValue.call(this, p, config).getFormula(this.actor),
damageTypes: p.applyTo === 'hitPoints' && !p.type.size ? new Set(['physical']) : p.type,
applyTo: p.applyTo
applyTo: p.applyTo,
fullRestore: p.fullRestore
}));
if (!formulas.length) return false;
@ -67,6 +68,7 @@ export default class DamageField extends fields.SchemaField {
if (DamageField.getAutomation() === CONFIG.DH.SETTINGS.actionAutomationChoices.always.id)
damageConfig.dialog.configure = false;
if (formulas.every(f => f.fullRestore)) damageConfig.dialog.configure = false;
if (config.hasSave) config.onSave = damageConfig.onSave = this.save.damageMod;
damageConfig.source.message = messageId;
@ -305,6 +307,10 @@ export class DHResourceData extends foundry.abstract.DataModel {
initial: false,
label: 'DAGGERHEART.ACTIONS.Settings.resultBased.label'
}),
fullRestore: new fields.BooleanField({
initial: false,
label: 'DAGGERHEART.ACTIONS.Settings.fullRestore.label'
}),
value: new fields.EmbeddedDataField(DHActionDiceData),
valueAlt: new fields.EmbeddedDataField(DHActionDiceData)
};

View file

@ -774,17 +774,21 @@ export default class DhpActor extends Actor {
Object.entries(healings).forEach(([key, healing]) => {
healing.parts.forEach(part => {
const update = updates.find(u => u.key === key);
if (update) update.value += part.total;
else updates.push({ value: part.total, key });
if (update) {
update.value += part.total;
update.clear ||= !!part.fullRestore;
} else updates.push({ value: part.total, key, clear: !!part.fullRestore });
});
});
updates.forEach(
u =>
(u.value = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false)
? u.value * -1
: u.value)
);
updates.forEach(u => {
if (u.key === CONFIG.DH.GENERAL.healingTypes.weaponResource.id) return;
u.value = !(u.key === 'fear' || this.system?.resources?.[u.key]?.isReversed === false)
? u.value * -1
: u.value;
});
this.convertResourceHealingToReload(updates);
await this.modifyResource(updates);
@ -810,7 +814,7 @@ export default class DhpActor extends Actor {
resources.forEach(r => {
if (r.itemId) {
const { path, value } = game.system.api.fields.ActionFields.CostField.getItemIdCostUpdate(r);
updates.items[r.key] = {
updates.items[`${r.itemId}-${r.key}`] = {
target: r.target,
resources: { [path]: value }
};
@ -881,6 +885,22 @@ export default class DhpActor extends Actor {
return damage >= this.system.damageThresholds.severe ? 3 : damage >= this.system.damageThresholds.major ? 2 : 1;
}
convertResourceHealingToReload(updates) {
const resourceIndex = updates.findIndex(u => u.key === CONFIG.DH.GENERAL.healingTypes.weaponResource.id);
if (resourceIndex === -1) return;
const [reload] = updates.splice(resourceIndex, 1);
const weapons = this.items.filter(i => i.type === 'weapon' && i.system.equipped && i.system.resource);
for (const weapon of weapons) {
updates.push({
key: CONFIG.DH.GENERAL.itemAbilityCosts.resource.id,
value: reload.value,
clear: reload.clear,
itemId: weapon.id,
target: weapon
});
}
}
convertStressDamageToHP(resources) {
const stressDamage = resources.find(r => r.key === 'stress'),
newValue = this.system.resources.stress.value + stressDamage.value;