mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-04-22 23:43:37 +02:00
[V14] Armor System ArmorScore (#1744)
* Readded so that armor items have their system defined armor instead of using an ActiveEffect * Consolidate armor source retrieval * Fix regression with updating armor when sources are disabled * Simplify armor pip update * Use helper in damage reduction dialog * . * Corrected SRD Armor Items --------- Co-authored-by: Carlos Fernandez <cfern1990@gmail.com>
This commit is contained in:
parent
50dcbf4396
commit
33fb7bcc69
45 changed files with 365 additions and 1535 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { damageKeyToNumber, getDamageLabel } from '../../helpers/utils.mjs';
|
||||
import { damageKeyToNumber, getArmorSources, getDamageLabel } from '../../helpers/utils.mjs';
|
||||
|
||||
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
|
||||
|
||||
|
|
@ -21,15 +21,11 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
|
|||
this.rulesDefault
|
||||
);
|
||||
|
||||
const allArmorEffects = Array.from(actor.allApplicableEffects()).filter(x => x.system.armorData);
|
||||
const orderedArmorEffects = game.system.api.data.activeEffects.changeTypes.armor.orderEffectsForAutoChange(
|
||||
allArmorEffects,
|
||||
true
|
||||
);
|
||||
const armor = orderedArmorEffects.reduce((acc, effect) => {
|
||||
const { current, max } = effect.system.armorData;
|
||||
const orderedArmorSources = getArmorSources(actor).filter(s => !s.disabled);
|
||||
const armor = orderedArmorSources.reduce((acc, { document }) => {
|
||||
const { current, max } = document.type === 'armor' ? document.system.armor : document.system.armorData;
|
||||
acc.push({
|
||||
effect: effect,
|
||||
effect: document,
|
||||
marks: [...Array(max).keys()].reduce((acc, _, index) => {
|
||||
const spent = index < current;
|
||||
acc[foundry.utils.randomID()] = { selected: false, disabled: spent, spent };
|
||||
|
|
@ -159,8 +155,11 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
|
|||
const parent = source.effect.origin
|
||||
? await foundry.utils.fromUuid(source.effect.origin)
|
||||
: source.effect.parent;
|
||||
|
||||
const useEffectName = parent.type === 'armor' || parent instanceof Actor;
|
||||
const label = useEffectName ? source.effect.name : parent.name;
|
||||
armorSources.push({
|
||||
label: parent.name,
|
||||
label: label,
|
||||
uuid: source.effect.uuid,
|
||||
marks: source.marks
|
||||
});
|
||||
|
|
@ -219,13 +218,10 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
|
|||
|
||||
const maxArmor = this.actor.system.rules.damageReduction.maxArmorMarked.value;
|
||||
this.marks = {
|
||||
armor: Object.keys(this.marks.armor).reduce((acc, key, index) => {
|
||||
const mark = this.marks.armor[key];
|
||||
armor: this.marks.armor.map((mark, index) => {
|
||||
const keepSelectValue = !this.rulesOn || index + 1 <= maxArmor;
|
||||
acc[key] = { ...mark, selected: keepSelectValue ? mark.selected : false };
|
||||
|
||||
return acc;
|
||||
}, {}),
|
||||
return { ...mark, selected: keepSelectValue ? mark.selected : false };
|
||||
}),
|
||||
stress: this.marks.stress
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import DhDeathMove from '../../dialogs/deathMove.mjs';
|
|||
import { CharacterLevelup, LevelupViewMode } from '../../levelup/_module.mjs';
|
||||
import DhCharacterCreation from '../../characterCreation/characterCreation.mjs';
|
||||
import FilterMenu from '../../ux/filter-menu.mjs';
|
||||
import { getDocFromElement, getDocFromElementSync } from '../../../helpers/utils.mjs';
|
||||
import { getArmorSources, getDocFromElement, getDocFromElementSync } from '../../../helpers/utils.mjs';
|
||||
|
||||
/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */
|
||||
|
||||
|
|
@ -943,20 +943,14 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
|||
return;
|
||||
}
|
||||
|
||||
const armorSources = [];
|
||||
for (var effect of Array.from(this.document.allApplicableEffects())) {
|
||||
const origin = effect.origin ? await foundry.utils.fromUuid(effect.origin) : effect.parent;
|
||||
if (!effect.system.armorData || effect.disabled || effect.isSuppressed) continue;
|
||||
|
||||
const originIsActor = origin instanceof Actor;
|
||||
const name = originIsActor ? effect.name : origin.name;
|
||||
armorSources.push({
|
||||
uuid: effect.uuid,
|
||||
name,
|
||||
...effect.system.armorData
|
||||
});
|
||||
}
|
||||
|
||||
const armorSources = getArmorSources(this.document)
|
||||
.filter(s => !s.disabled)
|
||||
.toReversed()
|
||||
.map(({ name, document, data }) => ({
|
||||
...data,
|
||||
uuid: document.uuid,
|
||||
name
|
||||
}));
|
||||
if (!armorSources.length) return;
|
||||
|
||||
const useResourcePips = game.settings.get(
|
||||
|
|
@ -980,11 +974,6 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
|||
direction: 'DOWN'
|
||||
});
|
||||
|
||||
html.querySelectorAll('.armor-marks-input').forEach(element => {
|
||||
element.addEventListener('blur', CharacterSheet.armorSourceUpdate);
|
||||
element.addEventListener('input', CharacterSheet.armorSourceInput);
|
||||
});
|
||||
|
||||
html.querySelectorAll('.armor-slot').forEach(element => {
|
||||
element.addEventListener('click', CharacterSheet.armorSourcePipUpdate);
|
||||
});
|
||||
|
|
@ -999,49 +988,45 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
|||
}
|
||||
|
||||
/** Update specific armor source */
|
||||
static async armorSourceUpdate(event) {
|
||||
const effect = await foundry.utils.fromUuid(event.target.dataset.uuid);
|
||||
const armorChange = effect.system.armorChange;
|
||||
if (!armorChange) return;
|
||||
const current = Math.max(Math.min(Number.parseInt(event.target.value), effect.system.armorData.max), 0);
|
||||
|
||||
const newChanges = effect.system.changes.map(change => ({
|
||||
...change,
|
||||
value: change.type === 'armor' ? { ...change.value, current } : change.value
|
||||
}));
|
||||
|
||||
event.target.value = current;
|
||||
const progressBar = event.target.closest('.status-bar.armor-slots').querySelector('progress');
|
||||
progressBar.value = current;
|
||||
|
||||
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);
|
||||
const armorChange = effect.system.armorChange;
|
||||
if (!armorChange) return;
|
||||
const { uuid, value } = target.dataset;
|
||||
const document = await foundry.utils.fromUuid(uuid);
|
||||
|
||||
const { current } = effect.system.armorData;
|
||||
let inputValue = Number.parseInt(value);
|
||||
let decreasing = false;
|
||||
let newCurrent = 0;
|
||||
|
||||
const inputValue = Number.parseInt(target.dataset.value);
|
||||
const decreasing = current >= inputValue;
|
||||
const newCurrent = decreasing ? inputValue - 1 : inputValue;
|
||||
if (document.type === 'armor') {
|
||||
decreasing = document.system.armor.current >= inputValue;
|
||||
newCurrent = decreasing ? inputValue - 1 : inputValue;
|
||||
await document.update({ 'system.armor.current': newCurrent });
|
||||
} else if (document.system.armorData) {
|
||||
const { current } = document.system.armorData;
|
||||
decreasing = current >= inputValue;
|
||||
newCurrent = decreasing ? inputValue - 1 : inputValue;
|
||||
|
||||
const newChanges = effect.system.changes.map(change => ({
|
||||
...change,
|
||||
value: change.type === 'armor' ? { ...change.value, current: newCurrent } : change.value
|
||||
}));
|
||||
const newChanges = document.system.changes.map(change => ({
|
||||
...change,
|
||||
value: change.type === 'armor' ? { ...change.value, current: newCurrent } : change.value
|
||||
}));
|
||||
|
||||
await document.update({ 'system.changes': newChanges });
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
const container = target.closest('.slot-bar');
|
||||
for (const armorSlot of container.querySelectorAll('.armor-slot i')) {
|
||||
const marked = !decreasing && Number.parseInt(armorSlot.dataset.index) < newCurrent;
|
||||
armorSlot.classList.toggle('fa-shield', marked);
|
||||
armorSlot.classList.toggle('fa-shield-halved', !marked);
|
||||
const index = Number.parseInt(armorSlot.dataset.index);
|
||||
if (decreasing && index >= newCurrent) {
|
||||
armorSlot.classList.remove('fa-shield');
|
||||
armorSlot.classList.add('fa-shield-halved');
|
||||
} else if (!decreasing && index < newCurrent) {
|
||||
armorSlot.classList.add('fa-shield');
|
||||
armorSlot.classList.remove('fa-shield-halved');
|
||||
}
|
||||
}
|
||||
|
||||
await effect.update({ 'system.changes': newChanges });
|
||||
}
|
||||
|
||||
static async #toggleResourceManagement(event, button) {
|
||||
|
|
|
|||
|
|
@ -34,13 +34,6 @@ export default class ArmorSheet extends ItemAttachmentSheet(DHBaseItemSheet) {
|
|||
...super.PARTS
|
||||
};
|
||||
|
||||
_attachPartListeners(partId, htmlElement, options) {
|
||||
super._attachPartListeners(partId, htmlElement, options);
|
||||
|
||||
for (const element of htmlElement.querySelectorAll('.base-score-input'))
|
||||
element.addEventListener('change', this.updateArmorEffect.bind(this));
|
||||
}
|
||||
|
||||
/**@inheritdoc */
|
||||
async _preparePartContext(partId, context) {
|
||||
await super._preparePartContext(partId, context);
|
||||
|
|
@ -48,11 +41,6 @@ export default class ArmorSheet extends ItemAttachmentSheet(DHBaseItemSheet) {
|
|||
switch (partId) {
|
||||
case 'settings':
|
||||
context.features = this.document.system.armorFeatures.map(x => x.value);
|
||||
context.armorScore = this.document.system.armorData.max;
|
||||
break;
|
||||
case 'effects':
|
||||
context.effects.actives = context.effects.actives.filter(x => !x.system.armorData);
|
||||
context.effects.inactives = context.effects.inactives.filter(x => !x.system.armorData);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue