From 213a07b64c397a9ceb3abae7ef95d9f6e12c864e Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sun, 8 Jun 2025 00:52:53 +0200 Subject: [PATCH] Improved Character datamodel --- daggerheart.mjs | 4 +- lang/en.json | 10 +- module/applications/_module.mjs | 2 +- module/applications/levelup.mjs | 24 +- module/applications/rollSelectionDialog.mjs | 59 +--- module/applications/sheets/adversary.mjs | 2 +- .../sheets/{pc.mjs => character.mjs} | 51 ++-- module/data/_module.mjs | 2 +- module/data/{pc.mjs => character.mjs} | 252 +++++------------- module/data/settings/VariantRules.mjs | 5 +- module/documents/actor.mjs | 18 +- module/helpers/handlebarsHelper.mjs | 5 + system.json | 16 +- templates/settings/variant-rules.hbs | 2 + templates/sheets/parts/attributes.hbs | 6 +- templates/sheets/parts/defense.hbs | 24 +- templates/sheets/parts/experience.hbs | 6 +- templates/sheets/parts/weapons.hbs | 32 +-- templates/sheets/pc/pc.hbs | 2 +- templates/views/rollSelection.hbs | 34 --- 20 files changed, 175 insertions(+), 381 deletions(-) rename module/applications/sheets/{pc.mjs => character.mjs} (96%) rename module/data/{pc.mjs => character.mjs} (51%) diff --git a/daggerheart.mjs b/daggerheart.mjs index 58600ad4..044b49a3 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -54,12 +54,12 @@ Hooks.once('init', () => { CONFIG.Actor.documentClass = documents.DhpActor; CONFIG.Actor.dataModels = { - pc: models.DhpPC, + pc: models.DhCharacter, adversary: models.DhpAdversary, environment: models.DhpEnvironment }; Actors.unregisterSheet('core', foundry.appv1.sheets.ActorSheet); - Actors.registerSheet(SYSTEM.id, applications.DhpPCSheet, { types: ['pc'], makeDefault: true }); + Actors.registerSheet(SYSTEM.id, applications.DhCharacterSheet, { types: ['pc'], makeDefault: true }); Actors.registerSheet(SYSTEM.id, applications.DhpAdversarySheet, { types: ['adversary'], makeDefault: true }); Actors.registerSheet(SYSTEM.id, applications.DhpEnvironment, { types: ['environment'], makeDefault: true }); diff --git a/lang/en.json b/lang/en.json index eb5ecd62..0b2cd154 100755 --- a/lang/en.json +++ b/lang/en.json @@ -110,8 +110,14 @@ }, "VariantRules": { "ActionTokens": { - "Name": "Action Tokens", - "Hint": "Give each player action tokens to use in combat" + "label": "Action Tokens", + "hint": "Give each player action tokens to use in combat" + }, + "FIELDS": { + "useCoins": { + "label": "Use Coins", + "hint": "test" + } } }, "DualityRollColor": { diff --git a/module/applications/_module.mjs b/module/applications/_module.mjs index 5c031db0..079fe062 100644 --- a/module/applications/_module.mjs +++ b/module/applications/_module.mjs @@ -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'; diff --git a/module/applications/levelup.mjs b/module/applications/levelup.mjs index 22c6d33e..e53a09f8 100644 --- a/module/applications/levelup.mjs +++ b/module/applications/levelup.mjs @@ -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; }, {}), diff --git a/module/applications/rollSelectionDialog.mjs b/module/applications/rollSelectionDialog.mjs index 3230cf72..66ec0d1e 100644 --- a/module/applications/rollSelectionDialog.mjs +++ b/module/applications/rollSelectionDialog.mjs @@ -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(); } diff --git a/module/applications/sheets/adversary.mjs b/module/applications/sheets/adversary.mjs index b9180bf3..2087ea0a 100644 --- a/module/applications/sheets/adversary.mjs +++ b/module/applications/sheets/adversary.mjs @@ -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'); diff --git a/module/applications/sheets/pc.mjs b/module/applications/sheets/character.mjs similarity index 96% rename from module/applications/sheets/pc.mjs rename to module/applications/sheets/character.mjs index 7433e3f3..759489cb 100644 --- a/module/applications/sheets/pc.mjs +++ b/module/applications/sheets/character.mjs @@ -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; } diff --git a/module/data/_module.mjs b/module/data/_module.mjs index b70b5a23..85dae6dd 100644 --- a/module/data/_module.mjs +++ b/module/data/_module.mjs @@ -1,4 +1,4 @@ -export { default as DhpPC } from './pc.mjs'; +export { default as DhCharacter } from './character.mjs'; export { default as DhClass } from './item/class.mjs'; export { default as DhSubclass } from './item/subclass.mjs'; export { default as DhCombat } from './combat.mjs'; diff --git a/module/data/pc.mjs b/module/data/character.mjs similarity index 51% rename from module/data/pc.mjs rename to module/data/character.mjs index 740b51eb..69861bb8 100644 --- a/module/data/pc.mjs +++ b/module/data/character.mjs @@ -1,45 +1,28 @@ -import { getPathValue } from '../helpers/utils.mjs'; +import { burden } from '../config/generalConfig.mjs'; import ForeignDocumentUUIDField from './fields/foreignDocumentUUIDField.mjs'; import { LevelOptionType } from './levelTier.mjs'; -const fields = foundry.data.fields; - const attributeField = () => - new fields.SchemaField({ - bonus: new fields.NumberField({ initial: 0, integer: true }), - base: new fields.NumberField({ initial: 0, integer: true }), - tierMarked: new fields.BooleanField({ required: true, initial: false }) + new foundry.data.fields.SchemaField({ + value: new foundry.data.fields.NumberField({ initial: 0, integer: true }), + tierMarked: new foundry.data.fields.BooleanField({ initial: false }) }); const resourceField = max => - new fields.SchemaField({ - value: new fields.NumberField({ initial: 0, integer: true }), - bonus: new fields.NumberField({ initial: 0, integer: true }), - min: new fields.NumberField({ initial: 0, integer: true }), - baseMax: new fields.NumberField({ initial: max, integer: true }) + new foundry.data.fields.SchemaField({ + value: new foundry.data.fields.NumberField({ initial: 0, integer: true }), + max: new foundry.data.fields.NumberField({ initial: max, integer: true }) }); -export default class DhpPC extends foundry.abstract.TypeDataModel { +export default class DhCharacter extends foundry.abstract.TypeDataModel { static defineSchema() { + const fields = foundry.data.fields; + return { resources: new fields.SchemaField({ hitPoints: resourceField(6), stress: resourceField(6), - hope: new fields.SchemaField({ - value: new fields.NumberField({ initial: -1, integer: true }), // FIXME. Logic is gte and needs -1 in PC/Hope. Change to 0 - min: new fields.NumberField({ initial: 0, integer: true }) - }) - }), - bonuses: new fields.SchemaField({ - damage: new fields.ArrayField( - new fields.SchemaField({ - value: new fields.NumberField({ integer: true, initial: 0 }), - type: new fields.StringField({ nullable: true }), - initiallySelected: new fields.BooleanField(), - hopeIncrease: new fields.StringField({ initial: null, nullable: true }), - description: new fields.StringField({}) - }) - ) + hope: resourceField(6) }), traits: new fields.SchemaField({ agility: attributeField(), @@ -49,24 +32,18 @@ export default class DhpPC extends foundry.abstract.TypeDataModel { presence: attributeField(), knowledge: attributeField() }), - proficiency: new fields.SchemaField({ - base: new fields.NumberField({ required: true, initial: 1, integer: true }), - bonus: new fields.NumberField({ required: true, initial: 0, integer: true }) - }), - evasion: new fields.SchemaField({ - bonus: new fields.NumberField({ initial: 0, integer: true }) - }), - experiences: new fields.ArrayField( + proficiency: new fields.NumberField({ initial: 1, integer: true }), + evasion: new fields.NumberField({ initial: 0, integer: true }), + experiences: new fields.TypedObjectField( new fields.SchemaField({ - id: new fields.StringField({ required: true }), description: new fields.StringField({}), value: new fields.NumberField({ integer: true, nullable: true, initial: null }) }), { - initial: [ - { id: foundry.utils.randomID(), description: '', value: 2 }, - { id: foundry.utils.randomID(), description: '', value: 2 } - ] + initial: { + [foundry.utils.randomID()]: { description: '', value: 2 }, + [foundry.utils.randomID()]: { description: '', value: 2 } + } } ), gold: new fields.SchemaField({ @@ -76,27 +53,14 @@ export default class DhpPC extends foundry.abstract.TypeDataModel { chests: new fields.NumberField({ initial: 0, integer: true }) }), pronouns: new fields.StringField({}), - domainData: new fields.SchemaField({ - maxLoadout: new fields.NumberField({ initial: 2, integer: true }), - maxCards: new fields.NumberField({ initial: 2, integer: true }) - }), - story: new fields.SchemaField({ - background: new fields.HTMLField(), - appearance: new fields.HTMLField(), - connections: new fields.HTMLField(), - scars: new fields.ArrayField( - new fields.SchemaField({ - name: new fields.StringField({}), - description: new fields.HTMLField() - }) - ) - }), - description: new fields.StringField({}), - //Temporary until new FoundryVersion fix --> See Armor.Mjs DataPreparation - armorMarks: new fields.SchemaField({ - max: new fields.NumberField({ initial: 6, integer: true }), - value: new fields.NumberField({ initial: 0, integer: true }) - }), + scars: new fields.TypedObjectField( + new fields.SchemaField({ + name: new fields.StringField({}), + description: new fields.HTMLField() + }) + ), + story: new fields.HTMLField(), + description: new fields.HTMLField(), class: new fields.SchemaField({ value: new ForeignDocumentUUIDField({ type: 'Item', nullable: true }), subclass: new ForeignDocumentUUIDField({ type: 'Item', nullable: true }) @@ -109,10 +73,6 @@ export default class DhpPC extends foundry.abstract.TypeDataModel { }; } - get tier() { - return this.#getTier(this.levelData.currentLevel); - } - get ancestry() { return this.parent.items.find(x => x.type === 'ancestry') ?? null; } @@ -197,57 +157,21 @@ export default class DhpPC extends foundry.abstract.TypeDataModel { return this.parent.items.find(x => x.type === 'armor' && x.system.equipped); } - get equippedWeapons() { - const primaryWeapon = this.parent.items.find( - x => x.type === 'weapon' && x.system.equipped && !x.system.secondary - ); - const secondaryWeapon = this.parent.items.find( - x => x.type === 'weapon' && x.system.equipped && x.system.secondary - ); - return { - primary: this.#weaponData(primaryWeapon), - secondary: this.#weaponData(secondaryWeapon), - burden: this.getBurden(primaryWeapon, secondaryWeapon) - }; + get primaryWeapon() { + return this.parent.items.find(x => x.type === 'weapon' && x.system.equipped && !x.system.secondary); } - static async unequipBeforeEquip(itemToEquip) { - const equippedWeapons = this.equippedWeapons; - - if (itemToEquip.system.secondary) { - if (equippedWeapons.primary && equippedWeapons.primary.burden === SYSTEM.GENERAL.burden.twoHanded.value) { - await this.parent.items.get(equippedWeapons.primary.id).update({ 'system.equipped': false }); - } - - if (equippedWeapons.secondary) { - await this.parent.items.get(equippedWeapons.secondary.id).update({ 'system.equipped': false }); - } - } else { - if (equippedWeapons.secondary && itemToEquip.system.burden === SYSTEM.GENERAL.burden.twoHanded.value) { - await this.parent.items.get(equippedWeapons.secondary.id).update({ 'system.equipped': false }); - } - - if (equippedWeapons.primary) { - await this.parent.items.get(equippedWeapons.primary.id).update({ 'system.equipped': false }); - } - } + get secondaryWeapon() { + return this.parent.items.find(x => x.type === 'weapon' && x.system.equipped && x.system.secondary); } - get effects() { - return this.parent.items.reduce((acc, item) => { - const effects = item.system.effectData; - if (effects && !item.system.disabled) { - for (var key in effects) { - const effect = effects[key]; - for (var effectEntry of effect) { - if (!acc[key]) acc[key] = []; - acc[key].push({ name: item.name, value: effectEntry }); - } - } - } - - return acc; - }, {}); + get getWeaponBurden() { + return this.primaryWeapon?.system?.burden === burden.twoHanded.value || + (this.primaryWeapon && this.secondaryWeapon) + ? burden.twoHanded.value + : this.primaryWeapon || this.secondaryWeapon + ? burden.oneHanded.value + : null; } get refreshableFeatures() { @@ -263,43 +187,32 @@ export default class DhpPC extends foundry.abstract.TypeDataModel { ); } - //Should not be done in data? - //TODO: REMOVE THIS - #weaponData(weapon) { - return weapon - ? { - id: weapon.id, - name: weapon.name, - trait: game.i18n.localize(CONFIG.daggerheart.ACTOR.abilities[weapon.system.trait].label), - range: CONFIG.daggerheart.GENERAL.range[weapon.system.range], - damage: { - value: weapon.system.damage.value, - type: CONFIG.daggerheart.GENERAL.damageTypes[weapon.system.damage.type] - }, - burden: weapon.system.burden, - feature: CONFIG.daggerheart.ITEM.weaponFeatures[weapon.system.feature], - img: weapon.img, - uuid: weapon.uuid - } - : null; - } + static async unequipBeforeEquip(itemToEquip) { + const primary = this.primaryWeapon, + secondary = this.secondaryWeapon; + if (itemToEquip.system.secondary) { + if (primary && primary.burden === SYSTEM.GENERAL.burden.twoHanded.value) { + await primary.update({ 'system.equipped': false }); + } - prepareBaseData() { - this.resources.hitPoints.max = this.resources.hitPoints.baseMax + this.resources.hitPoints.bonus; - this.resources.stress.max = this.resources.stress.baseMax + this.resources.stress.bonus; - this.evasion.value = (this.class?.system?.evasion ?? 0) + this.evasion.bonus; - this.proficiency.value = this.proficiency.base + this.proficiency.bonus; + if (secondary) { + await secondary.update({ 'system.equipped': false }); + } + } else { + if (secondary && itemToEquip.system.burden === SYSTEM.GENERAL.burden.twoHanded.value) { + await secondary.update({ 'system.equipped': false }); + } - for (var attributeKey in this.traits) { - const attribute = this.traits[attributeKey]; - attribute.value = attribute.base + attribute.bonus; + if (primary) { + await primary.update({ 'system.equipped': false }); + } } } - prepareDerivedData() { - this.resources.hope.max = 6 - this.story.scars.length; - if (this.resources.hope.value >= this.resources.hope.max) { - this.resources.hope.value = Math.max(this.resources.hope.max - 1, 0); + prepareBaseData() { + for (var attributeKey in this.traits) { + const attribute = this.traits[attributeKey]; + /* Levleup handling */ } const armor = this.armor; @@ -311,57 +224,18 @@ export default class DhpPC extends foundry.abstract.TypeDataModel { ? armor.system.baseThresholds.severe + this.levelData.level.current : this.levelData.level.current * 2 }; - - this.applyEffects(); } - applyEffects() { - const effects = this.effects; - for (var key in effects) { - const effectType = effects[key]; - for (var effect of effectType) { - switch (key) { - case SYSTEM.EFFECTS.effectTypes.health.id: - this.resources.hitPoints.bonus += effect.value.valueData.value; - break; - case SYSTEM.EFFECTS.effectTypes.stress.id: - this.resources.stress.bonus += effect.value.valueData.value; - break; - case SYSTEM.EFFECTS.effectTypes.damage.id: - this.bonuses.damage.push({ - value: getPathValue(effect.value.valueData.value, this), - type: 'physical', - description: effect.name, - hopeIncrease: effect.value.valueData.hopeIncrease, - initiallySelected: effect.value.initiallySelected, - appliesOn: effect.value.appliesOn - }); - } - } - } - } - - getBurden(primary, secondary) { - const twoHanded = - primary?.system?.burden === 'twoHanded' || - secondary?.system?.burden === 'twoHanded' || - (primary?.system?.burden === 'oneHanded' && secondary?.system?.burden === 'oneHanded'); - const oneHanded = - !twoHanded && (primary?.system?.burden === 'oneHanded' || secondary?.system?.burden === 'oneHanded'); - - return twoHanded ? 'twoHanded' : oneHanded ? 'oneHanded' : null; - } - - #getTier(level) { - if (level >= 8) return 3; - else if (level >= 5) return 2; - else if (level >= 2) return 1; - else return 0; + prepareDerivedData() { + this.resources.hope.max -= Object.keys(this.scars).length; + this.resources.hope.value = Math.min(this.resources.hope.value, this.resources.hope.max); } } class DhPCLevelData extends foundry.abstract.DataModel { static defineSchema() { + const fields = foundry.data.fields; + return { level: new fields.SchemaField({ current: new fields.NumberField({ required: true, integer: true, initial: 1 }), diff --git a/module/data/settings/VariantRules.mjs b/module/data/settings/VariantRules.mjs index 2a1f948d..7d28a1d7 100644 --- a/module/data/settings/VariantRules.mjs +++ b/module/data/settings/VariantRules.mjs @@ -1,11 +1,14 @@ export default class DhVariantRules extends foundry.abstract.DataModel { + static LOCALIZATION_PREFIXES = ['DAGGERHEART.Settings.VariantRules']; + static defineSchema() { const fields = foundry.data.fields; return { actionTokens: new fields.SchemaField({ enabled: new fields.BooleanField({ required: true, initial: false }), tokens: new fields.NumberField({ required: true, integer: true, initial: 3 }) - }) + }), + useCoins: new fields.BooleanField({ initial: false }) }; } diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index bc116550..0d5ae423 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -173,12 +173,11 @@ export default class DhpActor extends Actor { return { roll, dice: dice[0], modifiers, advantageState: advantage === true ? 1 : advantage === false ? 2 : 0 }; } - async dualityRoll(modifier, shiftKey, bonusDamage = []) { + async dualityRoll(modifier, shiftKey) { let hopeDice = 'd12', fearDice = 'd12', advantageDice = null, - disadvantageDice = null, - bonusDamageString = ''; + disadvantageDice = null; const modifiers = modifier.value !== null @@ -195,12 +194,9 @@ export default class DhpActor extends Actor { : []; if (!shiftKey) { const dialogClosed = new Promise((resolve, _) => { - new RollSelectionDialog( - this.system.experiences, - bonusDamage, - this.system.resources.hope.value, - resolve - ).render(true); + new RollSelectionDialog(this.system.experiences, this.system.resources.hope.value, resolve).render( + true + ); }); const result = await dialogClosed; (hopeDice = result.hope), @@ -214,7 +210,6 @@ export default class DhpActor extends Actor { title: x.description }) ); - bonusDamageString = result.bonusDamage; const automateHope = await game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation.Hope); @@ -268,8 +263,7 @@ export default class DhpActor extends Actor { fear: { dice: fearDice, value: fear }, advantage: { dice: advantageDice, value: advantage }, disadvantage: { dice: disadvantageDice, value: disadvantage }, - modifiers: modifiers, - bonusDamageString + modifiers: modifiers }; } diff --git a/module/helpers/handlebarsHelper.mjs b/module/helpers/handlebarsHelper.mjs index 87d1fb7f..25dd0e5e 100644 --- a/module/helpers/handlebarsHelper.mjs +++ b/module/helpers/handlebarsHelper.mjs @@ -11,6 +11,7 @@ export default class RegisterHandlebarsHelpers { includes: this.includes, debug: this.debug, signedNumber: this.signedNumber, + length: this.length, switch: this.switch, case: this.case }); @@ -82,6 +83,10 @@ export default class RegisterHandlebarsHelpers { return number >= 0 ? `+${number}` : number; } + static length(obj) { + return Object.keys(obj).length; + } + static switch(value, options) { this.switch_value = value; this.switch_break = false; diff --git a/system.json b/system.json index f90f53c8..362f1b31 100644 --- a/system.json +++ b/system.json @@ -163,10 +163,7 @@ "name": "Daggerheart", "sorting": "m", "color": "#08718c", - "packs": [ - "adversaries", - "environments" - ], + "packs": ["adversaries", "environments"], "folders": [ { "name": "Character Options", @@ -186,12 +183,7 @@ "name": "Items", "sorting": "m", "color": "#000000", - "packs": [ - "weapons", - "armors", - "consumables", - "general-items" - ] + "packs": ["weapons", "armors", "consumables", "general-items"] } ] } @@ -211,7 +203,9 @@ }, "documentTypes": { "Actor": { - "pc": {}, + "character": { + "htmlFields": ["story", "description", "scars.*.description"] + }, "adversary": {}, "environment": {} }, diff --git a/templates/settings/variant-rules.hbs b/templates/settings/variant-rules.hbs index f39cb2a9..2c4d7d30 100644 --- a/templates/settings/variant-rules.hbs +++ b/templates/settings/variant-rules.hbs @@ -8,6 +8,8 @@ + {{formGroup settingFields.schema.fields.useCoins value=settingFields._source.useCoins localize=true }} +