Update armor slot handling

This commit is contained in:
Dapoolp 2025-09-02 14:26:50 +02:00
parent 4bdafeff6d
commit af3a415e56
10 changed files with 56 additions and 72 deletions

View file

@ -2085,6 +2085,10 @@
"base": "Base Thresholds", "base": "Base Thresholds",
"major": "Major Threshold", "major": "Major Threshold",
"severe": "Severe Threshold" "severe": "Severe Threshold"
},
"switch": {
"title": "Armor Swap",
"content": "Reset Marked Armor Slots ?"
} }
}, },
"Beastform": { "Beastform": {

View file

@ -20,7 +20,7 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
); );
const canApplyArmor = damageType.every(t => actor.system.armorApplicableDamageTypes[t] === true); const canApplyArmor = damageType.every(t => actor.system.armorApplicableDamageTypes[t] === true);
const availableArmor = actor.system.armorScore - actor.system.armor.system.marks.value; const availableArmor = actor.system.resources.armor.max - actor.system.resources.armor.value;
const maxArmorMarks = canApplyArmor ? availableArmor : 0; const maxArmorMarks = canApplyArmor ? availableArmor : 0;
const armor = [...Array(maxArmorMarks).keys()].reduce((acc, _) => { const armor = [...Array(maxArmorMarks).keys()].reduce((acc, _) => {
@ -116,7 +116,7 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
const { selectedArmorMarks, selectedStressMarks, stressReductions, currentMarks, currentDamage } = const { selectedArmorMarks, selectedStressMarks, stressReductions, currentMarks, currentDamage } =
this.getDamageInfo(); this.getDamageInfo();
context.armorScore = this.actor.system.armorScore; context.armorScore = this.actor.system.resources.armor.max;
context.armorMarks = currentMarks; context.armorMarks = currentMarks;
context.basicMarksUsed = context.basicMarksUsed =
selectedArmorMarks.length === this.actor.system.rules.damageReduction.maxArmorMarked.value; selectedArmorMarks.length === this.actor.system.rules.damageReduction.maxArmorMarked.value;
@ -165,7 +165,7 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
? Object.values(this.availableStressReductions).filter(red => red.selected) ? Object.values(this.availableStressReductions).filter(red => red.selected)
: []; : [];
const currentMarks = const currentMarks =
this.actor.system.armor.system.marks.value + selectedArmorMarks.length + selectedStressMarks.length; this.actor.system.resources.armor.value + selectedArmorMarks.length + selectedStressMarks.length;
const armorMarkReduction = const armorMarkReduction =
selectedArmorMarks.length * this.actor.system.rules.damageReduction.increasePerArmorMark; selectedArmorMarks.length * this.actor.system.rules.damageReduction.increasePerArmorMark;
@ -207,7 +207,7 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
} }
if (this.rulesOn) { if (this.rulesOn) {
if (!currentMark.selected && currentMarks === this.actor.system.armorScore) { if (!currentMark.selected && currentMarks === this.actor.system.resources.armor.max) {
ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noAvailableArmorMarks')); ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noAvailableArmorMarks'));
return; return;
} }

View file

@ -134,11 +134,6 @@ export default class CharacterSheet extends DHBaseActorSheet {
element.addEventListener('change', this.updateItemQuantity.bind(this)); element.addEventListener('change', this.updateItemQuantity.bind(this));
element.addEventListener('click', e => e.stopPropagation()); element.addEventListener('click', e => e.stopPropagation());
}); });
// Add listener for armor marks input
htmlElement.querySelectorAll('.armor-marks-input').forEach(element => {
element.addEventListener('change', this.updateArmorMarks.bind(this));
});
} }
/** @inheritDoc */ /** @inheritDoc */
@ -581,15 +576,6 @@ export default class CharacterSheet extends DHBaseActorSheet {
this.render(); this.render();
} }
async updateArmorMarks(event) {
const armor = this.document.system.armor;
if (!armor) return;
const maxMarks = this.document.system.armorScore;
const value = Math.min(Math.max(Number(event.currentTarget.value), 0), maxMarks);
await armor.update({ 'system.marks.value': value });
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Application Clicks Actions */ /* Application Clicks Actions */
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -702,6 +688,19 @@ export default class CharacterSheet extends DHBaseActorSheet {
} }
await item.update({ 'system.equipped': true }); await item.update({ 'system.equipped': true });
if(this.document.system.resources.armor.value > 0) {
const confirmed = await foundry.applications.api.DialogV2.confirm({
window: {
title: game.i18n.localize('DAGGERHEART.ITEMS.Armor.switch.title')
},
content: game.i18n.localize('DAGGERHEART.ITEMS.Armor.switch.content')
});
if (confirmed)
await this.document.update({'system.resources.armor.value': 0});
}
break; break;
case 'weapon': case 'weapon':
if (this.document.effects.find(x => !x.disabled && x.type === 'beastform')) { if (this.document.effects.find(x => !x.disabled && x.type === 'beastform')) {

View file

@ -35,7 +35,14 @@ export default class DhCharacter extends BaseDataActor {
'DAGGERHEART.ACTORS.Character.maxHPBonus' 'DAGGERHEART.ACTORS.Character.maxHPBonus'
), ),
stress: resourceField(6, 0, 'DAGGERHEART.GENERAL.stress', true), stress: resourceField(6, 0, 'DAGGERHEART.GENERAL.stress', true),
hope: resourceField(6, 2, 'DAGGERHEART.GENERAL.hope') hope: resourceField(6, 2, 'DAGGERHEART.GENERAL.hope'),
armor: resourceField(
0,
0,
'',
true,
''
)
}), }),
traits: new fields.SchemaField({ traits: new fields.SchemaField({
agility: attributeField('DAGGERHEART.CONFIG.Traits.agility.name'), agility: attributeField('DAGGERHEART.CONFIG.Traits.agility.name'),
@ -631,11 +638,8 @@ export default class DhCharacter extends BaseDataActor {
this.resources.hope.value = Math.min(baseHope, this.resources.hope.max); this.resources.hope.value = Math.min(baseHope, this.resources.hope.max);
this.attack.roll.trait = this.rules.attack.roll.trait ?? this.attack.roll.trait; this.attack.roll.trait = this.rules.attack.roll.trait ?? this.attack.roll.trait;
this.resources.armor = { this.resources.armor.max = this.armorScore;
value: this.armor?.system?.marks?.value ?? 0, if(this.resources.armor.value > this.resources.armor.max) this.resources.armor.value = this.resources.armor.max;
max: this.armorScore,
isReversed: true
};
this.attack.damage.parts[0].value.custom.formula = `@prof${this.basicAttackDamageDice}${this.rules.attack.damage.bonus ? ` + ${this.rules.attack.damage.bonus}` : ''}`; this.attack.damage.parts[0].value.custom.formula = `@prof${this.basicAttackDamageDice}${this.rules.attack.damage.bonus ? ` + ${this.rules.attack.damage.bonus}` : ''}`;
} }

View file

@ -55,9 +55,14 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel {
} }
get action() { get action() {
const actionItem = this.actionItem; const actionActor = this.actionActor,
if (!actionItem || !this.source.action) return null; actionItem = this.actionItem;
return actionItem.system.actionsList?.find(a => a.id === this.source.action); if (!this.source.action) return null;
if(actionItem)
return actionItem.system.actionsList?.find(a => a.id === this.source.action);
else if(actionActor?.system.attack?._id === this.source.action)
return actionActor.system.attack
return null;
} }
get targetMode() { get targetMode() {

View file

@ -187,14 +187,6 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
if (allowed === false) return false; if (allowed === false) return false;
addLinkedItemsDiff(changed.system?.features, this.features, options); addLinkedItemsDiff(changed.system?.features, this.features, options);
const autoSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation);
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.system.resources, changed.system.marks, 'armor');
options.scrollingTextData = [armorData];
}
} }
_onUpdate(changed, options, userId) { _onUpdate(changed, options, userId) {

View file

@ -514,8 +514,7 @@ export default class DhpActor extends Actor {
const availableStress = this.system.resources.stress.max - this.system.resources.stress.value; const availableStress = this.system.resources.stress.max - this.system.resources.stress.value;
const canUseArmor = const canUseArmor =
this.system.armor && this.system.resources.armor.value < this.system.resources.armor.max &&
this.system.armor.system.marks.value < this.system.armorScore &&
type.every(t => this.system.armorApplicableDamageTypes[t] === true); type.every(t => this.system.armorApplicableDamageTypes[t] === true);
const canUseStress = Object.keys(stressDamageReduction).reduce((acc, x) => { const canUseStress = Object.keys(stressDamageReduction).reduce((acc, x) => {
const rule = stressDamageReduction[x]; const rule = stressDamageReduction[x];
@ -558,7 +557,6 @@ export default class DhpActor extends Actor {
if ( if (
this.type === 'character' && this.type === 'character' &&
!isDirect && !isDirect &&
this.system.armor &&
this.#canReduceDamage(hpDamage.value, hpDamage.damageTypes) this.#canReduceDamage(hpDamage.value, hpDamage.damageTypes)
) { ) {
const armorSlotResult = await this.owner.query( const armorSlotResult = await this.owner.query(
@ -682,14 +680,6 @@ export default class DhpActor extends Actor {
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear) + r.value game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear) + r.value
); );
break; break;
case 'armor':
if (this.system.armor?.system?.marks) {
updates.armor.resources['system.marks.value'] = Math.max(
Math.min(this.system.armor.system.marks.value + r.value, this.system.armorScore),
0
);
}
break;
default: default:
if (this.system.resources?.[r.key]) { if (this.system.resources?.[r.key]) {
updates.actor.resources[`system.resources.${r.key}.value`] = Math.max( updates.actor.resources[`system.resources.${r.key}.value`] = Math.max(

View file

@ -9,13 +9,6 @@ export default class DHToken extends TokenDocument {
const barGroup = game.i18n.localize('TOKEN.BarAttributes'); const barGroup = game.i18n.localize('TOKEN.BarAttributes');
const valueGroup = game.i18n.localize('TOKEN.BarValues'); const valueGroup = game.i18n.localize('TOKEN.BarValues');
const bars = attributes.bar.map(v => {
const a = v.join('.');
const modelLabel = model ? game.i18n.localize(model.schema.getField(`${a}.value`).label) : null;
return { group: barGroup, value: a, label: modelLabel ? modelLabel : a };
});
bars.sort((a, b) => a.label.compare(b.label));
const invalidAttributes = [ const invalidAttributes = [
'gold', 'gold',
'levelData', 'levelData',
@ -29,8 +22,21 @@ export default class DHToken extends TokenDocument {
'description', 'description',
'impulses', 'impulses',
'tier', 'tier',
'type' 'type',
'resources.armor'
]; ];
const bars = attributes.bar.reduce((acc, v) => {
const a = v.join('.');
if (invalidAttributes.some(x => a.startsWith(x))) return acc;
const modelLabel = model ? game.i18n.localize(model.schema.getField(`${a}.value`).label) : null;
acc.push({ group: barGroup, value: a, label: modelLabel ? modelLabel : a });
return acc;
}, []);
bars.sort((a, b) => a.label.compare(b.label));
const values = attributes.value.reduce((acc, v) => { const values = attributes.value.reduce((acc, v) => {
const a = v.join('.'); const a = v.join('.');
if (invalidAttributes.some(x => a.startsWith(x))) return acc; if (invalidAttributes.some(x => a.startsWith(x))) return acc;

View file

@ -85,7 +85,7 @@
}, },
"changes": [ "changes": [
{ {
"key": "system.resources.hitPoints", "key": "system.resources.hitPoints.max",
"mode": 2, "mode": 2,
"value": "1", "value": "1",
"priority": null "priority": null

View file

@ -62,26 +62,10 @@
</div> </div>
</div> </div>
{{!-- {{#if document.system.armor.system.marks}}
<div class="status-bar armor-slots">
<div class='status-value'>
<p><input class="bar-input armor-marks-input" value="{{document.system.armor.system.marks.value}}" type="number"></p>
<p>/</p>
<p class="bar-label">{{document.system.armorScore}}</p>
</div>
<progress
class='progress-bar stress-color'
value='{{document.system.armor.system.marks.value}}'
max='{{document.system.armorScore}}'
></progress>
<div class="status-label">
<h4>{{localize "DAGGERHEART.GENERAL.armorSlots"}}</h4>
</div>
</div> --}}
{{#if document.system.resources.armor.max}} {{#if document.system.resources.armor.max}}
<div class="status-bar armor-slots"> <div class="status-bar armor-slots">
<div class='status-value'> <div class='status-value'>
<p><input class="bar-input armor-marks-input" value="{{document.system.resources.armor.value}}" type="number"></p> <p><input class="bar-input armor-marks-input" value="{{document.system.resources.armor.value}}" type="number" name="system.resources.armor.value"></p>
<p>/</p> <p>/</p>
<p class="bar-label">{{document.system.resources.armor.max}}</p> <p class="bar-label">{{document.system.resources.armor.max}}</p>
</div> </div>