Fixed up Summary. Fixed multiclass/subclass blocking on selection

This commit is contained in:
WBHarry 2025-06-01 11:50:43 +02:00
parent 57334b0a63
commit 6d075ec44e
7 changed files with 320 additions and 82 deletions

View file

@ -200,27 +200,126 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
case 'summary':
const actorArmor = this.actor.system.armor;
const { current: currentLevel, changed: changedLevel } = this.actor.system.levelData.level;
context.levelAchievements = {
statisticIncreases: {
proficiency: {
old: this.actor.system.proficiency,
new: this.actor.system.proficiency + this.levelup.allInitialAchievements.proficiency
const achievementCards = [];
for (var card of Object.values(this.levelup.domainCards)) {
if (card.uuid) {
const itemCard = await foundry.utils.fromUuid(card.uuid);
achievementCards.push(itemCard);
}
}
context.achievements = {
proficiency: {
old: this.actor.system.proficiency,
new:
this.actor.system.proficiency +
Object.values(this.levelup.allInitialAchievements).reduce(
(acc, x) => acc + x.proficiency,
0
)
},
damageThresholds: {
major: {
old: this.actor.system.damageThresholds.major,
new: this.actor.system.damageThresholds.major + changedLevel - currentLevel
},
damageThresholds: {
major: {
old: this.actor.system.damageThresholds.major,
new: this.actor.system.damageThresholds.major + changedLevel - currentLevel
},
severe: {
old: this.actor.system.damageThresholds.severe,
new:
this.actor.system.damageThresholds.severe +
(actorArmor ? changedLevel - currentLevel : (changedLevel - currentLevel) * 2)
},
unarmored: !actorArmor
}
severe: {
old: this.actor.system.damageThresholds.severe,
new:
this.actor.system.damageThresholds.severe +
(actorArmor ? changedLevel - currentLevel : (changedLevel - currentLevel) * 2)
},
unarmored: !actorArmor
},
domainCards: {
values: achievementCards,
shown: achievementCards.length > 0
},
experiences: {
values: Object.values(this.levelup.allInitialAchievements).flatMap(achievements => {
return Object.values(achievements.newExperiences).reduce((acc, experience) => {
if (experience.name) acc.push(experience);
return acc;
}, []);
})
}
};
context.achievements.proficiency.shown =
context.achievements.proficiency.new > context.achievements.proficiency.old;
context.achievements.experiences.shown = context.achievements.experiences.values.length > 0;
const advancementChoices = this.levelup.selectionData.reduce((acc, data) => {
const advancementChoice = {
...data,
path: `tiers.${data.tier}.levels.${data.level}.optionSelections.${data.optionKey}.${data.checkboxNr}.data`
};
if (acc[data.type]) acc[data.type].push(advancementChoice);
else acc[data.type] = [advancementChoice];
return acc;
}, {});
const advancementCards = [];
const cardChoices = advancementChoices.domainCard ?? [];
for (var card of cardChoices) {
if (card.data.length > 0) {
for (var data of card.data) {
const itemCard = await foundry.utils.fromUuid(data);
advancementCards.push(itemCard);
}
}
}
context.advancements = {
statistics: {
proficiency: {
old: context.achievements.proficiency.new,
new:
context.achievements.proficiency.new +
Object.values(advancementChoices.proficiency ?? {}).reduce((acc, x) => acc + x.value, 0)
},
hitPoints: {
old: this.actor.system.resources.health.max,
new:
this.actor.system.resources.health.max +
Object.values(advancementChoices.hitPoint ?? {}).reduce((acc, x) => acc + x.value, 0)
},
stress: {
old: this.actor.system.resources.stress.max,
new:
this.actor.system.resources.stress.max +
Object.values(advancementChoices.stress ?? {}).reduce((acc, x) => acc + x.value, 0)
},
evasion: {
old: this.actor.system.evasion.value,
new:
this.actor.system.evasion.value +
Object.values(advancementChoices.evasion ?? {}).reduce((acc, x) => acc + x.value, 0)
}
},
traits: Object.values(advancementChoices.trait ?? {}).flatMap(x =>
x.data.map(data => game.i18n.localize(abilities[data].label))
),
domainCards: advancementCards,
experiences: Object.values(advancementChoices.experience ?? {}).flatMap(x =>
x.data.map(data => ({ name: data, modifier: x.value }))
)
};
context.advancements.statistics.proficiency.shown =
context.advancements.statistics.proficiency.new > context.advancements.statistics.proficiency.old;
context.advancements.statistics.hitPoints.shown =
context.advancements.statistics.hitPoints.new > context.advancements.statistics.hitPoints.old;
context.advancements.statistics.stress.shown =
context.advancements.statistics.stress.new > context.advancements.statistics.stress.old;
context.advancements.statistics.evasion.shown =
context.advancements.statistics.evasion.new > context.advancements.statistics.evasion.old;
context.advancements.statistics.shown =
context.advancements.statistics.proficiency.shown ||
context.advancements.statistics.hitPoints.shown ||
context.advancements.statistics.stress.shown ||
context.advancements.statistics.evasion.shown;
break;
}

View file

@ -223,6 +223,66 @@ export class DhLevelup extends foundry.abstract.DataModel {
return acc;
}, {});
}
/* Data to render all options from */
get tierCheckboxGroups() {
const multiclassSelected = Object.values(this.tiers).some(tier =>
Object.values(tier.levels).some(level => {
return Object.keys(level.optionSelections).some(option =>
Object.values(level.optionSelections[option]).some(x => option === 'multiclass' && x.selected)
);
})
);
return Object.keys(this.tiers).map(tierKey => {
const tier = this.tiers[tierKey];
const subclassSelected = Object.values(tier.levels).some(level => {
return Object.keys(level.optionSelections).some(option =>
Object.values(level.optionSelections[option]).some(x => option === 'subclass' && x.selected)
);
});
return {
tierActive: tier.active,
tierName: tier.name,
groups: Object.keys(tier.options).map(optionKey => {
const option = tier.options[optionKey];
const checkboxes = [...Array(option.checkboxSelections).keys()].flatMap(checkboxNr => {
const levelId = Object.keys(tier.levels).find(levelKey => {
const optionSelect = tier.levels[levelKey].optionSelections;
return Object.keys(optionSelect)
.filter(key => key === optionKey)
.some(optionKey => optionSelect[optionKey][checkboxNr]?.selected);
});
const selected = Boolean(levelId);
const disabled = !levelId
? false
: tier.levels[levelId].optionSelections[optionKey][checkboxNr]?.locked;
const multiclassDisabled =
!selected && optionKey === 'multiclass' && (multiclassSelected || subclassSelected);
return [...Array(option.minCost)].map(_ => ({
...option,
tier: tierKey,
level: levelId,
selected: selected,
optionKey: optionKey,
checkboxNr: checkboxNr,
disabled: disabled || multiclassDisabled,
cost: option.minCost
}));
});
return {
label: game.i18n.localize(option.label),
checkboxGroups: chunkify(checkboxes, option.minCost, chunkedBoxes => ({
multi: option.minCost > 1,
checkboxes: chunkedBoxes
}))
};
})
};
});
}
}
class DhLevelupTier extends foundry.abstract.DataModel {
@ -304,40 +364,6 @@ class DhLevelupTier extends foundry.abstract.DataModel {
total: allSelections.total
};
}
/* Data to render all options in a Tier from */
get tierCheckboxGroups() {
return Object.keys(this.options).map(optionKey => {
const option = this.options[optionKey];
const checkboxes = [...Array(option.checkboxSelections).keys()].flatMap(checkboxNr => {
const levelId = Object.keys(this.levels).find(levelKey => {
const optionSelect = this.levels[levelKey].optionSelections;
return Object.keys(optionSelect)
.filter(key => key === optionKey)
.some(optionKey => optionSelect[optionKey][checkboxNr]?.selected);
});
return [...Array(option.minCost)].map(_ => ({
...option,
tier: this.tier,
level: levelId,
selected: Boolean(levelId),
optionKey: optionKey,
checkboxNr: checkboxNr,
disabled: !levelId ? false : this.levels[levelId].optionSelections[optionKey][checkboxNr]?.locked,
cost: option.minCost
}));
});
return {
label: game.i18n.localize(option.label),
checkboxGroups: chunkify(checkboxes, option.minCost, chunkedBoxes => ({
multi: option.minCost > 1,
checkboxes: chunkedBoxes
}))
};
});
}
}
class DhLevelupTierOption extends foundry.abstract.DataModel {