Compare commits

...

2 commits

Author SHA1 Message Date
WBHarry
6176c3265d Fixed ArmorManagement pip syle 2026-02-14 01:39:13 +01:00
WBHarry
8f0b1f6ed3 Fixed DamageReductionDialog 2026-02-13 23:01:55 +01:00
11 changed files with 293 additions and 90 deletions

View file

@ -437,7 +437,7 @@
"text": "Are you sure you want to delete {name}?" "text": "Are you sure you want to delete {name}?"
}, },
"DamageReduction": { "DamageReduction": {
"armorMarks": "Armor Marks", "maxUseableArmor": "Useable Armor Slots",
"armorWithStress": "Spend 1 stress to use an extra mark", "armorWithStress": "Spend 1 stress to use an extra mark",
"thresholdImmunities": "Threshold Immunities", "thresholdImmunities": "Threshold Immunities",
"stress": "Stress", "stress": "Stress",

View file

@ -10,7 +10,8 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
this.reject = reject; this.reject = reject;
this.actor = actor; this.actor = actor;
this.damage = damage; this.damage = damage;
this.damageType = damageType; // this.damageType = damageType;
this.damageType = ['physical'];
this.rulesDefault = game.settings.get( this.rulesDefault = game.settings.get(
CONFIG.DH.id, CONFIG.DH.id,
CONFIG.DH.SETTINGS.gameSettings.Automation CONFIG.DH.SETTINGS.gameSettings.Automation
@ -20,14 +21,25 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
this.rulesDefault this.rulesDefault
); );
const canApplyArmor = damageType.every(t => actor.system.armorApplicableDamageTypes[t] === true); const allArmorEffects = Array.from(actor.allApplicableEffects()).filter(x => x.type === 'armor');
const availableArmor = actor.system.armorScore.max - actor.system.armorScore.value; const orderedArmorEffects = game.system.api.data.activeEffects.ArmorEffect.orderEffectsForAutoChange(
const maxArmorMarks = canApplyArmor ? availableArmor : 0; allArmorEffects,
true
);
const armor = orderedArmorEffects.reduce((acc, effect) => {
if (effect.type !== 'armor') return acc;
const { value, max } = effect.system.armorData;
acc.push({
effect: effect,
marks: [...Array(max).keys()].reduce((acc, _, index) => {
const spent = index < value;
acc[foundry.utils.randomID()] = { selected: false, disabled: spent, spent };
return acc;
}, {})
});
const armor = [...Array(maxArmorMarks).keys()].reduce((acc, _) => {
acc[foundry.utils.randomID()] = { selected: false };
return acc; return acc;
}, {}); }, []);
const stress = [...Array(actor.system.rules.damageReduction.maxArmorMarked.stressExtra ?? 0).keys()].reduce( const stress = [...Array(actor.system.rules.damageReduction.maxArmorMarked.stressExtra ?? 0).keys()].reduce(
(acc, _) => { (acc, _) => {
acc[foundry.utils.randomID()] = { selected: false }; acc[foundry.utils.randomID()] = { selected: false };
@ -121,13 +133,11 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
context.thresholdImmunities = context.thresholdImmunities =
Object.keys(this.thresholdImmunities).length > 0 ? this.thresholdImmunities : null; Object.keys(this.thresholdImmunities).length > 0 ? this.thresholdImmunities : null;
const { selectedArmorMarks, selectedStressMarks, stressReductions, currentMarks, currentDamage } = const { selectedStressMarks, stressReductions, currentMarks, currentDamage, maxArmorUsed, availableArmor } =
this.getDamageInfo(); this.getDamageInfo();
context.armorScore = this.actor.system.armorScore.max; context.armorScore = this.actor.system.armorScore.max;
context.armorMarks = currentMarks; context.armorMarks = currentMarks;
context.basicMarksUsed =
selectedArmorMarks.length === this.actor.system.rules.damageReduction.maxArmorMarked.value;
const stressReductionStress = this.availableStressReductions const stressReductionStress = this.availableStressReductions
? stressReductions.reduce((acc, red) => acc + red.cost, 0) ? stressReductions.reduce((acc, red) => acc + red.cost, 0)
@ -141,16 +151,27 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
} }
: null; : null;
const maxArmor = this.actor.system.rules.damageReduction.maxArmorMarked.value; context.maxArmorUsed = maxArmorUsed;
context.marks = { context.availableArmor = availableArmor;
armor: Object.keys(this.marks.armor).reduce((acc, key, index) => { context.basicMarksUsed = availableArmor === 0 || selectedStressMarks.length;
const mark = this.marks.armor[key];
if (!this.rulesOn || index + 1 <= maxArmor) acc[key] = mark;
return acc; const armorSources = [];
}, {}), for (const source of this.marks.armor) {
const parent = source.effect.origin
? await foundry.utils.fromUuid(source.effect.origin)
: source.effect.parent;
armorSources.push({
label: parent.name,
uuid: source.effect.uuid,
marks: source.marks
});
}
context.marks = {
armor: armorSources,
stress: this.marks.stress stress: this.marks.stress
}; };
context.usesStressArmor = Object.keys(context.marks.stress).length;
context.availableStressReductions = this.availableStressReductions; context.availableStressReductions = this.availableStressReductions;
context.damage = getDamageLabel(this.damage); context.damage = getDamageLabel(this.damage);
@ -167,27 +188,31 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
} }
getDamageInfo = () => { getDamageInfo = () => {
const selectedArmorMarks = Object.values(this.marks.armor).filter(x => x.selected); const selectedArmorMarks = this.marks.armor.flatMap(x => Object.values(x.marks).filter(x => x.selected));
const selectedStressMarks = Object.values(this.marks.stress).filter(x => x.selected); const selectedStressMarks = Object.values(this.marks.stress).filter(x => x.selected);
const stressReductions = this.availableStressReductions const stressReductions = this.availableStressReductions
? Object.values(this.availableStressReductions).filter(red => red.selected) ? Object.values(this.availableStressReductions).filter(red => red.selected)
: []; : [];
const currentMarks = const currentMarks = this.actor.system.armorScore.value + selectedArmorMarks.length;
this.actor.system.armorScore.value + selectedArmorMarks.length + selectedStressMarks.length;
const maxArmorUsed = this.actor.system.rules.damageReduction.maxArmorMarked.value + selectedStressMarks.length;
const availableArmor =
maxArmorUsed -
this.marks.armor.reduce((acc, source) => {
acc += Object.values(source.marks).filter(x => x.selected).length;
return acc;
}, 0);
const armorMarkReduction = const armorMarkReduction =
selectedArmorMarks.length * this.actor.system.rules.damageReduction.increasePerArmorMark; selectedArmorMarks.length * this.actor.system.rules.damageReduction.increasePerArmorMark;
let currentDamage = Math.max( let currentDamage = Math.max(this.damage - armorMarkReduction - stressReductions.length, 0);
this.damage - armorMarkReduction - selectedStressMarks.length - stressReductions.length,
0
);
if (this.reduceSeverity) { if (this.reduceSeverity) {
currentDamage = Math.max(currentDamage - this.reduceSeverity, 0); currentDamage = Math.max(currentDamage - this.reduceSeverity, 0);
} }
if (this.thresholdImmunities[currentDamage]) currentDamage = 0; if (this.thresholdImmunities[currentDamage]) currentDamage = 0;
return { selectedArmorMarks, selectedStressMarks, stressReductions, currentMarks, currentDamage }; return { selectedStressMarks, stressReductions, currentMarks, currentDamage, maxArmorUsed, availableArmor };
}; };
static toggleRules() { static toggleRules() {
@ -209,8 +234,8 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
} }
static setMarks(_, target) { static setMarks(_, target) {
const currentMark = this.marks[target.dataset.type][target.dataset.key]; const currentMark = foundry.utils.getProperty(this.marks, target.dataset.path);
const { selectedStressMarks, stressReductions, currentMarks, currentDamage } = this.getDamageInfo(); const { selectedStressMarks, stressReductions, currentDamage, availableArmor } = this.getDamageInfo();
if (!currentMark.selected && currentDamage === 0) { if (!currentMark.selected && currentDamage === 0) {
ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.damageAlreadyNone')); ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.damageAlreadyNone'));
@ -218,12 +243,18 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
} }
if (this.rulesOn) { if (this.rulesOn) {
if (!currentMark.selected && currentMarks === this.actor.system.armorScore.max) { if (target.dataset.type === 'armor' && !currentMark.selected && !availableArmor) {
ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noAvailableArmorMarks')); ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noAvailableArmorMarks'));
return; return;
} }
} }
const stressUsed = selectedStressMarks.length;
if (target.dataset.type === 'armor' && stressUsed) {
const updateResult = this.updateStressArmor(target.dataset.id, !currentMark.selected);
if (updateResult === false) return;
}
if (currentMark.selected) { if (currentMark.selected) {
const currentDamageLabel = getDamageLabel(currentDamage); const currentDamageLabel = getDamageLabel(currentDamage);
for (let reduction of stressReductions) { for (let reduction of stressReductions) {
@ -232,8 +263,16 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
} }
} }
if (target.dataset.type === 'armor' && selectedStressMarks.length > 0) { if (target.dataset.type === 'stress' && currentMark.armorMarkId) {
selectedStressMarks.forEach(mark => (mark.selected = false)); for (const source of this.marks.armor) {
const match = Object.keys(source.marks).find(key => key === currentMark.armorMarkId);
if (match) {
source.marks[match].selected = false;
break;
}
}
currentMark.armorMarkId = null;
} }
} }
@ -241,6 +280,25 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
this.render(); this.render();
} }
updateStressArmor(armorMarkId, select) {
let stressMarkKey = null;
if (select) {
stressMarkKey = Object.keys(this.marks.stress).find(
key => this.marks.stress[key].selected && !this.marks.stress[key].armorMarkId
);
} else {
stressMarkKey = Object.keys(this.marks.stress).find(
key => this.marks.stress[key].armorMarkId === armorMarkId
);
if (!stressMarkKey)
stressMarkKey = Object.keys(this.marks.stress).find(key => this.marks.stress[key].selected);
}
if (!stressMarkKey) return false;
this.marks.stress[stressMarkKey].armorMarkId = select ? armorMarkId : null;
}
static useStressReduction(_, target) { static useStressReduction(_, target) {
const damageValue = Number(target.dataset.reduction); const damageValue = Number(target.dataset.reduction);
const stressReduction = this.availableStressReductions[damageValue]; const stressReduction = this.availableStressReductions[damageValue];
@ -279,11 +337,19 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
} }
static async takeDamage() { static async takeDamage() {
const { selectedArmorMarks, selectedStressMarks, stressReductions, currentDamage } = this.getDamageInfo(); const { selectedStressMarks, stressReductions, currentDamage } = this.getDamageInfo();
const armorSpent = selectedArmorMarks.length + selectedStressMarks.length; const armorChanges = this.marks.armor.reduce((acc, source) => {
const stressSpent = selectedStressMarks.length + stressReductions.reduce((acc, red) => acc + red.cost, 0); const amount = Object.values(source.marks).filter(x => x.selected).length;
if (!amount) return acc;
this.resolve({ modifiedDamage: currentDamage, armorSpent, stressSpent }); acc.push({ uuid: source.effect.uuid, amount });
return acc;
}, []);
const stressSpent =
selectedStressMarks.filter(x => x.armorMarkId).length +
stressReductions.reduce((acc, red) => acc + red.cost, 0);
this.resolve({ modifiedDamage: currentDamage, armorChanges, stressSpent });
await this.close(true); await this.close(true);
} }

