Fixed Stress Reductions

This commit is contained in:
WBHarry 2025-06-24 21:35:21 +02:00
parent f4539ab158
commit 0e1320e31d
8 changed files with 279 additions and 74 deletions

View file

@ -1,4 +1,4 @@
import { getDamageLabel } from '../helpers/utils.mjs';
import { damageKeyToNumber, getDamageLabel } from '../helpers/utils.mjs';
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
@ -11,13 +11,32 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
this.actor = actor;
this.damage = damage;
const maxUseable = actor.system.armorScore - actor.system.armor.system.marks.value;
this.availableArmorMarks = {
max: actor.system.rules.maxArmorMarked.total + (actor.system.rules.stressExtra ?? 0),
maxUseable: actor.system.armorScore - actor.system.armor.system.marks.value,
stressIndex:
(actor.system.rules.stressExtra ?? 0) > 0 ? actor.system.rules.maxArmorMarked.total : undefined,
max: Math.min(
maxUseable,
actor.system.rules.maxArmorMarked.total + (actor.system.rules.maxArmorMarked.stressExtra ?? 0)
),
stressIndex: actor.system.rules.maxArmorMarked.total,
selected: 0
};
this.availableStressReductions = Object.keys(actor.system.rules.stressDamageReduction).reduce((acc, key) => {
const dr = actor.system.rules.stressDamageReduction[key];
if (dr.enabled) {
if (acc === null) acc = {};
const damage = damageKeyToNumber(key);
acc[damage] = {
cost: dr.cost,
selected: false,
from: getDamageLabel(damage),
to: getDamageLabel(damage - 1)
};
}
return acc;
}, null);
}
get title() {
@ -33,6 +52,7 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
},
actions: {
setMarks: this.setMarks,
useStressReduction: this.useStressReduction,
takeDamage: this.takeDamage
},
form: {
@ -61,13 +81,31 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
const context = await super._prepareContext(_options);
context.armorScore = this.actor.system.armorScore;
context.armorMarks = this.actor.system.armor.system.marks.value + this.availableArmorMarks.selected;
const selectedStressReductions = Object.values(this.availableStressReductions).filter(red => red.selected);
const stressReductionStress = this.availableStressReductions
? selectedStressReductions.reduce((acc, red) => acc + red.cost, 0)
: 0;
context.stress =
this.availableArmorMarks.stressIndex || this.availableStressReductions
? {
value:
this.actor.system.resources.stress.value +
(Math.max(this.availableArmorMarks.selected - this.availableArmorMarks.stressIndex, 0) +
stressReductionStress),
maxTotal: this.actor.system.resources.stress.maxTotal
}
: null;
context.availableArmorMarks = this.availableArmorMarks;
context.availableStressReductions = this.availableStressReductions;
context.damage = getDamageLabel(this.damage);
context.reducedDamage =
this.availableArmorMarks.selected > 0
? getDamageLabel(this.damage - this.availableArmorMarks.selected)
this.availableArmorMarks.selected > 0 || selectedStressReductions.length > 0
? getDamageLabel(this.damage - this.availableArmorMarks.selected - selectedStressReductions.length)
: null;
context.currentDamage = context.reducedDamage ?? context.damage;
return context;
}
@ -79,21 +117,51 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
static setMarks(_, target) {
const index = Number(target.dataset.index);
if (index >= this.availableArmorMarks.maxUseable) {
ui.notifications.info(game.i18n.localize('DAGGERHEART.DamageReduction.Notifications.NotEnoughArmor'));
return;
}
const isDecreasing = index < this.availableArmorMarks.selected;
if (!isDecreasing && this.damage - this.availableArmorMarks.selected === 0) {
ui.notifications.info(game.i18n.localize('DAGGERHEART.DamageReduction.Notifications.DamageAlreadyNone'));
return;
}
if (isDecreasing) {
const selectedStressReductions = Object.values(this.availableStressReductions).filter(red => red.selected);
const reducedDamage =
this.availableArmorMarks.selected > 0 || selectedStressReductions.length > 0
? getDamageLabel(this.damage - this.availableArmorMarks.selected - selectedStressReductions.length)
: null;
const currentDamage = reducedDamage ?? getDamageLabel(this.damage);
for (let reduction of selectedStressReductions) {
if (reduction.selected && reduction.to === currentDamage) {
reduction.selected = false;
}
}
}
this.availableArmorMarks.selected = isDecreasing ? index : index + 1;
this.render();
}
static useStressReduction(_, target) {
const damageValue = Number(target.dataset.reduction);
const stressReduction = this.availableStressReductions[damageValue];
if (stressReduction.selected) {
stressReduction.selected = false;
this.render();
} else {
const selectedStressReductions = Object.values(this.availableStressReductions).filter(red => red.selected);
const reducedDamage =
this.availableArmorMarks.selected > 0 || selectedStressReductions.length > 0
? getDamageLabel(this.damage - this.availableArmorMarks.selected - selectedStressReductions.length)
: null;
const currentDamage = reducedDamage ?? getDamageLabel(this.damage);
if (stressReduction.from !== currentDamage) return;
stressReduction.selected = true;
this.render();
}
}
static async takeDamage() {
const armorSpent = this.availableArmorMarks.selected;
const modifiedDamage = this.damage - armorSpent;