diff --git a/lang/en.json b/lang/en.json index 59b058ab..54c70ae9 100755 --- a/lang/en.json +++ b/lang/en.json @@ -437,7 +437,7 @@ "text": "Are you sure you want to delete {name}?" }, "DamageReduction": { - "maxUseableArmor": "Useable Armor Slots", + "armorMarks": "Armor Marks", "armorWithStress": "Spend 1 stress to use an extra mark", "thresholdImmunities": "Threshold Immunities", "stress": "Stress", diff --git a/module/applications/dialogs/damageReductionDialog.mjs b/module/applications/dialogs/damageReductionDialog.mjs index 31e4f72d..d4a2b4d3 100644 --- a/module/applications/dialogs/damageReductionDialog.mjs +++ b/module/applications/dialogs/damageReductionDialog.mjs @@ -10,8 +10,7 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap this.reject = reject; this.actor = actor; this.damage = damage; - // this.damageType = damageType; - this.damageType = ['physical']; + this.damageType = damageType; this.rulesDefault = game.settings.get( CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation @@ -21,25 +20,14 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap this.rulesDefault ); - const allArmorEffects = Array.from(actor.allApplicableEffects()).filter(x => x.type === 'armor'); - const orderedArmorEffects = game.system.api.data.activeEffects.ArmorEffect.orderEffectsForAutoChange( - 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 canApplyArmor = damageType.every(t => actor.system.armorApplicableDamageTypes[t] === true); + const availableArmor = actor.system.armorScore.max - actor.system.armorScore.value; + const maxArmorMarks = canApplyArmor ? availableArmor : 0; + const armor = [...Array(maxArmorMarks).keys()].reduce((acc, _) => { + acc[foundry.utils.randomID()] = { selected: false }; return acc; - }, []); + }, {}); const stress = [...Array(actor.system.rules.damageReduction.maxArmorMarked.stressExtra ?? 0).keys()].reduce( (acc, _) => { acc[foundry.utils.randomID()] = { selected: false }; @@ -133,11 +121,13 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap context.thresholdImmunities = Object.keys(this.thresholdImmunities).length > 0 ? this.thresholdImmunities : null; - const { selectedStressMarks, stressReductions, currentMarks, currentDamage, maxArmorUsed, availableArmor } = + const { selectedArmorMarks, selectedStressMarks, stressReductions, currentMarks, currentDamage } = this.getDamageInfo(); context.armorScore = this.actor.system.armorScore.max; context.armorMarks = currentMarks; + context.basicMarksUsed = + selectedArmorMarks.length === this.actor.system.rules.damageReduction.maxArmorMarked.value; const stressReductionStress = this.availableStressReductions ? stressReductions.reduce((acc, red) => acc + red.cost, 0) @@ -151,27 +141,16 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap } : null; - context.maxArmorUsed = maxArmorUsed; - context.availableArmor = availableArmor; - context.basicMarksUsed = availableArmor === 0 || selectedStressMarks.length; - - 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 - }); - } + const maxArmor = this.actor.system.rules.damageReduction.maxArmorMarked.value; context.marks = { - armor: armorSources, + armor: Object.keys(this.marks.armor).reduce((acc, key, index) => { + const mark = this.marks.armor[key]; + if (!this.rulesOn || index + 1 <= maxArmor) acc[key] = mark; + + return acc; + }, {}), stress: this.marks.stress }; - - context.usesStressArmor = Object.keys(context.marks.stress).length; context.availableStressReductions = this.availableStressReductions; context.damage = getDamageLabel(this.damage); @@ -188,31 +167,27 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap } getDamageInfo = () => { - const selectedArmorMarks = this.marks.armor.flatMap(x => Object.values(x.marks).filter(x => x.selected)); + const selectedArmorMarks = Object.values(this.marks.armor).filter(x => x.selected); const selectedStressMarks = Object.values(this.marks.stress).filter(x => x.selected); const stressReductions = this.availableStressReductions ? Object.values(this.availableStressReductions).filter(red => red.selected) : []; - const currentMarks = this.actor.system.armorScore.value + selectedArmorMarks.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 currentMarks = + this.actor.system.armorScore.value + selectedArmorMarks.length + selectedStressMarks.length; const armorMarkReduction = selectedArmorMarks.length * this.actor.system.rules.damageReduction.increasePerArmorMark; - let currentDamage = Math.max(this.damage - armorMarkReduction - stressReductions.length, 0); + let currentDamage = Math.max( + this.damage - armorMarkReduction - selectedStressMarks.length - stressReductions.length, + 0 + ); if (this.reduceSeverity) { currentDamage = Math.max(currentDamage - this.reduceSeverity, 0); } if (this.thresholdImmunities[currentDamage]) currentDamage = 0; - return { selectedStressMarks, stressReductions, currentMarks, currentDamage, maxArmorUsed, availableArmor }; + return { selectedArmorMarks, selectedStressMarks, stressReductions, currentMarks, currentDamage }; }; static toggleRules() { @@ -234,8 +209,8 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap } static setMarks(_, target) { - const currentMark = foundry.utils.getProperty(this.marks, target.dataset.path); - const { selectedStressMarks, stressReductions, currentDamage, availableArmor } = this.getDamageInfo(); + const currentMark = this.marks[target.dataset.type][target.dataset.key]; + const { selectedStressMarks, stressReductions, currentMarks, currentDamage } = this.getDamageInfo(); if (!currentMark.selected && currentDamage === 0) { ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.damageAlreadyNone')); @@ -243,18 +218,12 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap } if (this.rulesOn) { - if (target.dataset.type === 'armor' && !currentMark.selected && !availableArmor) { + if (!currentMark.selected && currentMarks === this.actor.system.armorScore.max) { ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noAvailableArmorMarks')); 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) { const currentDamageLabel = getDamageLabel(currentDamage); for (let reduction of stressReductions) { @@ -263,16 +232,8 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap } } - if (target.dataset.type === 'stress' && currentMark.armorMarkId) { - 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; + if (target.dataset.type === 'armor' && selectedStressMarks.length > 0) { + selectedStressMarks.forEach(mark => (mark.selected = false)); } } @@ -280,25 +241,6 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap 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) { const damageValue = Number(target.dataset.reduction); const stressReduction = this.availableStressReductions[damageValue]; @@ -337,19 +279,11 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap } static async takeDamage() { - const { selectedStressMarks, stressReductions, currentDamage } = this.getDamageInfo(); - const armorChanges = this.marks.armor.reduce((acc, source) => { - const amount = Object.values(source.marks).filter(x => x.selected).length; - if (!amount) return acc; + const { selectedArmorMarks, selectedStressMarks, stressReductions, currentDamage } = this.getDamageInfo(); + const armorSpent = selectedArmorMarks.length + selectedStressMarks.length; + const stressSpent = selectedStressMarks.length + stressReductions.reduce((acc, red) => acc + red.cost, 0); - 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 }); + this.resolve({ modifiedDamage: currentDamage, armorSpent, stressSpent }); await this.close(true); } diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index b9b6a123..c9a6047b 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -966,16 +966,11 @@ export default class CharacterSheet extends DHBaseActorSheet { if (armorSources.length <= 1) return; - const useResourcePips = game.settings.get( - CONFIG.DH.id, - CONFIG.DH.SETTINGS.gameSettings.appearance - ).useResourcePips; const html = document.createElement('div'); html.innerHTML = await foundry.applications.handlebars.renderTemplate( `systems/daggerheart/templates/ui/tooltip/armorManagement.hbs`, { - sources: armorSources, - useResourcePips + sources: armorSources } ); @@ -991,10 +986,6 @@ export default class CharacterSheet extends DHBaseActorSheet { element.addEventListener('blur', CharacterSheet.armorSourceUpdate); element.addEventListener('input', CharacterSheet.armorSourceInput); }); - - html.querySelectorAll('.armor-slot').forEach(element => { - element.addEventListener('click', CharacterSheet.armorSourcePipUpdate); - }); } static async armorSourceInput(event) { @@ -1009,11 +1000,12 @@ export default class CharacterSheet extends DHBaseActorSheet { static async armorSourceUpdate(event) { const effect = await foundry.utils.fromUuid(event.target.dataset.uuid); 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 newChanges = [ { - ...effect.system.changes[0], + ...armorEffect, value } ]; @@ -1025,38 +1017,6 @@ export default class CharacterSheet extends DHBaseActorSheet { 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. * @type {ApplicationClickAction} diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index 1ede6554..87f203ec 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -559,18 +559,6 @@ export default class DhCharacter extends BaseDataActor { 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() { const ancestryFeatures = [], communityFeatures = [], diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 2bc0179a..64e877c9 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -626,10 +626,12 @@ export default class DhpActor extends Actor { } ); if (armorSlotResult) { - const { modifiedDamage, armorChanges, stressSpent } = armorSlotResult; + const { modifiedDamage, armorSpent, stressSpent } = armorSlotResult; updates.find(u => u.key === 'hitPoints').value = modifiedDamage; - for (const armorChange of armorChanges) { - updates.push({ value: armorChange.amount, key: 'armor', uuid: armorChange.uuid }); + if (armorSpent) { + const armorUpdate = updates.find(u => u.key === 'armor'); + if (armorUpdate) armorUpdate.value += armorSpent; + else updates.push({ value: armorSpent, key: 'armor' }); } if (stressSpent) { const stressUpdate = updates.find(u => u.key === 'stress'); @@ -776,8 +778,7 @@ export default class DhpActor extends Actor { ); break; case 'armor': - if (!r.uuid) this.system.updateArmorValue(r); - else this.system.updateArmorEffectValue(r); + this.system.updateArmorValue(r); break; default: if (this.system.resources?.[r.key]) { diff --git a/styles/less/dialog/damage-reduction/damage-reduction-container.less b/styles/less/dialog/damage-reduction/damage-reduction-container.less index e8242bdd..2f343fb3 100644 --- a/styles/less/dialog/damage-reduction/damage-reduction-container.less +++ b/styles/less/dialog/damage-reduction/damage-reduction-container.less @@ -35,10 +35,7 @@ display: flex; flex-direction: column; align-items: center; - - &.full-width { - width: 100%; - } + width: 100%; } .padded { @@ -48,7 +45,6 @@ .armor-title { margin: 0; white-space: nowrap; - width: 100%; } .resources-container { @@ -66,17 +62,12 @@ .mark-selection { display: flex; - flex-direction: column; + align-items: center; width: 100%; margin: 0; - h4 { - margin: 0; - } - .mark-selection-inner { display: flex; - justify-content: center; gap: 8px; .mark-container { @@ -100,19 +91,6 @@ 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 { position: relative; right: 0.5px; diff --git a/styles/less/sheets/actors/character/sidebar.less b/styles/less/sheets/actors/character/sidebar.less index ddd3a348..42e40386 100644 --- a/styles/less/sheets/actors/character/sidebar.less +++ b/styles/less/sheets/actors/character/sidebar.less @@ -276,23 +276,6 @@ } } - .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 { padding: 0 5px; } diff --git a/styles/less/ux/tooltip/armorManagement.less b/styles/less/ux/tooltip/armorManagement.less index 390c0a00..bc716fa0 100644 --- a/styles/less/ux/tooltip/armorManagement.less +++ b/styles/less/ux/tooltip/armorManagement.less @@ -97,27 +97,4 @@ } } } - - .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); - } - } - } } diff --git a/templates/dialogs/damageReduction.hbs b/templates/dialogs/damageReduction.hbs index 50fe3422..57d7ee61 100644 --- a/templates/dialogs/damageReduction.hbs +++ b/templates/dialogs/damageReduction.hbs @@ -7,57 +7,53 @@
-

{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.maxUseableArmor"}}

-
{{availableArmor}}
+

{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.armorMarks"}}

+
{{armorMarks}}/{{armorScore}}
+ {{#if this.stress}} +
+

{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.stress"}}

+
{{this.stress.value}}/{{this.stress.max}}
+
+ {{/if}}
-
- {{#each marks.armor as |source|}} -
-

{{source.label}}

-
- {{#each source.marks}} - - - - {{/each}} -
-
- {{/each}} - {{#if usesStressArmor}} -
-

{{localize "Stress"}}

-
+
+

+
+ {{#each marks.armor}} +
+ +
+ {{/each}} {{#each marks.stress}}
{{/each}} -

- {{/if}} + +
{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.usedMarks"}}
{{#if availableStressReductions}}
-

{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.stressReduction"}}

+

{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.stressReduction"}}

{{/if}} {{#each availableStressReductions}}
-

+

{{#if this.any}} {{localize "DAGGERHEART.GENERAL.any"}} @@ -78,7 +74,7 @@ {{#if reduceSeverity}}
-

{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.reduceSeverity" nr=reduceSeverity}}

+

{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.reduceSeverity" nr=reduceSeverity}}

{{/if}} @@ -86,7 +82,7 @@ {{#if thresholdImmunities}}
-

{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.thresholdImmunities"}}

+

{{localize "DAGGERHEART.APPLICATIONS.DamageReduction.thresholdImmunities"}}

{{/if}} diff --git a/templates/sheets/actors/character/sidebar.hbs b/templates/sheets/actors/character/sidebar.hbs index d3be4983..10017343 100644 --- a/templates/sheets/actors/character/sidebar.hbs +++ b/templates/sheets/actors/character/sidebar.hbs @@ -45,13 +45,10 @@ {{/times}}
- +

{{else}}
@@ -64,10 +61,10 @@ value='{{document.system.armorScore.value}}' max='{{document.system.armorScore.max}}' > - + {{/if}}
{{else}} diff --git a/templates/ui/tooltip/armorManagement.hbs b/templates/ui/tooltip/armorManagement.hbs index f5cf0d32..aa8c9878 100644 --- a/templates/ui/tooltip/armorManagement.hbs +++ b/templates/ui/tooltip/armorManagement.hbs @@ -1,36 +1,19 @@
{{#each sources as |source|}} - {{#if ../useResourcePips}} -
- -
- {{#times source.max}} - - {{#if (gte ../value (add this 1))}} - - {{else}} - - {{/if}} - - {{/times}} +
+ +
+
+ + / + {{source.max}}
+
- {{else}} -
- -
-
- - / - {{source.max}} -
- -
-
- {{/if}} +
{{/each}}
\ No newline at end of file