Improved Character datamodel

This commit is contained in:
WBHarry 2025-06-08 00:52:53 +02:00
parent 746e0f239a
commit 213a07b64c
20 changed files with 175 additions and 381 deletions

View file

@ -1,4 +1,4 @@
export { default as DhpPCSheet } from './sheets/pc.mjs';
export { default as DhCharacterSheet } from './sheets/character.mjs';
export { default as DhpAdversarySheet } from './sheets/adversary.mjs';
export { default as DhpClassSheet } from './sheets/items/class.mjs';
export { default as DhpSubclass } from './sheets/items/subclass.mjs';

View file

@ -149,7 +149,10 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
const experienceIncreaseValues = experienceIncreases
.filter(exp => exp.data.length > 0)
.flatMap(exp =>
exp.data.map(data => this.actor.system.experiences.find(x => x.id === data).description)
exp.data.map(data => {
const experience = Object.keys(this.actor.system.experiences).find(x => x === data);
return this.actor.system.experiences[experience].description;
})
);
context.experienceIncreases = {
values: experienceIncreaseValues,
@ -328,10 +331,12 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
break;
case 'experience':
if (!advancement[choiceKey]) advancement[choiceKey] = [];
const data = checkbox.data.map(
data =>
this.actor.system.experiences.find(x => x.id === data)?.description ?? ''
);
const data = checkbox.data.map(data => {
const experience = Object.keys(this.actor.system.experiences).find(
x => x === data
);
return this.actor.system.experiences[experience]?.description ?? '';
});
advancement[choiceKey].push({ data: data, value: checkbox.value });
break;
}
@ -354,8 +359,8 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
new: this.actor.system.resources.stress.max + (advancement.stress ?? 0)
},
evasion: {
old: this.actor.system.evasion.value,
new: this.actor.system.evasion.value + (advancement.evasion ?? 0)
old: this.actor.system.evasion,
new: this.actor.system.evasion + (advancement.evasion ?? 0)
}
},
traits:
@ -421,8 +426,9 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
if (experienceIncreaseTagify) {
tagifyElement(
experienceIncreaseTagify,
this.actor.system.experiences.reduce((acc, experience) => {
acc[experience.id] = { label: experience.description };
Object.keys(this.actor.system.experiences).reduce((acc, id) => {
const experience = this.actor.system.experiences[id];
acc[id] = { label: experience.description };
return acc;
}, {}),

View file

@ -1,7 +1,7 @@
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
export default class RollSelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(experiences, bonusDamage, hopeResource, resolve, isNpc) {
constructor(experiences, hopeResource, resolve) {
super({}, {});
this.experiences = experiences;
@ -17,23 +17,13 @@ export default class RollSelectionDialog extends HandlebarsApplicationMixin(Appl
fear: ['d12'],
advantage: null,
disadvantage: null,
bonusDamage: bonusDamage.reduce((acc, x) => {
if (x.appliesOn === SYSTEM.EFFECTS.applyLocations.attackRoll.id) {
acc.push({
...x,
hopeUses: 0
});
}
return acc;
}, []),
hopeResource: hopeResource
};
}
static DEFAULT_OPTIONS = {
tag: 'form',
id: 'roll-selection', //Having an id causes a new instance to overwrite previous.
id: 'roll-selection',
classes: ['daggerheart', 'views', 'roll-selection'],
position: {
width: 400,
@ -41,8 +31,6 @@ export default class RollSelectionDialog extends HandlebarsApplicationMixin(Appl
},
actions: {
selectExperience: this.selectExperience,
decreaseHopeUse: this.decreaseHopeUse,
increaseHopeUse: this.increaseHopeUse,
setAdvantage: this.setAdvantage,
setDisadvantage: this.setDisadvantage,
finish: this.finish
@ -76,9 +64,8 @@ export default class RollSelectionDialog extends HandlebarsApplicationMixin(Appl
context.disadvantage = this.data.disadvantage;
context.experiences = this.experiences.map(x => ({
...x,
selected: this.selectedExperiences.find(selected => selected.id === x.id)
selected: this.selectedExperiences.includes(x.id)
}));
context.bonusDamage = this.data.bonusDamage;
context.hopeResource = this.data.hopeResource + 1;
context.hopeUsed = this.getHopeUsed();
@ -86,15 +73,7 @@ export default class RollSelectionDialog extends HandlebarsApplicationMixin(Appl
}
static updateSelection(event, _, formData) {
const { bonusDamage, ...rest } = foundry.utils.expandObject(formData.object);
for (var index in bonusDamage) {
this.data.bonusDamage[index].initiallySelected = bonusDamage[index].initiallySelected;
if (bonusDamage[index].hopeUses) {
const value = Number.parseInt(bonusDamage[index].hopeUses);
if (!Number.isNaN(value)) this.data.bonusDamage[index].hopeUses = value;
}
}
const { ...rest } = foundry.utils.expandObject(formData.object);
this.data = foundry.utils.mergeObject(this.data, rest);
this.render();
@ -104,35 +83,12 @@ export default class RollSelectionDialog extends HandlebarsApplicationMixin(Appl
if (this.selectedExperiences.find(x => x.id === button.dataset.key)) {
this.selectedExperiences = this.selectedExperiences.filter(x => x.id !== button.dataset.key);
} else {
this.selectedExperiences = [
...this.selectedExperiences,
this.experiences.find(x => x.id === button.dataset.key)
];
this.selectedExperiences = [...this.selectedExperiences, button.dataset.key];
}
this.render();
}
getHopeUsed() {
return this.data.bonusDamage.reduce((acc, x) => acc + x.hopeUses, 0);
}
static decreaseHopeUse(_, button) {
const index = Number.parseInt(button.dataset.index);
if (this.data.bonusDamage[index].hopeUses - 1 >= 0) {
this.data.bonusDamage[index].hopeUses -= 1;
this.render(true);
}
}
static increaseHopeUse(_, button) {
const index = Number.parseInt(button.dataset.index);
if (this.data.bonusDamage[index].hopeUses <= this.data.hopeResource + 1) {
this.data.bonusDamage[index].hopeUses += 1;
this.render(true);
}
}
static setAdvantage() {
this.data.advantage = this.data.advantage ? null : 'd6';
this.data.disadvantage = null;
@ -149,11 +105,10 @@ export default class RollSelectionDialog extends HandlebarsApplicationMixin(Appl
static async finish() {
const { diceOptions, ...rest } = this.data;
this.resolve({
...rest,
experiences: this.selectedExperiences,
hopeUsed: this.getHopeUsed(),
bonusDamage: this.data.bonusDamage.reduce((acc, x) => acc.concat(` + ${1 + x.hopeUses}${x.value}`), '')
experiences: this.selectedExperiences.map(x => ({ id: x, ...this.experiences[x] }))
});
this.close();
}

View file

@ -362,7 +362,7 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
name: x.actor.name,
img: x.actor.img,
difficulty: x.actor.system.difficulty,
evasion: x.actor.system.evasion.value
evasion: x.actor.system.evasion
}));
const cls = getDocumentClass('ChatMessage');

View file

@ -8,7 +8,7 @@ import DhlevelUp from '../levelup.mjs';
const { ActorSheetV2 } = foundry.applications.sheets;
const { TextEditor } = foundry.applications.ux;
export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
constructor(options = {}) {
super(options);
@ -248,7 +248,8 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
ancestry: ancestry[0],
community: community[0],
advancement: {
...this.mapAdvancementFeatures(this.document, SYSTEM)
// Removed until we have features again
// ...this.mapAdvancementFeatures(this.document, SYSTEM)
}
};
@ -265,8 +266,7 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
vault: vault.map(x => ({
...x,
uuid: x.uuid,
sendToLoadoutDisabled:
this.document.system.domainCards.loadout.length >= this.document.system.domainData.maxLoadout
sendToLoadoutDisabled: this.document.system.domainCards.loadout.length >= 5
}))
};
@ -584,26 +584,21 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
const weapon = await fromUuid(button.dataset.weapon);
const damage = {
value: `${this.document.system.proficiency.value}${weapon.system.damage.value}`,
type: weapon.system.damage.type,
bonusDamage: this.document.system.bonuses.damage
type: weapon.system.damage.type
};
const modifier = this.document.system.traits[weapon.system.trait].value;
const { roll, hope, fear, advantage, disadvantage, modifiers, bonusDamageString } =
await this.document.dualityRoll(
{ title: game.i18n.localize(abilities[weapon.system.trait].label), value: modifier },
event.shiftKey,
damage.bonusDamage
);
damage.value = damage.value.concat(bonusDamageString);
const { roll, hope, fear, advantage, disadvantage, modifiers } = await this.document.dualityRoll(
{ title: game.i18n.localize(abilities[weapon.system.trait].label), value: modifier },
event.shiftKey
);
const targets = Array.from(game.user.targets).map(x => ({
id: x.id,
name: x.actor.name,
img: x.actor.img,
difficulty: x.actor.system.difficulty,
evasion: x.actor.system.evasion.value
evasion: x.actor.system.evasion
}));
const systemData = {
@ -659,7 +654,7 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
static async moveDomainCard(_, button) {
const toVault = button.dataset.action === 'sendToVault';
if (!toVault && this.document.system.domainCards.loadout.length >= this.document.system.domainData.maxLoadout) {
if (!toVault && this.document.system.domainCards.loadout.length >= 5) {
return;
}
@ -860,15 +855,13 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
}
async experienceDescriptionChange(event) {
const newExperiences = [...this.document.system.experiences];
newExperiences[event.currentTarget.dataset.index].description = event.currentTarget.value;
await this.document.update({ 'system.experiences': newExperiences });
const path = `system.experiences.${event.currentTarget.dataset.experience}.description`;
await this.document.update({ [path]: event.currentTarget.value });
}
async experienceValueChange(event) {
const newExperiences = [...this.document.system.experiences];
newExperiences[event.currentTarget.dataset.index].value = event.currentTarget.value;
await this.document.update({ 'system.experiences': newExperiences });
const path = `system.experiences.${event.currentTarget.dataset.index}.value`;
await this.document.update({ [path]: event.currentTarget.value });
}
static setStoryEditor(_, button) {
@ -1080,18 +1073,12 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
const itemObject = await fromUuid(item.uuid);
switch (target) {
case 'weapon-section':
if (
itemObject.system.secondary &&
this.document.system.equippedWeapons.burden === 'twoHanded'
) {
if (itemObject.system.secondary && this.document.system.getWeaponBurden === 'twoHanded') {
ui.notifications.info(
game.i18n.localize('DAGGERHEART.Notification.Info.SecondaryEquipWhileTwohanded')
);
return;
} else if (
itemObject.system.burden === 'twoHanded' &&
this.document.system.equippedWeapons.secondary
) {
} else if (itemObject.system.burden === 'twoHanded' && this.document.system.secondaryWeapon) {
ui.notifications.info(
game.i18n.localize('DAGGERHEART.Notification.Info.TwohandedEquipWhileSecondary')
);
@ -1154,7 +1141,7 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
return;
}
if (this.document.system.domainCards.total.length === this.document.system.domainData.maxCards) {
if (this.document.system.domainCards.total.length === 5) {
ui.notifications.error(game.i18n.localize('DAGGERHEART.Notification.Error.MaxLoadoutReached'));
return;
}
@ -1164,7 +1151,7 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) {
return;
}
if (this.document.system.domainCards.loadout.length >= this.document.system.domainData.maxLoadout) {
if (this.document.system.domainCards.loadout.length >= 5) {
itemData.system.inVault = true;
}