View file

@ -966,11 +966,16 @@ export default class CharacterSheet extends DHBaseActorSheet {
if (armorSources.length <= 1) return; if (armorSources.length <= 1) return;
const useResourcePips = game.settings.get(
CONFIG.DH.id,
CONFIG.DH.SETTINGS.gameSettings.appearance
).useResourcePips;
const html = document.createElement('div'); const html = document.createElement('div');
html.innerHTML = await foundry.applications.handlebars.renderTemplate( html.innerHTML = await foundry.applications.handlebars.renderTemplate(
`systems/daggerheart/templates/ui/tooltip/armorManagement.hbs`, `systems/daggerheart/templates/ui/tooltip/armorManagement.hbs`,
{ {
sources: armorSources sources: armorSources,
useResourcePips
} }
); );
@ -986,6 +991,10 @@ export default class CharacterSheet extends DHBaseActorSheet {
element.addEventListener('blur', CharacterSheet.armorSourceUpdate); element.addEventListener('blur', CharacterSheet.armorSourceUpdate);
element.addEventListener('input', CharacterSheet.armorSourceInput); element.addEventListener('input', CharacterSheet.armorSourceInput);
}); });
html.querySelectorAll('.armor-slot').forEach(element => {
element.addEventListener('click', CharacterSheet.armorSourcePipUpdate);
});
} }
static async armorSourceInput(event) { static async armorSourceInput(event) {
@ -1000,12 +1009,11 @@ export default class CharacterSheet extends DHBaseActorSheet {
static async armorSourceUpdate(event) { static async armorSourceUpdate(event) {
const effect = await foundry.utils.fromUuid(event.target.dataset.uuid); const effect = await foundry.utils.fromUuid(event.target.dataset.uuid);
if (effect.system.changes.length !== 1) return; if (effect.system.changes.length !== 1) return;
const armorEffect = effect.system.changes[0];
const value = Math.max(Math.min(Number.parseInt(event.target.value), effect.system.armorData.max), 0); const value = Math.max(Math.min(Number.parseInt(event.target.value), effect.system.armorData.max), 0);
const newChanges = [ const newChanges = [
{ {
...armorEffect, ...effect.system.changes[0],
value value
} }
]; ];
@ -1017,6 +1025,38 @@ export default class CharacterSheet extends DHBaseActorSheet {
await effect.update({ 'system.changes': newChanges }); await effect.update({ 'system.changes': newChanges });
} }
static async armorSourcePipUpdate(event) {
const target = event.target.closest('.armor-slot');
const effect = await foundry.utils.fromUuid(target.dataset.uuid);
if (effect.system.changes.length !== 1) return;
const { value, max } = effect.system.armorData;
const inputValue = Number.parseInt(target.dataset.value);
const decreasing = value >= inputValue;
const newValue = decreasing ? inputValue - 1 : inputValue;
const newChanges = [
{
...effect.system.changes[0],
value: newValue
}
];
const container = target.closest('.slot-bar');
for (const armorSlot of container.querySelectorAll('.armor-slot i')) {
const index = Number.parseInt(armorSlot.dataset.index);
if (decreasing && index >= newValue) {
armorSlot.classList.remove('fa-shield');
armorSlot.classList.add('fa-shield-halved');
} else if (!decreasing && index < newValue) {
armorSlot.classList.add('fa-shield');
armorSlot.classList.remove('fa-shield-halved');
}
}
await effect.update({ 'system.changes': newChanges });
}
/** /**
* Open the downtime application. * Open the downtime application.
* @type {ApplicationClickAction} * @type {ApplicationClickAction}

View file

@ -559,6 +559,18 @@ export default class DhCharacter extends BaseDataActor {
doc.updateEmbeddedDocuments('ActiveEffect', updates, { render: index === updateValues.length - 1 }); doc.updateEmbeddedDocuments('ActiveEffect', updates, { render: index === updateValues.length - 1 });
} }
async updateArmorEffectValue({ uuid, value }) {
const effect = await foundry.utils.fromUuid(uuid);
await effect.update({
'system.changes': [
{
...effect.system.armorChange,
value: effect.system.armorChange.value + value
}
]
});
}
get sheetLists() { get sheetLists() {
const ancestryFeatures = [], const ancestryFeatures = [],
communityFeatures = [], communityFeatures = [],

View file

@ -626,12 +626,10 @@ export default class DhpActor extends Actor {
} }
); );
if (armorSlotResult) { if (armorSlotResult) {
const { modifiedDamage, armorSpent, stressSpent } = armorSlotResult; const { modifiedDamage, armorChanges, stressSpent } = armorSlotResult;
updates.find(u => u.key === 'hitPoints').value = modifiedDamage; updates.find(u => u.key === 'hitPoints').value = modifiedDamage;
if (armorSpent) { for (const armorChange of armorChanges) {
const armorUpdate = updates.find(u => u.key === 'armor'); updates.push({ value: armorChange.amount, key: 'armor', uuid: armorChange.uuid });
if (armorUpdate) armorUpdate.value += armorSpent;
else updates.push({ value: armorSpent, key: 'armor' });
} }
if (stressSpent) { if (stressSpent) {
const stressUpdate = updates.find(u => u.key === 'stress'); const stressUpdate = updates.find(u => u.key === 'stress');
@ -778,7 +776,8 @@ export default class DhpActor extends Actor {
); );
break; break;
case 'armor': case 'armor':
this.system.updateArmorValue(r); if (!r.uuid) this.system.updateArmorValue(r);
else this.system.updateArmorEffectValue(r);
break; break;
default: default:
if (this.system.resources?.[r.key]) { if (this.system.resources?.[r.key]) {

View file

@ -35,7 +35,10 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
width: 100%;
&.full-width {
width: 100%;
}
} }
.padded { .padded {
@ -45,6 +48,7 @@
.armor-title { .armor-title {
margin: 0; margin: 0;
white-space: nowrap; white-space: nowrap;
width: 100%;
} }
.resources-container { .resources-container {
@ -62,12 +66,17 @@
.mark-selection { .mark-selection {
display: flex; display: flex;
align-items: center; flex-direction: column;
width: 100%; width: 100%;
margin: 0; margin: 0;
h4 {
margin: 0;
}
.mark-selection-inner { .mark-selection-inner {
display: flex; display: flex;
justify-content: center;
gap: 8px; gap: 8px;
.mark-container { .mark-container {
@ -91,6 +100,19 @@
opacity: 0.2; opacity: 0.2;
} }
&.spent {
::after {
position: absolute;
content: '/';
color: red;
font-weight: 700;
font-size: 1.8em;
left: -1px;
top: -7px;
rotate: 13deg;
}
}
.fa-shield { .fa-shield {
position: relative; position: relative;
right: 0.5px; right: 0.5px;

View file

@ -276,6 +276,23 @@
} }
} }
.slot-label {
.slot-value-container {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
i {
position: absolute;
right: 0;
font-size: 12px;
color: light-dark(@beige, @dark-blue);
}
}
}
.status-value { .status-value {
padding: 0 5px; padding: 0 5px;
} }

View file

@ -97,4 +97,27 @@
} }
} }
} }
.slot-bar {
display: flex;
flex-wrap: wrap;
gap: 4px;
padding: 5px;
border: 1px solid light-dark(@dark-blue, @golden);
border-radius: 6px;
z-index: 1;
background: @dark-blue;
justify-content: center;
color: light-dark(@dark-blue, @golden);
.armor-slot {
cursor: pointer;
transition: all 0.3s ease;
font-size: var(--font-size-12);
.fa-shield-halved {
color: light-dark(@dark-blue-40, @golden-40);
}
}
}
} }

View file

@ -7,53 +7,57 @@
<div class="section-container padded"> <div class="section-container padded">
<div class="resources-container"> <div class="resources-container">
<div class="resource-container"> <div class="resource-container">
<h4 class="armor-title">{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.armorMarks"}}</h4> <h4 class="armor-title">{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.maxUseableArmor"}}</h4>
<div class="markers-subtitle">{{armorMarks}}/{{armorScore}}</div> <div class="markers-subtitle">{{availableArmor}}</div>
</div> </div>
{{#if this.stress}}
<div class="resource-container">
<h4 class="armor-title">{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.stress"}}</h4>
<div class="markers-subtitle">{{this.stress.value}}/{{this.stress.max}}</div>
</div>
{{/if}}
</div> </div>
</div> </div>
<div class="section-container"> <div class="section-container full-width">
<h4 class="mark-selection divider"> {{#each marks.armor as |source|}}
<div class="mark-selection-inner"> <div class="mark-selection">
{{#each marks.armor}} <h4 class="divider">{{source.label}}</h4>
<div <div class="mark-selection-inner">
class="mark-container {{#if this.selected}}selected{{/if}}" {{#each source.marks}}
data-action="setMarks" data-key="{{@key}}" data-type="armor" <a
> class="mark-container {{#if this.selected}}selected{{/if}} {{#if this.spent}}spent{{/if}} {{#if this.disabled}}inactive{{/if}}"
<i class="fa-solid fa-shield"></i> data-action="setMarks" data-type="armor" data-path="{{concat "armor." @../key ".marks." @key}}" data-id="{{@key}}"
</div> {{#if this.disabled}}disabled{{/if}}
{{/each}} >
<i class="fa-solid fa-shield"></i>
</a>
{{/each}}
</div>
</div>
{{/each}}
{{#if usesStressArmor}}
<div class="mark-selection">
<h4 class="divider">{{localize "Stress"}}</h4>
<div class="mark-selection-inner">
{{#each marks.stress}} {{#each marks.stress}}
<div <div
class="mark-container {{#if this.selected}}selected{{/if}} {{#if (not @root.basicMarksUsed)}}inactive{{/if}}" class="mark-container {{#if this.selected}}selected{{/if}} {{#if (not @root.basicMarksUsed)}}inactive{{/if}}"
{{#if @root.basicMarksUsed}}data-action="setMarks"{{/if}} data-key="{{@key}}" data-type="stress" data-tooltip="{{#if @root.basicMarksUsed}}{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.armorWithStress"}}{{else}}{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.unncessaryStress"}}{{/if}}" {{#if @root.basicMarksUsed}}data-action="setMarks"{{/if}} data-type="stress" data-path="{{concat "stress." @key}}" data-tooltip="{{#if @root.basicMarksUsed}}{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.armorWithStress"}}{{else}}{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.unncessaryStress"}}{{/if}}"
> >
<i class="fa-solid fa-bolt"></i> <i class="fa-solid fa-bolt"></i>
</div> </div>
{{/each}} {{/each}}
</div>
</div> </div>
</h4> {{/if}}
<div class="markers-subtitle bold">{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.usedMarks"}}</div>
</div> </div>
{{#if availableStressReductions}} {{#if availableStressReductions}}
<div class="resources-container"> <div class="resources-container">
<div class="resource-container"> <div class="resource-container">
<h4 class="armor-title">{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.stressReduction"}}</h4> <h4 class="armor-title divider">{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.stressReduction"}}</h4>
</div> </div>
</div> </div>
{{/if}} {{/if}}
{{#each availableStressReductions}} {{#each availableStressReductions}}
<div class="section-container"> <div class="section-container">
<h4 class="chip-container divider"> <h4 class="chip-container">
<div class="chip-inner-container selectable {{#if (or this.any (eq this.from @root.currentDamage))}}active{{/if}} {{#if this.selected}}selected{{/if}}" data-action="useStressReduction" data-reduction="{{@key}}"> <div class="chip-inner-container selectable {{#if (or this.any (eq this.from @root.currentDamage))}}active{{/if}} {{#if this.selected}}selected{{/if}}" data-action="useStressReduction" data-reduction="{{@key}}">
{{#if this.any}} {{#if this.any}}
{{localize "DAGGERHEART.GENERAL.any"}} {{localize "DAGGERHEART.GENERAL.any"}}
@ -74,7 +78,7 @@
{{#if reduceSeverity}} {{#if reduceSeverity}}
<div class="resources-container"> <div class="resources-container">
<div class="resource-container"> <div class="resource-container">
<h4 class="armor-title">{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.reduceSeverity" nr=reduceSeverity}}</h4> <h4 class="armor-title divider">{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.reduceSeverity" nr=reduceSeverity}}</h4>
</div> </div>
</div> </div>
{{/if}} {{/if}}
@ -82,7 +86,7 @@
{{#if thresholdImmunities}} {{#if thresholdImmunities}}
<div class="resources-container"> <div class="resources-container">
<div class="resource-container"> <div class="resource-container">
<h4 class="armor-title">{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.thresholdImmunities"}}</h4> <h4 class="armor-title divider">{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.thresholdImmunities"}}</h4>
</div> </div>
</div> </div>
{{/if}} {{/if}}

View file

@ -45,10 +45,13 @@
</a> </a>
{{/times}} {{/times}}
</div> </div>
<div class="slot-label"> <a class="slot-label" data-action="toggleArmorMangement">
<span class="label">{{localize "DAGGERHEART.GENERAL.armorSlots"}}</span> <span class="label">{{localize "DAGGERHEART.GENERAL.armorSlots"}}</span>
<span class="value">{{document.system.armorScore.value}} / {{document.system.armorScore.max}}</span> <div class="slot-value-container">
</div> <span class="value">{{document.system.armorScore.value}} / {{document.system.armorScore.max}}</span>
<i class="fa-solid fa-gear"></i>
</div>
</a>
</div> </div>
{{else}} {{else}}
<div class='status-value'> <div class='status-value'>
@ -61,10 +64,10 @@
value='{{document.system.armorScore.value}}' value='{{document.system.armorScore.value}}'
max='{{document.system.armorScore.max}}' max='{{document.system.armorScore.max}}'
></progress> ></progress>
<div class="status-label" data-action="toggleArmorMangement"> <a class="status-label" data-action="toggleArmorMangement">
<h4>{{localize "DAGGERHEART.GENERAL.armorSlots"}}</h4> <h4>{{localize "DAGGERHEART.GENERAL.armorSlots"}}</h4>
<i class="fa-solid fa-gear"></i> <i class="fa-solid fa-gear"></i>
</div> </a>
{{/if}} {{/if}}
</div> </div>
{{else}} {{else}}

View file

@ -1,19 +1,36 @@
<div class="daggerheart armor-management-container"> <div class="daggerheart armor-management-container">
{{#each sources as |source|}} {{#each sources as |source|}}
<div class="armor-source-container"> {{#if ../useResourcePips}}
<label class="armor-source-label">{{source.name}}</label> <div class="armor-source-container">
<div class="status-bar armor-slots"> <label class="armor-source-label">{{source.name}}</label>
<div class='status-value'> <div class="slot-bar">
<input class="bar-input armor-marks-input" value="{{source.value}}" data-uuid="{{source.uuid}}" type="number"> {{#times source.max}}
<span>/</span> <a class='armor-slot' data-value="{{add this 1}}" data-uuid="{{source.uuid}}">
<span class="bar-label">{{source.max}}</span> {{#if (gte ../value (add this 1))}}
<i class="fa-solid fa-shield" data-index="{{this}}"></i>
{{else}}
<i class="fa-solid fa-shield-halved" data-index="{{this}}"></i>
{{/if}}
</a>
{{/times}}
</div> </div>
<progress
class='progress-bar stress-color'
value='{{source.value}}'
max='{{source.max}}'
></progress>
</div> </div>
</div> {{else}}
<div class="armor-source-container">
<label class="armor-source-label">{{source.name}}</label>
<div class="status-bar armor-slots">
<div class='status-value'>
<input class="bar-input armor-marks-input" value="{{source.value}}" data-uuid="{{source.uuid}}" type="number">
<span>/</span>
<span class="bar-label">{{source.max}}</span>
</div>
<progress
class='progress-bar stress-color'
value='{{source.value}}'
max='{{source.max}}'
></progress>
</div>
</div>
{{/if}}
{{/each}} {{/each}}
</div> </div>