diff --git a/module/applications/levelup.mjs b/module/applications/levelup.mjs index e53a09f8..8ca04026 100644 --- a/module/applications/levelup.mjs +++ b/module/applications/levelup.mjs @@ -204,7 +204,7 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2) const multiclassSubclass = this.actor.system.multiclass?.system?.subclasses?.[0]; const possibleSubclasses = [ - this.actor.system.subclass, + this.actor.system.class.subclass, ...(multiclassSubclass ? [multiclassSubclass] : []) ]; const selectedSubclasses = possibleSubclasses.filter(x => subclassSelections.includes(x.uuid)); diff --git a/module/applications/multiclassDialog.mjs b/module/applications/multiclassDialog.mjs deleted file mode 100644 index f9e53c17..00000000 --- a/module/applications/multiclassDialog.mjs +++ /dev/null @@ -1,115 +0,0 @@ -const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; - -export default class DhpMulticlassDialog extends HandlebarsApplicationMixin(ApplicationV2) { - constructor(actorName, actorClass, resolve) { - super({}); - - this.actorName = actorName; - this.actorClass = actorClass; - this.resolve = resolve; - - this.classChoices = Array.from( - game.items.reduce((acc, x) => { - if (x.type === 'class' && x.name !== actorClass.name) { - acc.add(x); - } - - return acc; - }, new Set()) - ); - this.subclassChoices = []; - this.domainChoices = []; - - this.data = { - class: null, - subclass: null, - domain: null - }; - } - - get title() { - return `${this.actorName} - Multiclass`; - } - - static DEFAULT_OPTIONS = { - classes: ['daggerheart', 'views', 'multiclass'], - position: { width: 600, height: 'auto' }, - actions: { - selectClass: this.selectClass, - selectSubclass: this.selectSubclass, - selectDomain: this.selectDomain, - finish: this.finish - } - }; - - static PARTS = { - form: { - id: 'levelup', - template: 'systems/daggerheart/templates/views/multiclass.hbs' - } - }; - - async _prepareContext(_options) { - const context = await super._prepareContext(_options); - context.classChoices = this.classChoices; - context.subclassChoices = this.subclassChoices; - context.domainChoices = this.domainChoices; - context.disabledFinish = !this.data.class || !this.data.subclass || !this.data.domain; - context.data = this.data; - - return context; - } - - static async selectClass(_, button) { - const oldClass = this.data.class; - this.data.class = this.data.class?.uuid === button.dataset.class ? null : await fromUuid(button.dataset.class); - if (oldClass !== button.dataset.class) { - this.data.subclass = null; - this.data.domain = null; - this.subclassChoices = this.data.class ? this.data.class.system.subclasses : []; - - //FIXME - this.domainChoices = this.data.class - ? this.data.class.system.domains.map(x => { - const config = SYSTEM.DOMAIN.domains[x]; - return { - name: game.i18n.localize(config.name), - id: config.id, - img: config.src, - disabled: this.actorClass.system.domains.includes(config.id) - }; - }) - : []; - } - - this.render(true); - } - - static async selectSubclass(_, button) { - this.data.subclass = - this.data.subclass?.uuid === button.dataset.subclass - ? null - : this.subclassChoices.find(x => x.uuid === button.dataset.subclass); - this.render(true); - } - - static async selectDomain(_, button) { - const domain = - this.data.domain?.id === button.dataset.domain - ? null - : this.domainChoices.find(x => x.id === button.dataset.domain); - if (domain?.disabled) return; - - this.data.domain = domain; - this.render(true); - } - - static finish() { - this.close({}, this.data); - } - - async close(options = {}, data = null) { - this.resolve(data); - super.close(options); - } -} diff --git a/module/applications/sheets/character.mjs b/module/applications/sheets/character.mjs index 759489cb..194f134a 100644 --- a/module/applications/sheets/character.mjs +++ b/module/applications/sheets/character.mjs @@ -55,7 +55,6 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { selectScar: this.selectScar, deleteScar: this.deleteScar, makeDeathMove: this.makeDeathMove, - toggleFeatureDice: this.toggleFeatureDice, setStoryEditor: this.setStoryEditor, itemQuantityDecrease: (_, button) => this.setItemQuantity(button, -1), itemQuantityIncrease: (_, button) => this.setItemQuantity(button, 1), @@ -247,10 +246,7 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { const foundation = { ancestry: ancestry[0], community: community[0], - advancement: { - // Removed until we have features again - // ...this.mapAdvancementFeatures(this.document, SYSTEM) - } + advancement: {} }; const nrLoadoutCards = this.document.system.domainCards.loadout.length; @@ -305,33 +301,6 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { context.inventory = Array(1).fill(Array(5).fill([])); } - context.classFeatures = ( - this.multiclassFeatureSetSelected - ? this.document.system.multiclassFeatures - : this.document.system.classFeatures - ).map(x => { - if (x.system.featureType.type !== 'dice') { - return x; - } - - return { - ...x, - uuid: x.uuid, - system: { - ...x.system, - featureType: { - ...x.system.featureType, - data: { - ...x.system.featureType.data, - property: this.document.system.subclass - ? SYSTEM.ACTOR.featureProperties[x.system.featureType.data.property].path(this.document) - : 0 - } - } - } - }; - }); - return context; } @@ -360,135 +329,6 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { ); } - mapAdvancementFeatures(actor, config) { - if (!actor.system.class.value || !actor.system.class.subclass) return { foundation: null, advancements: [] }; - - const { subclass, multiclassSubclass } = actor.system.subclassFeatures; - - const foundation = { - type: 'foundation', - multiclass: false, - img: actor.system.subclass.img, - subtitle: game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.FoundationTitle'), - domains: actor.system.class.value.system.domains.map(x => config.DOMAIN.domains[x].src), - className: actor.system.class.value.name, - subclassUuid: actor.system.subclass.uuid, - subclassName: actor.system.subclass.name, - spellcast: config.ACTOR.abilities[actor.system.subclass.system.spellcastingTrait]?.name ?? null, - description: actor.system.subclass.system.foundationFeature.description, - abilities: subclass.foundation, - abilityKey: 'foundationFeature' - }; - - const firstKey = - actor.system.subclass.system.specializationFeature.unlocked && - actor.system.subclass.system.specializationFeature.tier === 2 - ? 'sub' - : actor.system.multiclass?.system?.multiclassTier === 2 - ? 'multi' - : null; - const firstType = firstKey === 'sub' ? 'specialization' : 'foundation'; - const firstBase = - firstKey === 'sub' ? actor.system.subclass : firstKey === 'multi' ? actor.system.multiclassSubclass : null; - const first = !firstBase - ? null - : { - type: firstType, - multiclass: firstKey === 'multi', - img: firstBase.img, - subtitle: - firstKey === 'sub' - ? game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.SpecializationTitle') - : game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.FoundationTitle'), - domains: - firstKey === 'sub' - ? actor.system.class.value.system.domains.map(x => config.DOMAIN.domains[x].src) - : actor.system.multiclass.system.domains.map(x => config.DOMAIN.domains[x].src), - className: firstKey === 'sub' ? actor.system.class.value.name : actor.system.multiclass.name, - subclassUuid: firstBase.uuid, - subclassName: firstBase.name, - spellcast: - firstKey === 'sub' - ? null - : (config.ACTOR.abilities[firstBase.system.spellcastingTrait]?.name ?? null), - description: - firstKey === 'sub' - ? firstBase.system.specializationFeature.description - : firstBase.system.foundationFeature.description, - abilities: firstKey === 'sub' ? subclass.specialization : multiclassSubclass.foundation, - abilityKey: firstKey === 'sub' ? 'specializationFeature' : 'foundationFeature' - }; - - const secondKey = - (actor.system.subclass.system.specializationFeature.unlocked && - actor.system.subclass.system.specializationFeature.tier === 3) || - (actor.system.subclass.system.masteryFeature.unlocked && - actor.system.subclass.system.masteryFeature.tier === 3) - ? 'sub' - : actor.system.multiclass?.system?.multiclassTier === 3 || - actor.system.multiclassSubclass?.system?.specializationFeature?.unlocked - ? 'multi' - : null; - const secondBase = - secondKey === 'sub' - ? actor.system.subclass - : secondKey === 'multi' - ? actor.system.multiclassSubclass - : null; - const secondAbilities = secondKey === 'sub' ? subclass : multiclassSubclass; - const secondType = secondBase - ? secondBase.system.masteryFeature.unlocked - ? 'mastery' - : secondBase.system.specializationFeature.unlocked - ? 'specialization' - : 'foundation' - : null; - const second = !secondBase - ? null - : { - type: secondType, - multiclass: secondKey === 'multi', - img: secondBase.img, - subtitle: secondBase.system.masteryFeature.unlocked - ? game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.MasteryTitle') - : secondBase.system.specializationFeature.unlocked - ? game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.SpecializationTitle') - : game.i18n.localize('DAGGERHEART.Sheets.PC.DomainCard.FoundationTitle'), - domains: - secondKey === 'sub' - ? actor.system.class.value.system.domains.map(x => config.DOMAIN.domains[x].src) - : actor.system.multiclass.system.domains.map(x => config.DOMAIN.domains[x].src), - className: secondKey === 'sub' ? actor.system.class.value.name : actor.system.multiclass.name, - subclassUuid: secondBase.uuid, - subclassName: secondBase.name, - spellcast: - secondKey === 'sub' || secondBase.system.specializationFeature.unlocked - ? null - : (config.ACTOR.abilities[firstBase.system.spellcastingTrait]?.name ?? null), - description: secondBase.system.masteryFeature.unlocked - ? secondBase.system.masteryFeature.description - : secondBase.system.specializationFeature.unlocked - ? secondBase.system.specializationFeature.description - : firstBase.system.foundationFeature.description, - abilities: secondBase.system.masteryFeature.unlocked - ? secondAbilities.mastery - : secondBase.system.specializationFeature.unlocked - ? secondAbilities.specialization - : secondAbilities.foundation, - abilityKey: secondBase.system.masteryFeature.unlocked - ? 'masteryFeature' - : secondBase.system.specializationFeature.unlocked - ? 'specializationFeature' - : 'foundationFeature' - }; - - return { - foundation: foundation, - first: first, - second: second - }; - } - async attributeChange(event) { const path = `system.traits.${event.currentTarget.dataset.attribute}.base`; await this.document.update({ [path]: event.currentTarget.value }); @@ -639,7 +479,7 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { } openLevelUp() { - if (!this.document.system.class.value || !this.document.system.subclass) { + if (!this.document.system.class.value || !this.document.system.class.subclass) { ui.notifications.error(game.i18n.localize('DAGGERHEART.Sheets.PC.Errors.missingClassOrSubclass')); return; } @@ -798,62 +638,6 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { } } - static async toggleFeatureDice(_, button) { - const index = Number.parseInt(button.dataset.index); - const feature = this.document.system.classFeatures.find(x => x.uuid === button.dataset.feature); - const path = `system.featureType.data.numbers.${index}`; - if (feature.system.featureType.data.numbers[index]?.used) return; - - if (Object.keys(feature.system.featureType.data.numbers).length <= index) { - const roll = new Roll(feature.system.featureType.data.value); - const rollData = await roll.evaluate(); - const cls = getDocumentClass('ChatMessage'); - const msg = new cls({ - user: game.user.id, - rolls: [roll] - }); - - await cls.create(msg.toObject()); - - await feature.update({ [path]: { value: Number.parseInt(rollData.total), used: false } }); - } else { - await Dialog.confirm({ - title: game.i18n.localize('Confirm feature use'), - content: `Are you sure you want to use ${feature.name}?`, - yes: async () => { - await feature.update({ [path]: { used: true } }); - - const cls = getDocumentClass('ChatMessage'); - const msg = new cls({ - user: game.user.id, - content: await foundry.applications.handlebars.renderTemplate( - 'systems/daggerheart/templates/chat/ability-use.hbs', - { - title: game.i18n.localize('DAGGERHEART.Chat.FeatureTitle'), - card: { - name: `${feature.name} - Roll Of ${feature.system.featureType.data.numbers[index].value}`, - img: feature.img - } - } - ) - }); - - cls.create(msg.toObject()); - }, - no: () => { - return; - }, - defaultYes: false - }); - } - } - - async onFeatureInputBlur(event) { - const feature = this.document.system.classFeatures.find(x => x.uuid === event.currentTarget.dataset.feature); - const value = Number.parseInt(event.currentTarget.value); - if (!Number.isNaN(value)) await feature?.update({ 'system.featureType.data.value': value }); - } - async experienceDescriptionChange(event) { const path = `system.experiences.${event.currentTarget.dataset.experience}.description`; await this.document.update({ [path]: event.currentTarget.value }); @@ -949,8 +733,8 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) { static async useAdvancementCard(_, button) { const item = button.dataset.multiclass === 'true' - ? this.document.system.multiclassSubclass - : this.document.system.subclass; + ? this.document.system.multiclass.subclass + : this.document.system.class.subclass; const ability = item.system[`${button.dataset.key}Feature`]; const title = `${item.name} - ${game.i18n.localize(`DAGGERHEART.Sheets.PC.DomainCard.${capitalize(button.dataset.key)}Title`)}`; diff --git a/module/config/actorConfig.mjs b/module/config/actorConfig.mjs index 4db5ca9c..68596833 100644 --- a/module/config/actorConfig.mjs +++ b/module/config/actorConfig.mjs @@ -76,7 +76,7 @@ export const featureProperties = { }, spellcastingTrait: { name: 'DAGGERHEART.FeatureProperty.SpellcastingTrait', - path: actor => actor.system.traits[actor.system.subclass.system.spellcastingTrait].data.value + path: actor => actor.system.traits[actor.system.class.subclass.system.spellcastingTrait].data.value } }; diff --git a/module/data/character.mjs b/module/data/character.mjs index 69861bb8..a3494ecd 100644 --- a/module/data/character.mjs +++ b/module/data/character.mjs @@ -77,64 +77,10 @@ export default class DhCharacter extends foundry.abstract.TypeDataModel { return this.parent.items.find(x => x.type === 'ancestry') ?? null; } - get multiclassSubclass() { - return this.parent.items.find(x => x.type === 'subclass' && x.system.multiclass) ?? null; - } - - get subclass() { - return this.parent.items.find(x => x.type === 'subclass' && !x.system.multiclass) ?? null; - } - - get subclassFeatures() { - const subclass = this.subclass; - const multiclass = this.multiclassSubclass; - const subclassItems = this.parent.items.filter(x => x.type === 'feature' && x.system.type === 'subclass'); - return { - subclass: !subclass - ? {} - : { - foundation: subclassItems.filter(x => - subclass.system.foundationFeature.abilities.some(ability => ability.uuid === x.uuid) - ), - specialization: subclassItems.filter(x => - subclass.system.specializationFeature.abilities.some(ability => ability.uuid === x.uuid) - ), - mastery: subclassItems.filter(x => - subclass.system.masteryFeature.abilities.some(ability => ability.uuid === x.uuid) - ) - }, - multiclassSubclass: !multiclass - ? {} - : { - foundation: subclassItems.filter(x => - multiclass.system.foundationFeature.abilities.some(ability => ability.uuid === x.uuid) - ), - specialization: subclassItems.filter(x => - multiclass.system.specializationFeature.abilities.some(ability => ability.uuid === x.uuid) - ), - mastery: subclassItems.filter(x => - multiclass.system.masteryFeature.abilities.some(ability => ability.uuid === x.uuid) - ) - } - }; - } - get community() { return this.parent.items.find(x => x.type === 'community') ?? null; } - get classFeatures() { - return this.parent.items.filter( - x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.class.id && !x.system.multiclass - ); - } - - get multiclassFeatures() { - return this.parent.items.filter( - x => x.type === 'feature' && x.system.type === SYSTEM.ITEM.featureTypes.class.id && x.system.multiclass - ); - } - get domains() { const classDomains = this.class ? this.class.system.domains : []; const multiclassDomains = this.multiclass ? this.multiclass.system.domains : []; diff --git a/templates/sheets/pc/pc.hbs b/templates/sheets/pc/pc.hbs index 0ed46e85..abeeb76a 100644 --- a/templates/sheets/pc/pc.hbs +++ b/templates/sheets/pc/pc.hbs @@ -55,7 +55,7 @@ {{/objectSelector}} - {{#objectSelector title="Subclass" ids=(join document.system.subclass.uuid) values=(join document.system.subclass.name) titleFontSize=14}} + {{#objectSelector title="Subclass" ids=(join document.system.class.subclass.uuid) values=(join document.system.class.subclass.name) titleFontSize=14}} {{/objectSelector}}