diff --git a/daggerheart.mjs b/daggerheart.mjs index cc923ac6..2399ccdf 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -284,7 +284,6 @@ const preloadHandlebarsTemplates = async function () { 'systems/daggerheart/templates/sheets/pc/parts/heritageCard.hbs', 'systems/daggerheart/templates/sheets/pc/parts/advancementCard.hbs', 'systems/daggerheart/templates/views/parts/level.hbs', - 'systems/daggerheart/templates/components/slider.hbs', 'systems/daggerheart/templates/components/card-preview.hbs', 'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs' ]); diff --git a/lang/en.json b/lang/en.json index 2b5f2724..a18c02dd 100755 --- a/lang/en.json +++ b/lang/en.json @@ -816,7 +816,8 @@ "AbilityCheckTitle": "{ability} Check" }, "AttackRoll": { - "Title": "Attack - {attack}" + "Title": "Attack - {attack}", + "RollDamage": "Roll Damage" }, "DamageRoll": { "Title": "Damage - {damage}", @@ -996,7 +997,8 @@ "Features": "Features", "Guide": "Character Guide", "Items": "Items", - "Appearance": "Appearance" + "Appearance": "Appearance", + "settings": "Settings" }, "Domains": "Domains", "DamageThresholds": { @@ -1010,14 +1012,14 @@ "Subclasses": "Subclasses", "Guide": { "Suggestions": { - "Title": "Suggested", + "Title": "Suggested Equipments", "Traits": { "Title": "Traits" } }, - "SuggestedPrimaryWeaponTitle": "Suggested Primary Weapon", - "SuggestedSecondaryWeaponTitle": "Suggested Secondary Weapon", - "SuggestedArmorTitle": "Suggested Armor", + "SuggestedPrimaryWeaponTitle": "Primary Weapon", + "SuggestedSecondaryWeaponTitle": "Secondary Weapon", + "SuggestedArmorTitle": "Armor", "Inventory": { "Title": "Inventory", "Take": "Take", diff --git a/module/applications/_module.mjs b/module/applications/_module.mjs index 21af5efb..5c031db0 100644 --- a/module/applications/_module.mjs +++ b/module/applications/_module.mjs @@ -1,7 +1,7 @@ export { default as DhpPCSheet } from './sheets/pc.mjs'; export { default as DhpAdversarySheet } from './sheets/adversary.mjs'; -export { default as DhpClassSheet } from './sheets/class.mjs'; -export { default as DhpSubclass } from './sheets/subclass.mjs'; +export { default as DhpClassSheet } from './sheets/items/class.mjs'; +export { default as DhpSubclass } from './sheets/items/subclass.mjs'; export { default as DhpFeatureSheet } from './sheets/items/feature.mjs'; export { default as DhpDomainCardSheet } from './sheets/items/domainCard.mjs'; export { default as DhpAncestry } from './sheets/items/ancestry.mjs'; diff --git a/module/applications/chatMessage.mjs b/module/applications/chatMessage.mjs index fb4cc613..a8cf6f50 100644 --- a/module/applications/chatMessage.mjs +++ b/module/applications/chatMessage.mjs @@ -1,19 +1,11 @@ import DhpDualityRoll from '../data/dualityRoll.mjs'; import { DualityRollColor } from '../data/settings/Appearance.mjs'; -export default class DhpChatMesssage extends ChatMessage { +export default class DhpChatMessage extends ChatMessage { async renderHTML() { - if ( - this.type === 'dualityRoll' || - this.type === 'adversaryRoll' || - this.type === 'damageRoll' || - this.type === 'abilityUse' - ) { - this.content = await foundry.applications.handlebars.renderTemplate(this.content, this.system); - } - /* We can change to fully implementing the renderHTML function if needed, instead of augmenting it. */ const html = await super.renderHTML(); + if ( this.type === 'dualityRoll' && game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.appearance).dualityColorScheme === diff --git a/module/applications/deathMove.mjs b/module/applications/deathMove.mjs index af4a0c9c..ea2c86e6 100644 --- a/module/applications/deathMove.mjs +++ b/module/applications/deathMove.mjs @@ -47,12 +47,15 @@ export default class DhpDeathMove extends HandlebarsApplicationMixin(Application const cls = getDocumentClass('ChatMessage'); const msg = new cls({ user: game.user.id, - content: await renderTemplate('systems/daggerheart/templates/chat/deathMove.hbs', { - player: this.actor.name, - title: game.i18n.localize(this.selectedMove.name), - img: this.selectedMove.img, - description: game.i18n.localize(this.selectedMove.description) - }) + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/deathMove.hbs', + { + player: this.actor.name, + title: game.i18n.localize(this.selectedMove.name), + img: this.selectedMove.img, + description: game.i18n.localize(this.selectedMove.description) + } + ) }); cls.create(msg.toObject()); diff --git a/module/applications/downtime.mjs b/module/applications/downtime.mjs index f1da7678..49d8b1ab 100644 --- a/module/applications/downtime.mjs +++ b/module/applications/downtime.mjs @@ -70,13 +70,16 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV const cls = getDocumentClass('ChatMessage'); const msg = new cls({ user: game.user.id, - content: await renderTemplate('systems/daggerheart/templates/chat/downtime.hbs', { - player: this.actor.name, - title: game.i18n.localize(this.selectedActivity.name), - img: this.selectedActivity.img, - description: game.i18n.localize(this.selectedActivity.description), - refreshedFeatures: refreshedFeatures - }) + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/downtime.hbs', + { + player: this.actor.name, + title: game.i18n.localize(this.selectedActivity.name), + img: this.selectedActivity.img, + description: game.i18n.localize(this.selectedActivity.description), + refreshedFeatures: refreshedFeatures + } + ) }); cls.create(msg.toObject()); diff --git a/module/applications/sheets/adversary.mjs b/module/applications/sheets/adversary.mjs index 54827b84..2087ea0a 100644 --- a/module/applications/sheets/adversary.mjs +++ b/module/applications/sheets/adversary.mjs @@ -330,15 +330,19 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) { ); const cls = getDocumentClass('ChatMessage'); + const systemData = { + roll: roll._formula, + total: roll._total, + modifiers: modifiers, + diceResults: diceResults + }; const msg = new cls({ type: 'adversaryRoll', - system: { - roll: roll._formula, - total: roll._total, - modifiers: modifiers, - diceResults: diceResults - }, - content: 'systems/daggerheart/templates/chat/adversary-roll.hbs', + system: systemData, + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/adversary-roll.hbs', + systemData + ), rolls: [roll] }); @@ -362,21 +366,25 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) { })); const cls = getDocumentClass('ChatMessage'); + const systemData = { + title: button.dataset.name, + origin: this.document.id, + roll: roll._formula, + advantageState, + total: roll._total, + modifiers: modifiers, + dice: dice, + targets: targets, + damage: { value: button.dataset.damage, type: button.dataset.damageType } + }; const msg = new cls({ type: 'adversaryRoll', sound: CONFIG.sounds.dice, - system: { - title: button.dataset.name, - origin: this.document.id, - roll: roll._formula, - advantageState, - total: roll._total, - modifiers: modifiers, - dice: dice, - targets: targets, - damage: { value: button.dataset.damage, type: button.dataset.damageType } - }, - content: 'systems/daggerheart/templates/chat/adversary-attack-roll.hbs', + system: systemData, + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/adversary-attack-roll.hbs', + systemData + ), rolls: [roll] }); diff --git a/module/applications/sheets/class.mjs b/module/applications/sheets/class.mjs deleted file mode 100644 index e9ec1305..00000000 --- a/module/applications/sheets/class.mjs +++ /dev/null @@ -1,483 +0,0 @@ -// import DhpApplicationMixin from '../daggerheart-sheet.mjs'; -// import Tagify from '@yaireo/tagify'; - -// export default class ClassSheet extends DhpApplicationMixin(ItemSheet) { -// static documentType = "class"; - -// /** @override */ -// static get defaultOptions() { -// return foundry.utils.mergeObject(super.defaultOptions, { -// classes: ["daggerheart", "sheet", "class"], -// width: 600, -// height: 'auto', -// resizable: false, -// tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "features" }], -// dragDrop: [ -// { dragSelector: '.suggested-item', dropSelector: null }, -// { dragSelector: null, dropSelector: '.take-section' }, -// { dragSelector: null, dropSelector: '.choice-a-section' }, -// { dragSelector: null, dropSelector: '.choice-b-section' }, -// { dragSelector: null, dropSelector: '.primary-weapon-section' }, -// { dragSelector: null, dropSelector: '.secondary-weapon-section' }, -// { dragSelector: null, dropSelector: '.armor-section' }, -// { dragSelector: null, dropSelector: null }, -// ] -// }); -// } - -// /** @override */ -// async getData() { -// const context = super.getData(); -// context.domains = this.object.system.domains.map(x => SYSTEM.DOMAIN.domains[x].name) - -// return context; -// } - -// activateListeners(html){ -// super.activateListeners(html); - -// const domainInput = $(html).find('.domain-input')[0]; -// const domainTagify = new Tagify(domainInput, { -// tagTextProp: "name", -// enforceWhitelist: true, -// whitelist : Object.keys(SYSTEM.DOMAIN.domains).map(key => { -// const domain = SYSTEM.DOMAIN.domains[key]; -// return { value: key, name: game.i18n.localize(domain.name), src: domain.src, background: domain.background }; -// }), -// maxTags: 2, -// callbacks : { invalid: this.onAddTag }, -// dropdown : { -// mapValueTo: 'name', -// searchKeys: ['name'], -// enabled: 0, -// maxItems: 20, -// closeOnSelect : true, -// highlightFirst: false, -// }, -// templates: { -// tag(tagData){ //z-index: unset; background-image: ${tagData.background}; Maybe a domain specific background for the chips? -// return ` -// -//
-// ${tagData[this.settings.tagTextProp] || tagData.value} -// -//
-//
`; -// }} -// }); - -// domainTagify.on('change', this.onDomainSelect.bind(this)); -// } - -// onAddTag(e){ -// if( e.detail.index ===2 ){ -// ui.notifications.info(game.i18n.localize("DAGGERHEART.Notification.Info.ClassCanOnlyHaveTwoDomains")); -// } -// } - -// async onDomainSelect(event) { -// const domains = event.detail?.value ? JSON.parse(event.detail.value) : []; -// await this.object.update({ "system.domains": domains.map(x => x.value) }); -// this.render(true); -// } - -// async _handleAction(action, event, button) { -// switch(action){ -// case 'removeSubclass': -// await this.removeSubclass(button); -// break; -// case 'viewSubclass': -// await this.viewSubclass(button); -// break; -// case 'removeFeature': -// await this.removeFeature(button); -// break; -// case 'viewFeature': -// await this.viewFeature(button); -// break; -// case 'removeItem': -// await this.removeItem(event); -// break; -// case 'viewItem': -// await this.viewItem(button); -// break; -// case 'removePrimaryWeapon': -// await this.removePrimaryWeapon(event); -// break; -// case 'removeSecondaryWeapon': -// await this.removeSecondaryWeapon(event); -// break; -// case 'removeArmor': -// await this.removeArmor(event); -// break; -// } -// } - -// async removeSubclass(button){ -// await this.object.update({ "system.subclasses": this.object.system.subclasses.filter(x => x.uuid !== button.dataset.subclass)}); -// } - -// async viewSubclass(button){ -// const subclass = await fromUuid(button.dataset.subclass); -// subclass.sheet.render(true); -// } - -// async removeFeature(button){ -// await this.object.update({ "system.features": this.object.system.features.filter(x => x.uuid !== button.dataset.feature)}); -// } - -// async viewFeature(button){ -// const feature = await fromUuid(button.dataset.feature); -// feature.sheet.render(true); -// } - -// async removeItem(event){ -// event.stopPropagation(); -// const type = event.currentTarget.dataset.type; -// const path = `system.inventory.${type}`; -// await this.object.update({ [path]: this.object.system.inventory[type].filter(x => x.uuid !== event.currentTarget.dataset.item)}); -// } - -// async viewItem(button){ -// const item = await fromUuid(button.dataset.item); -// item.sheet.render(true); -// } - -// async removePrimaryWeapon(event){ -// event.stopPropagation(); -// await this.object.update({ "system.characterGuide.suggestedPrimaryWeapon": null }, { diff: false }); -// } - -// async removeSecondaryWeapon(event){ -// event.stopPropagation(); -// await this.object.update({ "system.characterGuide.suggestedSecondaryWeapon": null }, { diff: false }); -// } - -// async removeArmor(event){ -// event.stopPropagation(); -// await this.object.update({ "system.characterGuide.suggestedArmor": null }, { diff: false }); -// } - -// async _onDragStart(event){ -// if(event.currentTarget.classList.contains('suggested-item')){ -// event.dataTransfer.setData("text/plain", JSON.stringify({ type: 'Item', uuid: event.currentTarget.dataset.item })); -// } - -// super._onDragStart(event); -// } - -// async _onDrop(event) { -// const data = TextEditor.getDragEventData(event); -// const item = await fromUuid(data.uuid); -// if(item.type === 'subclass') { -// await this.object.update({ "system.subclasses": [...this.object.system.subclasses, { img: item.img, name: item.name, uuid: item.uuid }] }); -// } -// else if(item.type === 'feature') { - -// await this.object.update({ "system.features": [...this.object.system.features, { img: item.img, name: item.name, uuid: item.uuid }] }); -// } -// else if(item.type === 'weapon'){ -// if(event.currentTarget.classList.contains('primary-weapon-section')){ -// if(!this.object.system.characterGuide.suggestedPrimaryWeapon && !item.system.secondary) await this.object.update({ "system.characterGuide.suggestedPrimaryWeapon": { img: item.img, name: item.name, uuid: item.uuid } }); -// } else if(event.currentTarget.classList.contains('secondary-weapon-section')){ -// if(!this.object.system.characterGuide.suggestedSecondaryWeapon && item.system.secondary) await this.object.update({ "system.characterGuide.suggestedSecondaryWeapon": { img: item.img, name: item.name, uuid: item.uuid } }); -// } -// } -// else if(item.type === 'armor'){ -// if(event.currentTarget.classList.contains('armor-section')){ -// if(!this.object.system.characterGuide.suggestedArmor) await this.object.update({ "system.characterGuide.suggestedArmor": { img: item.img, name: item.name, uuid: item.uuid } }); -// } -// } -// else if(event.currentTarget.classList.contains('choice-a-section')){ -// if(item.type === 'miscellaneous' || item.type === 'consumable'){ -// if(this.object.system.inventory.choiceA.length < 2) await this.object.update({ "system.inventory.choiceA": [...this.object.system.inventory.choiceA, { img: item.img, name: item.name, uuid: item.uuid }] }); -// } -// } -// else if(item.type === 'miscellaneous'){ -// if(event.currentTarget.classList.contains('take-section')){ -// if(this.object.system.inventory.take.length < 3) await this.object.update({ "system.inventory.take": [...this.object.system.inventory.take, { img: item.img, name: item.name, uuid: item.uuid }] }); -// } -// else if(event.currentTarget.classList.contains('choice-b-section')){ -// if(this.object.system.inventory.choiceB.length < 2) await this.object.update({ "system.inventory.choiceB": [...this.object.system.inventory.choiceB, { img: item.img, name: item.name, uuid: item.uuid }] }); -// } -// } -// } -// } - -import DaggerheartSheet from './daggerheart-sheet.mjs'; -import Tagify from '@yaireo/tagify'; - -const { ItemSheetV2 } = foundry.applications.sheets; -const { TextEditor } = foundry.applications.ux; -export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) { - static DEFAULT_OPTIONS = { - tag: 'form', - classes: ['daggerheart', 'sheet', 'class'], - position: { width: 600 }, - actions: { - removeSubclass: this.removeSubclass, - viewSubclass: this.viewSubclass, - removeFeature: this.removeFeature, - viewFeature: this.viewFeature, - removeItem: this.removeItem, - viewItem: this.viewItem, - removePrimaryWeapon: this.removePrimaryWeapon, - removeSecondaryWeapon: this.removeSecondaryWeapon, - removeArmor: this.removeArmor - }, - form: { - handler: this.updateForm, - submitOnChange: true, - closeOnSubmit: false - }, - dragDrop: [ - { dragSelector: '.suggested-item', dropSelector: null }, - { dragSelector: null, dropSelector: '.take-section' }, - { dragSelector: null, dropSelector: '.choice-a-section' }, - { dragSelector: null, dropSelector: '.choice-b-section' }, - { dragSelector: null, dropSelector: '.primary-weapon-section' }, - { dragSelector: null, dropSelector: '.secondary-weapon-section' }, - { dragSelector: null, dropSelector: '.armor-section' }, - { dragSelector: null, dropSelector: null } - ] - }; - - static PARTS = { - form: { - id: 'feature', - template: 'systems/daggerheart/templates/sheets/class.hbs' - } - }; - - _getTabs() { - const tabs = { - features: { - active: true, - cssClass: '', - group: 'primary', - id: 'features', - icon: null, - label: game.i18n.localize('DAGGERHEART.Sheets.Class.Tabs.Features') - }, - guide: { - active: false, - cssClass: '', - group: 'primary', - id: 'guide', - icon: null, - label: game.i18n.localize('DAGGERHEART.Sheets.Class.Tabs.Guide') - } - }; - for (const v of Object.values(tabs)) { - v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active; - v.cssClass = v.active ? 'active' : ''; - } - - return tabs; - } - - _attachPartListeners(partId, htmlElement, options) { - super._attachPartListeners(partId, htmlElement, options); - - const domainInput = htmlElement.querySelector('.domain-input'); - const domainTagify = new Tagify(domainInput, { - tagTextProp: 'name', - enforceWhitelist: true, - whitelist: Object.keys(SYSTEM.DOMAIN.domains).map(key => { - const domain = SYSTEM.DOMAIN.domains[key]; - return { - value: key, - name: game.i18n.localize(domain.label), - src: domain.src, - background: domain.background - }; - }), - maxTags: 2, - callbacks: { invalid: this.onAddTag }, - dropdown: { - mapValueTo: 'name', - searchKeys: ['name'], - enabled: 0, - maxItems: 20, - closeOnSelect: true, - highlightFirst: false - }, - templates: { - tag(tagData) { - //z-index: unset; background-image: ${tagData.background}; Maybe a domain specific background for the chips? - return ` - -
- ${tagData[this.settings.tagTextProp] || tagData.value} - -
-
`; - } - } - }); - - domainTagify.on('change', this.onDomainSelect.bind(this)); - } - - async _prepareContext(_options) { - const context = await super._prepareContext(_options); - context.document = this.document; - context.tabs = this._getTabs(); - context.domains = this.document.system.domains.map(x => SYSTEM.DOMAIN.domains[x].label); - - return context; - } - - static async updateForm(event, _, formData) { - await this.document.update(formData.object); - this.render(); - } - - onAddTag(e) { - if (e.detail.index === 2) { - ui.notifications.info(game.i18n.localize('DAGGERHEART.Notification.Info.ClassCanOnlyHaveTwoDomains')); - } - } - - async onDomainSelect(event) { - const domains = event.detail?.value ? JSON.parse(event.detail.value) : []; - await this.document.update({ 'system.domains': domains.map(x => x.value) }); - this.render(true); - } - - static async removeSubclass(_, button) { - await this.document.update({ - 'system.subclasses': this.document.system.subclasses.filter(x => x.uuid !== button.dataset.subclass) - }); - } - - static async viewSubclass(_, button) { - const subclass = await fromUuid(button.dataset.subclass); - subclass.sheet.render(true); - } - - static async removeFeature(_, button) { - await this.document.update({ - 'system.features': this.document.system.features.filter(x => x.uuid !== button.dataset.feature) - }); - } - - static async viewFeature(_, button) { - const feature = await fromUuid(button.dataset.feature); - feature.sheet.render(true); - } - - static async removeItem(event, button) { - event.stopPropagation(); - const type = button.dataset.type; - const path = `system.inventory.${type}`; - await this.document.update({ - [path]: this.document.system.inventory[type].filter(x => x.uuid !== button.dataset.item) - }); - } - - static async viewItem(_, button) { - const item = await fromUuid(button.dataset.item); - item.sheet.render(true); - } - - static async removePrimaryWeapon(event) { - event.stopPropagation(); - await this.document.update({ 'system.characterGuide.suggestedPrimaryWeapon': null }, { diff: false }); - } - - static async removeSecondaryWeapon(event) { - event.stopPropagation(); - await this.document.update({ 'system.characterGuide.suggestedSecondaryWeapon': null }, { diff: false }); - } - - static async removeArmor(event) { - event.stopPropagation(); - await this.document.update({ 'system.characterGuide.suggestedArmor': null }, { diff: false }); - } - - async _onDrop(event) { - const data = TextEditor.getDragEventData(event); - const item = await fromUuid(data.uuid); - if (item.type === 'subclass') { - await this.document.update({ - 'system.subclasses': [ - ...this.document.system.subclasses, - { img: item.img, name: item.name, uuid: item.uuid } - ] - }); - } else if (item.type === 'feature') { - await this.document.update({ - 'system.features': [ - ...this.document.system.features, - { img: item.img, name: item.name, uuid: item.uuid } - ] - }); - } else if (item.type === 'weapon') { - if (event.currentTarget.classList.contains('primary-weapon-section')) { - if (!this.document.system.characterGuide.suggestedPrimaryWeapon && !item.system.secondary) - await this.document.update({ - 'system.characterGuide.suggestedPrimaryWeapon': { - img: item.img, - name: item.name, - uuid: item.uuid - } - }); - } else if (event.currentTarget.classList.contains('secondary-weapon-section')) { - if (!this.document.system.characterGuide.suggestedSecondaryWeapon && item.system.secondary) - await this.document.update({ - 'system.characterGuide.suggestedSecondaryWeapon': { - img: item.img, - name: item.name, - uuid: item.uuid - } - }); - } - } else if (item.type === 'armor') { - if (event.currentTarget.classList.contains('armor-section')) { - if (!this.document.system.characterGuide.suggestedArmor) - await this.document.update({ - 'system.characterGuide.suggestedArmor': { img: item.img, name: item.name, uuid: item.uuid } - }); - } - } else if (event.currentTarget.classList.contains('choice-a-section')) { - if (item.type === 'miscellaneous' || item.type === 'consumable') { - if (this.document.system.inventory.choiceA.length < 2) - await this.document.update({ - 'system.inventory.choiceA': [ - ...this.document.system.inventory.choiceA, - { img: item.img, name: item.name, uuid: item.uuid } - ] - }); - } - } else if (item.type === 'miscellaneous') { - if (event.currentTarget.classList.contains('take-section')) { - if (this.document.system.inventory.take.length < 3) - await this.document.update({ - 'system.inventory.take': [ - ...this.document.system.inventory.take, - { img: item.img, name: item.name, uuid: item.uuid } - ] - }); - } else if (event.currentTarget.classList.contains('choice-b-section')) { - if (this.document.system.inventory.choiceB.length < 2) - await this.document.update({ - 'system.inventory.choiceB': [ - ...this.document.system.inventory.choiceB, - { img: item.img, name: item.name, uuid: item.uuid } - ] - }); - } - } - } -} diff --git a/module/applications/sheets/environment.mjs b/module/applications/sheets/environment.mjs index 80295b05..8799d41a 100644 --- a/module/applications/sheets/environment.mjs +++ b/module/applications/sheets/environment.mjs @@ -123,10 +123,15 @@ export default class DhpEnvironment extends DaggerheartSheet(DocumentSheetV2) { const cls = getDocumentClass('ChatMessage'); const msg = new cls({ user: game.user.id, - content: await renderTemplate('systems/daggerheart/templates/chat/ability-use.hbs', { - title: game.i18n.format('DAGGERHEART.Chat.EnvironmentTitle', { actionType: button.dataset.actionType }), - card: { name: item.name, img: item.img, description: item.system.description } - }) + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/ability-use.hbs', + { + title: game.i18n.format('DAGGERHEART.Chat.EnvironmentTitle', { + actionType: button.dataset.actionType + }), + card: { name: item.name, img: item.img, description: item.system.description } + } + ) }); cls.create(msg.toObject()); diff --git a/module/applications/sheets/items/class.mjs b/module/applications/sheets/items/class.mjs new file mode 100644 index 00000000..2241a715 --- /dev/null +++ b/module/applications/sheets/items/class.mjs @@ -0,0 +1,270 @@ +import DaggerheartSheet from '../daggerheart-sheet.mjs'; +import Tagify from '@yaireo/tagify'; + +const { ItemSheetV2 } = foundry.applications.sheets; +const { TextEditor } = foundry.applications.ux; +export default class ClassSheet extends DaggerheartSheet(ItemSheetV2) { + static DEFAULT_OPTIONS = { + tag: 'form', + classes: ['daggerheart', 'sheet', 'item', 'dh-style', 'class'], + position: { width: 700 }, + actions: { + removeSubclass: this.removeSubclass, + viewSubclass: this.viewSubclass, + removeFeature: this.removeFeature, + viewFeature: this.viewFeature, + removeItem: this.removeItem, + viewItem: this.viewItem, + removePrimaryWeapon: this.removePrimaryWeapon, + removeSecondaryWeapon: this.removeSecondaryWeapon, + removeArmor: this.removeArmor + }, + form: { + handler: this.updateForm, + submitOnChange: true, + closeOnSubmit: false + }, + dragDrop: [ + { dragSelector: '.suggested-item', dropSelector: null }, + { dragSelector: null, dropSelector: '.take-section' }, + { dragSelector: null, dropSelector: '.choice-a-section' }, + { dragSelector: null, dropSelector: '.choice-b-section' }, + { dragSelector: null, dropSelector: '.primary-weapon-section' }, + { dragSelector: null, dropSelector: '.secondary-weapon-section' }, + { dragSelector: null, dropSelector: '.armor-section' }, + { dragSelector: null, dropSelector: null } + ] + }; + + static PARTS = { + header: { template: 'systems/daggerheart/templates/sheets/items/class/header.hbs' }, + tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, + features: { + template: 'systems/daggerheart/templates/sheets/items/class/features.hbs', + scrollable: ['.features'] + }, + settings: { + template: 'systems/daggerheart/templates/sheets/items/class/settings.hbs', + scrollable: ['.settings'] + } + }; + + static TABS = { + features: { + active: true, + cssClass: '', + group: 'primary', + id: 'features', + icon: null, + label: 'DAGGERHEART.Sheets.Class.Tabs.Features' + }, + settings: { + active: false, + cssClass: '', + group: 'primary', + id: 'settings', + icon: null, + label: 'DAGGERHEART.Sheets.Class.Tabs.settings' + } + }; + + _attachPartListeners(partId, htmlElement, options) { + super._attachPartListeners(partId, htmlElement, options); + + const domainInput = htmlElement.querySelector('.domain-input'); + const domainTagify = new Tagify(domainInput, { + tagTextProp: 'name', + enforceWhitelist: true, + whitelist: Object.keys(SYSTEM.DOMAIN.domains).map(key => { + const domain = SYSTEM.DOMAIN.domains[key]; + return { + value: key, + name: game.i18n.localize(domain.label), + src: domain.src, + background: domain.background + }; + }), + maxTags: 2, + callbacks: { invalid: this.onAddTag }, + dropdown: { + mapValueTo: 'name', + searchKeys: ['name'], + enabled: 0, + maxItems: 20, + closeOnSelect: true, + highlightFirst: false + }, + templates: { + tag(tagData) { + //z-index: unset; background-image: ${tagData.background}; Maybe a domain specific background for the chips? + return ` + +
+ ${tagData[this.settings.tagTextProp] || tagData.value} + +
+
`; + } + } + }); + + domainTagify.on('change', this.onDomainSelect.bind(this)); + } + + async _prepareContext(_options) { + const context = await super._prepareContext(_options); + context.document = this.document; + context.tabs = super._getTabs(this.constructor.TABS); + context.domains = this.document.system.domains.map(x => SYSTEM.DOMAIN.domains[x].label); + + return context; + } + + static async updateForm(event, _, formData) { + await this.document.update(formData.object); + this.render(); + } + + onAddTag(e) { + if (e.detail.index === 2) { + ui.notifications.info(game.i18n.localize('DAGGERHEART.Notification.Info.ClassCanOnlyHaveTwoDomains')); + } + } + + async onDomainSelect(event) { + const domains = event.detail?.value ? JSON.parse(event.detail.value) : []; + await this.document.update({ 'system.domains': domains.map(x => x.value) }); + this.render(true); + } + + static async removeSubclass(_, button) { + await this.document.update({ + 'system.subclasses': this.document.system.subclasses.filter(x => x.uuid !== button.dataset.subclass) + }); + } + + static async viewSubclass(_, button) { + const subclass = await fromUuid(button.dataset.subclass); + subclass.sheet.render(true); + } + + static async removeFeature(_, button) { + await this.document.update({ + 'system.features': this.document.system.features.filter(x => x.uuid !== button.dataset.feature) + }); + } + + static async viewFeature(_, button) { + const feature = await fromUuid(button.dataset.feature); + feature.sheet.render(true); + } + + static async removeItem(event, button) { + event.stopPropagation(); + const type = button.dataset.type; + const path = `system.inventory.${type}`; + await this.document.update({ + [path]: this.document.system.inventory[type].filter(x => x.uuid !== button.dataset.item) + }); + } + + static async viewItem(_, button) { + const item = await fromUuid(button.dataset.item); + item.sheet.render(true); + } + + static async removePrimaryWeapon(event) { + event.stopPropagation(); + await this.document.update({ 'system.characterGuide.suggestedPrimaryWeapon': null }, { diff: false }); + } + + static async removeSecondaryWeapon(event) { + event.stopPropagation(); + await this.document.update({ 'system.characterGuide.suggestedSecondaryWeapon': null }, { diff: false }); + } + + static async removeArmor(event) { + event.stopPropagation(); + await this.document.update({ 'system.characterGuide.suggestedArmor': null }, { diff: false }); + } + + async _onDrop(event) { + const data = TextEditor.getDragEventData(event); + const item = await fromUuid(data.uuid); + if (item.type === 'subclass') { + await this.document.update({ + 'system.subclasses': [ + ...this.document.system.subclasses, + { img: item.img, name: item.name, uuid: item.uuid } + ] + }); + } else if (item.type === 'feature') { + await this.document.update({ + 'system.features': [ + ...this.document.system.features, + { img: item.img, name: item.name, uuid: item.uuid } + ] + }); + } else if (item.type === 'weapon') { + if (event.currentTarget.classList.contains('primary-weapon-section')) { + if (!this.document.system.characterGuide.suggestedPrimaryWeapon && !item.system.secondary) + await this.document.update({ + 'system.characterGuide.suggestedPrimaryWeapon': { + img: item.img, + name: item.name, + uuid: item.uuid + } + }); + } else if (event.currentTarget.classList.contains('secondary-weapon-section')) { + if (!this.document.system.characterGuide.suggestedSecondaryWeapon && item.system.secondary) + await this.document.update({ + 'system.characterGuide.suggestedSecondaryWeapon': { + img: item.img, + name: item.name, + uuid: item.uuid + } + }); + } + } else if (item.type === 'armor') { + if (event.currentTarget.classList.contains('armor-section')) { + if (!this.document.system.characterGuide.suggestedArmor) + await this.document.update({ + 'system.characterGuide.suggestedArmor': { img: item.img, name: item.name, uuid: item.uuid } + }); + } + } else if (event.currentTarget.classList.contains('choice-a-section')) { + if (item.type === 'miscellaneous' || item.type === 'consumable') { + if (this.document.system.inventory.choiceA.length < 2) + await this.document.update({ + 'system.inventory.choiceA': [ + ...this.document.system.inventory.choiceA, + { img: item.img, name: item.name, uuid: item.uuid } + ] + }); + } + } else if (item.type === 'miscellaneous') { + if (event.currentTarget.classList.contains('take-section')) { + if (this.document.system.inventory.take.length < 3) + await this.document.update({ + 'system.inventory.take': [ + ...this.document.system.inventory.take, + { img: item.img, name: item.name, uuid: item.uuid } + ] + }); + } else if (event.currentTarget.classList.contains('choice-b-section')) { + if (this.document.system.inventory.choiceB.length < 2) + await this.document.update({ + 'system.inventory.choiceB': [ + ...this.document.system.inventory.choiceB, + { img: item.img, name: item.name, uuid: item.uuid } + ] + }); + } + } + } +} diff --git a/module/applications/sheets/items/subclass.mjs b/module/applications/sheets/items/subclass.mjs new file mode 100644 index 00000000..d34b8a3f --- /dev/null +++ b/module/applications/sheets/items/subclass.mjs @@ -0,0 +1,121 @@ +import DaggerheartSheet from '../daggerheart-sheet.mjs'; +import DaggerheartFeature from '../../../data/feature.mjs'; + +const { ItemSheetV2 } = foundry.applications.sheets; +const { TextEditor } = foundry.applications.ux; +const { duplicate, getProperty } = foundry.utils; +export default class SubclassSheet extends DaggerheartSheet(ItemSheetV2) { + static DEFAULT_OPTIONS = { + tag: 'form', + classes: ['daggerheart', 'sheet', 'item', 'dh-style', 'subclass'], + position: { width: 600 }, + window: { resizable: false }, + actions: { + editAbility: this.editAbility, + deleteFeatureAbility: this.deleteFeatureAbility + }, + form: { + handler: this.updateForm, + submitOnChange: true, + closeOnSubmit: false + }, + dragDrop: [ + { dragSelector: null, dropSelector: '.foundation-tab' }, + { dragSelector: null, dropSelector: '.specialization-tab' }, + { dragSelector: null, dropSelector: '.mastery-tab' } + ] + }; + + static PARTS = { + header: { template: 'systems/daggerheart/templates/sheets/items/subclass/header.hbs' }, + tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' }, + description: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-description.hbs' }, + features: { + template: 'systems/daggerheart/templates/sheets/items/subclass/features.hbs', + scrollable: ['.features'] + }, + settings: { + template: 'systems/daggerheart/templates/sheets/items/subclass/settings.hbs', + scrollable: ['.settings'] + } + }; + + static TABS = { + description: { + active: true, + cssClass: '', + group: 'primary', + id: 'description', + icon: null, + label: 'DAGGERHEART.Sheets.Feature.Tabs.Description' + }, + features: { + active: false, + cssClass: '', + group: 'primary', + id: 'features', + icon: null, + label: 'DAGGERHEART.Sheets.Feature.Tabs.Features' + }, + settings: { + active: false, + cssClass: '', + group: 'primary', + id: 'settings', + icon: null, + label: 'DAGGERHEART.Sheets.Feature.Tabs.Settings' + } + }; + + async _prepareContext(_options) { + const context = await super._prepareContext(_options); + context.document = this.document; + context.config = CONFIG.daggerheart; + context.tabs = super._getTabs(this.constructor.TABS); + + return context; + } + + static async updateForm(event, _, formData) { + await this.document.update(formData.object); + this.render(); + } + + static async editAbility(_, button) { + const feature = await fromUuid(button.dataset.ability); + feature.sheet.render(true); + } + + static async deleteFeatureAbility(event, button) { + event.preventDefault(); + event.stopPropagation(); + + const feature = button.dataset.feature; + const newAbilities = this.document.system[`${feature}Feature`].abilities.filter( + x => x.uuid !== button.dataset.ability + ); + const path = `system.${feature}Feature.abilities`; + + await this.document.update({ [path]: newAbilities }); + } + + async _onDrop(event) { + event.preventDefault(); + const data = TextEditor.getDragEventData(event); + const item = await fromUuid(data.uuid); + if (!(item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.subclass.id)) return; + + let featureField; + if (event.currentTarget.classList.contains('foundation-tab')) featureField = 'foundation'; + else if (event.currentTarget.classList.contains('specialization-tab')) featureField = 'specialization'; + else if (event.currentTarget.classList.contains('mastery-tab')) featureField = 'mastery'; + else return; + + const path = `system.${featureField}Feature.abilities`; + const abilities = duplicate(getProperty(this.document, path)) || []; + const featureData = { name: item.name, img: item.img, uuid: item.uuid }; + abilities.push(featureData); + + await this.document.update({ [path]: abilities }); + } +} diff --git a/module/applications/sheets/pc.mjs b/module/applications/sheets/pc.mjs index 5823a0fe..2d16b470 100644 --- a/module/applications/sheets/pc.mjs +++ b/module/applications/sheets/pc.mjs @@ -507,27 +507,33 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { ); const cls = getDocumentClass('ChatMessage'); - const msgData = { - type: 'dualityRoll', - sound: CONFIG.sounds.dice, - system: { - title: game.i18n.format('DAGGERHEART.Chat.DualityRoll.AbilityCheckTitle', { - ability: game.i18n.localize(abilities[button.dataset.attribute].label) - }), - origin: this.document.id, - roll: roll._formula, - modifiers: modifiers, - hope: hope, - fear: fear, - advantage: advantage, - disadvantage: disadvantage - }, - user: game.user.id, - content: 'systems/daggerheart/templates/chat/duality-roll.hbs', - rolls: [roll] + + const systemContent = { + title: game.i18n.format('DAGGERHEART.Chat.DualityRoll.AbilityCheckTitle', { + ability: game.i18n.localize(abilities[button.dataset.attribute].label) + }), + origin: this.document.id, + roll: roll._formula, + modifiers: modifiers, + hope: hope, + fear: fear, + advantage: advantage, + disadvantage: disadvantage }; - await cls.create(msgData); + const msg = new cls({ + type: 'dualityRoll', + sound: CONFIG.sounds.dice, + system: systemContent, + user: game.user.id, + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/duality-roll.hbs', + systemContent + ), + rolls: [roll] + }); + + await cls.create(msg.toObject()); } static async toggleMarks(_, button) { @@ -601,23 +607,28 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { evasion: x.actor.system.evasion })); + const systemData = { + title: weapon.name, + origin: this.document.id, + roll: roll._formula, + modifiers: modifiers, + hope: hope, + fear: fear, + advantage: advantage, + disadvantage: disadvantage, + damage: damage, + targets: targets + }; + const cls = getDocumentClass('ChatMessage'); const msg = new cls({ type: 'dualityRoll', sound: CONFIG.sounds.dice, - system: { - title: weapon.name, - origin: this.document.id, - roll: roll._formula, - modifiers: modifiers, - hope: hope, - fear: fear, - advantage: advantage, - disadvantage: disadvantage, - damage: damage, - targets: targets - }, - content: 'systems/daggerheart/templates/chat/attack-roll.hbs', + system: systemData, + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/attack-roll.hbs', + systemData + ), rolls: [roll] }); @@ -655,17 +666,21 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { const card = this.document.items.find(x => x.uuid === button.dataset.key); const cls = getDocumentClass('ChatMessage'); + const systemData = { + title: `${game.i18n.localize('DAGGERHEART.Chat.DomainCard.Title')} - ${capitalize(button.dataset.domain)}`, + img: card.img, + name: card.name, + description: card.system.effect, + actions: card.system.actions + }; const msg = new cls({ type: 'abilityUse', user: game.user.id, - content: 'systems/daggerheart/templates/chat/ability-use.hbs', - system: { - title: `${game.i18n.localize('DAGGERHEART.Chat.DomainCard.Title')} - ${capitalize(button.dataset.domain)}`, - img: card.img, - name: card.name, - description: card.system.effect, - actions: card.system.actions - } + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/ability-use.hbs', + systemData + ), + system: systemData }); cls.create(msg.toObject()); @@ -803,13 +818,16 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { const cls = getDocumentClass('ChatMessage'); const msg = new cls({ user: game.user.id, - content: await 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 + 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()); @@ -870,17 +888,21 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { const item = await fromUuid(button.dataset.id); const cls = getDocumentClass('ChatMessage'); + const systemData = { + title: game.i18n.localize('DAGGERHEART.Chat.FeatureTitle'), + img: item.img, + name: item.name, + description: item.system.description, + actions: item.system.actions + }; const msg = new cls({ type: 'abilityUse', user: game.user.id, - content: 'systems/daggerheart/templates/chat/ability-use.hbs', - system: { - title: game.i18n.localize('DAGGERHEART.Chat.FeatureTitle'), - img: item.img, - name: item.name, - description: item.system.description, - actions: item.system.actions - } + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/ability-use.hbs', + systemData + ), + system: systemData }); cls.create(msg.toObject()); @@ -891,22 +913,26 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { const type = button.dataset.type; const cls = getDocumentClass('ChatMessage'); + const systemData = { + title: + type === 'ancestry' + ? game.i18n.localize('DAGGERHEART.Chat.FoundationCard.AncestryTitle') + : type === 'community' + ? game.i18n.localize('DAGGERHEART.Chat.FoundationCard.CommunityTitle') + : game.i18n.localize('DAGGERHEART.Chat.FoundationCard.SubclassFeatureTitle'), + img: item.img, + name: item.name, + description: item.system.description, + actions: [] + }; const msg = new cls({ type: 'abilityUse', user: game.user.id, - system: { - title: - type === 'ancestry' - ? game.i18n.localize('DAGGERHEART.Chat.FoundationCard.AncestryTitle') - : type === 'community' - ? game.i18n.localize('DAGGERHEART.Chat.FoundationCard.CommunityTitle') - : game.i18n.localize('DAGGERHEART.Chat.FoundationCard.SubclassFeatureTitle'), - img: item.img, - name: item.name, - description: item.system.description, - actions: [] - }, - content: 'systems/daggerheart/templates/chat/ability-use.hbs' + system: systemData, + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/ability-use.hbs', + systemData + ) }); cls.create(msg.toObject()); @@ -923,10 +949,13 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { const cls = getDocumentClass('ChatMessage'); const msg = new cls({ user: game.user.id, - content: await renderTemplate('systems/daggerheart/templates/chat/ability-use.hbs', { - title: game.i18n.localize('DAGGERHEART.Chat.FoundationCard.SubclassFeatureTitle'), - card: { name: title, img: item.img, description: ability.description } - }) + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/ability-use.hbs', + { + title: game.i18n.localize('DAGGERHEART.Chat.FoundationCard.SubclassFeatureTitle'), + card: { name: title, img: item.img, description: ability.description } + } + ) }); cls.create(msg.toObject()); @@ -939,10 +968,13 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { const cls = getDocumentClass('ChatMessage'); const msg = new cls({ user: game.user.id, - content: await renderTemplate('systems/daggerheart/templates/chat/ability-use.hbs', { - title: game.i18n.localize('DAGGERHEART.Chat.FoundationCard.SubclassFeatureTitle'), - card: { name: item.name, img: item.img, description: item.system.description } - }) + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/ability-use.hbs', + { + title: game.i18n.localize('DAGGERHEART.Chat.FoundationCard.SubclassFeatureTitle'), + card: { name: item.name, img: item.img, description: item.system.description } + } + ) }); cls.create(msg.toObject()); diff --git a/module/applications/sheets/subclass.mjs b/module/applications/sheets/subclass.mjs deleted file mode 100644 index 40128ab0..00000000 --- a/module/applications/sheets/subclass.mjs +++ /dev/null @@ -1,204 +0,0 @@ -// import DhpApplicationMixin from '../daggerheart-sheet.mjs'; - -// export default class SubclassSheet extends DhpApplicationMixin(ItemSheet) { -// static documentType = "subclass"; - -// constructor(options){ -// super(options); -// } - -// static get defaultOptions() { -// return foundry.utils.mergeObject(super.defaultOptions, { -// classes: ["daggerheart", "sheet", "subclass"], -// width: 600, -// height: 720, -// tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "general" }], -// dragDrop: [ -// { dragSelector: null, dropSelector: '.foundation-tab' }, -// { dragSelector: null, dropSelector: '.specialization-tab' }, -// { dragSelector: null, dropSelector: '.mastery-tab' } -// ], -// }); -// } - -// getData() { -// const context = super.getData(); -// context.config = CONFIG.daggerheart; - -// return context; -// } - -// async _handleAction(action, event, button) { -// switch(action){ -// case "editAbility": -// this.editAbility(button); -// break; -// case "deleteFeatureAbility": -// this.deleteFeatureAbility(event); -// break; -// } -// } - -// async editAbility(button){ -// const feature = await fromUuid(button.dataset.ability); -// feature.sheet.render(true); -// } - -// async deleteFeatureAbility(event){ -// event.preventDefault(); -// event.stopPropagation(); - -// const feature = event.currentTarget.dataset.feature; -// const newAbilities = this.item.system[`${feature}Feature`].abilities.filter(x => x.uuid !== event.currentTarget.dataset.ability); -// const path = `system.${feature}Feature.abilities`; - -// await this.item.update({ [path]: newAbilities }); -// } - -// async _onDrop(event) { -// const data = TextEditor.getDragEventData(event); -// const item = await fromUuid(data.uuid); -// if(item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.subclass.id) { -// if(event.currentTarget.classList.contains('foundation-tab')){ -// await this.object.update({ "system.foundationFeature.abilities": [...this.item.system.foundationFeature.abilities, { img: item.img, name: item.name, uuid: item.uuid }] }); -// } -// else if(event.currentTarget.classList.contains('specialization-tab')){ -// await this.object.update({ "system.specializationFeature.abilities": [...this.item.system.specializationFeature.abilities, { img: item.img, name: item.name, uuid: item.uuid }] }); -// } -// else if(event.currentTarget.classList.contains('mastery-tab')){ -// await this.object.update({ "system.masteryFeature.abilities": [...this.item.system.masteryFeature.abilities, { img: item.img, name: item.name, uuid: item.uuid }] }); -// } -// } -// } -// } - -import DaggerheartSheet from './daggerheart-sheet.mjs'; -import DaggerheartFeature from '../../data/feature.mjs'; - -const { ItemSheetV2 } = foundry.applications.sheets; -const { TextEditor } = foundry.applications.ux; -const { duplicate, getProperty } = foundry.utils; -export default class SubclassSheet extends DaggerheartSheet(ItemSheetV2) { - static DEFAULT_OPTIONS = { - tag: 'form', - classes: ['daggerheart', 'sheet', 'subclass'], - position: { width: 600, height: 600 }, - window: { resizable: true }, - actions: { - editAbility: this.editAbility, - deleteFeatureAbility: this.deleteFeatureAbility - }, - form: { - handler: this.updateForm, - submitOnChange: true, - closeOnSubmit: false - }, - dragDrop: [ - { dragSelector: null, dropSelector: '.foundation-tab' }, - { dragSelector: null, dropSelector: '.specialization-tab' }, - { dragSelector: null, dropSelector: '.mastery-tab' } - ] - }; - - _getTabs() { - const tabs = { - general: { - active: true, - cssClass: '', - group: 'primary', - id: 'general', - icon: null, - label: game.i18n.localize('DAGGERHEART.Sheets.Subclass.Tabs.General') - }, - foundation: { - active: false, - cssClass: '', - group: 'primary', - id: 'foundation', - icon: null, - label: game.i18n.localize('DAGGERHEART.Sheets.Subclass.Tabs.Foundation') - }, - specialization: { - active: false, - cssClass: '', - group: 'primary', - id: 'specialization', - icon: null, - label: game.i18n.localize('DAGGERHEART.Sheets.Subclass.Tabs.Specialization') - }, - mastery: { - active: false, - cssClass: '', - group: 'primary', - id: 'mastery', - icon: null, - label: game.i18n.localize('DAGGERHEART.Sheets.Subclass.Tabs.Mastery') - } - }; - for (const v of Object.values(tabs)) { - v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active; - v.cssClass = v.active ? 'active' : ''; - } - - return tabs; - } - - static PARTS = { - form: { - id: 'feature', - template: 'systems/daggerheart/templates/sheets/subclass.hbs' - } - }; - - async _prepareContext(_options) { - const context = await super._prepareContext(_options); - context.document = this.document; - context.config = CONFIG.daggerheart; - context.tabs = this._getTabs(); - - return context; - } - - static async updateForm(event, _, formData) { - await this.document.update(formData.object); - this.render(); - } - - static async editAbility(_, button) { - const feature = await fromUuid(button.dataset.ability); - feature.sheet.render(true); - } - - static async deleteFeatureAbility(event, button) { - event.preventDefault(); - event.stopPropagation(); - - const feature = button.dataset.feature; - const newAbilities = this.document.system[`${feature}Feature`].abilities.filter( - x => x.uuid !== button.dataset.ability - ); - const path = `system.${feature}Feature.abilities`; - - await this.document.update({ [path]: newAbilities }); - } - - async _onDrop(event) { - event.preventDefault(); - const data = TextEditor.getDragEventData(event); - const item = await fromUuid(data.uuid); - if (!(item.type === 'feature' && item.system.type === SYSTEM.ITEM.featureTypes.subclass.id)) return; - - let featureField; - if (event.currentTarget.classList.contains('foundation-tab')) featureField = 'foundation'; - else if (event.currentTarget.classList.contains('specialization-tab')) featureField = 'specialization'; - else if (event.currentTarget.classList.contains('mastery-tab')) featureField = 'mastery'; - else return; - - const path = `system.${featureField}Feature.abilities`; - const abilities = duplicate(getProperty(this.document, path)) || []; - const featureData = { name: item.name, img: item.img, uuid: item.uuid }; - abilities.push(featureData); - - await this.document.update({ [path]: abilities }); - } -} diff --git a/module/data/pc.mjs b/module/data/pc.mjs index 62adf232..08763123 100644 --- a/module/data/pc.mjs +++ b/module/data/pc.mjs @@ -290,7 +290,7 @@ export default class DhpPC extends foundry.abstract.TypeDataModel { get refreshableFeatures() { return this.parent.items.reduce( (acc, x) => { - if (x.type === 'feature' && x.system.refreshData?.type) { + if (x.type === 'feature' && x.system.refreshData?.type === 'feature' && x.system.refreshData?.type) { acc[x.system.refreshData.type].push(x); } diff --git a/module/dialogs/selectDialog.mjs b/module/dialogs/selectDialog.mjs index e4792238..484979cc 100644 --- a/module/dialogs/selectDialog.mjs +++ b/module/dialogs/selectDialog.mjs @@ -5,9 +5,12 @@ export default class SelectDialog extends Dialog { this.data = { title: data.title, buttons: data.buttons, - content: renderTemplate('systems/daggerheart/templates/dialog/item-select.hbs', { - items: data.choices - }) + content: foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/dialog/item-select.hbs', + { + items: data.choices + } + ) }; this.actor = data.actor; diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index bef6da88..ff193d93 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -240,22 +240,26 @@ export default class DhpActor extends Actor { } const cls = getDocumentClass('ChatMessage'); + const systemData = { + title: game.i18n.format('DAGGERHEART.Chat.DamageRoll.Title', { damage: title }), + roll: rollString, + damage: { + total: rollResult.total, + type: damage.type + }, + dice: dice, + modifiers: modifiers, + targets: targets + }; const msg = new cls({ type: 'damageRoll', user: game.user.id, sound: CONFIG.sounds.dice, - system: { - title: game.i18n.format('DAGGERHEART.Chat.DamageRoll.Title', { damage: title }), - roll: rollString, - damage: { - total: rollResult.total, - type: damage.type - }, - dice: dice, - modifiers: modifiers, - targets: targets - }, - content: 'systems/daggerheart/templates/chat/damage-roll.hbs', + system: systemData, + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/damage-roll.hbs', + systemData + ), rolls: [roll] }); @@ -349,11 +353,14 @@ export default class DhpActor extends Actor { const cls = getDocumentClass('ChatMessage'); const msg = new cls({ user: game.user.id, - content: await renderTemplate('systems/daggerheart/templates/chat/damage-roll.hbs', { - roll: roll.formula, - total: roll.result, - type: action.damage.type - }) + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/damage-roll.hbs', + { + roll: roll.formula, + total: roll.result, + type: action.damage.type + } + ) }); cls.create(msg.toObject()); @@ -368,11 +375,14 @@ export default class DhpActor extends Actor { const cls = getDocumentClass('ChatMessage'); const msg = new cls({ user: game.user.id, - content: await renderTemplate('systems/daggerheart/templates/chat/healing-roll.hbs', { - roll: roll.formula, - total: roll.result, - type: action.healing.type - }) + content: await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/chat/healing-roll.hbs', + { + roll: roll.formula, + total: roll.result, + type: action.healing.type + } + ) }); cls.create(msg.toObject()); diff --git a/module/documents/item.mjs b/module/documents/item.mjs index cbf3ff2b..837b5564 100644 --- a/module/documents/item.mjs +++ b/module/documents/item.mjs @@ -38,25 +38,28 @@ export default class DhpItem extends Item { }, {}); // Render the document creation form - const html = await renderTemplate('systems/daggerheart/templates/sidebar/documentCreate.hbs', { - folders, - name: data.name || game.i18n.format('DOCUMENT.New', { type: label }), - folder: data.folder, - hasFolders: folders.length >= 1, - type: data.type || CONFIG[documentName]?.defaultType || typeObjects.armor, - types: { - Items: [typeObjects.armor, typeObjects.weapon, typeObjects.consumable, typeObjects.miscellaneous], - Character: [ - typeObjects.class, - typeObjects.subclass, - typeObjects.ancestry, - typeObjects.community, - typeObjects.feature, - typeObjects.domainCard - ] - }, - hasTypes: types.length > 1 - }); + const html = await foundry.applications.handlebars.renderTemplate( + 'systems/daggerheart/templates/sidebar/documentCreate.hbs', + { + folders, + name: data.name || game.i18n.format('DOCUMENT.New', { type: label }), + folder: data.folder, + hasFolders: folders.length >= 1, + type: data.type || CONFIG[documentName]?.defaultType || typeObjects.armor, + types: { + Items: [typeObjects.armor, typeObjects.weapon, typeObjects.consumable, typeObjects.miscellaneous], + Character: [ + typeObjects.class, + typeObjects.subclass, + typeObjects.ancestry, + typeObjects.community, + typeObjects.feature, + typeObjects.domainCard + ] + }, + hasTypes: types.length > 1 + } + ); // Render the confirmation dialog window return Dialog.prompt({ diff --git a/styles/components.less b/styles/components.less deleted file mode 100644 index 34292734..00000000 --- a/styles/components.less +++ /dev/null @@ -1,45 +0,0 @@ -.slider-container { - position: relative; - background: lightslategray; - - .slider-inner-container { - position: absolute; - top: 1px; - left: -60px; - background-color: inherit; - color: inherit; - border-radius: 30px; - cursor: pointer; - display: flex; - align-items: center; - height: 20px; - width: 40px; - padding: 0 4px; - border: @thinBorder solid black; - - &:hover { - filter: drop-shadow(0 0 3px red); - } - - input:checked { - opacity: 0; - width: 0; - height: 0; - - & + .slider-icon { - transform: translateX(17px); - transition: 1s; - } - } - - .slider-icon { - position: absolute; - left: 4px; - height: 15px; - width: 15px; - border-radius: 50%; - transition: 1s; - transform: translateX(0); - } - } -} diff --git a/styles/daggerheart.css b/styles/daggerheart.css index dea99a6f..e6ad610b 100755 --- a/styles/daggerheart.css +++ b/styles/daggerheart.css @@ -2268,9 +2268,6 @@ div.daggerheart.views.multiclass { .daggerheart.sheet.heritage .editor { height: 200px; } -.daggerheart.sheet.class .guide .guide-section { - gap: 8px; -} .daggerheart.sheet.class .guide .drop-section { width: 100%; } @@ -2290,18 +2287,12 @@ div.daggerheart.views.multiclass { min-width: 24px; } .daggerheart.sheet.class .guide .suggested-item { - padding: 2px 4px; border-radius: 6px; - border: 1px solid black; - background: #778899; display: flex; justify-content: space-between; align-items: center; width: 100%; } -.daggerheart.sheet.class .guide .suggested-item:not(:last-child) { - margin: 4px; -} .daggerheart.sheet.class .guide .suggested-item img { width: 30px; } @@ -2322,9 +2313,6 @@ div.daggerheart.views.multiclass { font-size: 14px; font-weight: bold; } -.daggerheart.sheet.class .guide .extra-section .extra-input { - margin-bottom: 4px; -} .daggerheart.sheet.class .guide-section-title-centered { font-weight: bold; font-size: 18px; @@ -2340,27 +2328,10 @@ div.daggerheart.views.multiclass { font-size: 14px; text-align: center; } -.daggerheart.sheet.class .tagify { - background: var(--color-light-1); - border: 1px solid var(--color-border); - height: 34px; - width: 100%; - border-radius: 3px; - margin-right: 1px; -} -.daggerheart.sheet.class .tagify tag div { +.daggerheart.sheet.class .domain-section { display: flex; - justify-content: space-between; align-items: center; - height: 22px; -} -.daggerheart.sheet.class .tagify tag div span { - font-weight: 400; -} -.daggerheart.sheet.class .tagify tag div img { - margin-left: 8px; - height: 20px; - width: 20px; + gap: 5px; } .daggerheart.sheet.adversary .adversary-header-container { position: relative; @@ -2733,46 +2704,6 @@ div.daggerheart.views.multiclass { background: inherit; border: 0; } -.slider-container { - position: relative; - background: lightslategray; -} -.slider-container .slider-inner-container { - position: absolute; - top: 1px; - left: -60px; - background-color: inherit; - color: inherit; - border-radius: 30px; - cursor: pointer; - display: flex; - align-items: center; - height: 20px; - width: 40px; - padding: 0 4px; - border: 1px solid black; -} -.slider-container .slider-inner-container:hover { - filter: drop-shadow(0 0 3px red); -} -.slider-container .slider-inner-container input:checked { - opacity: 0; - width: 0; - height: 0; -} -.slider-container .slider-inner-container input:checked + .slider-icon { - transform: translateX(17px); - transition: 1s; -} -.slider-container .slider-inner-container .slider-icon { - position: absolute; - left: 4px; - height: 15px; - width: 15px; - border-radius: 50%; - transition: 1s; - transform: translateX(0); -} .item-button.checked { background: green; } @@ -2937,6 +2868,44 @@ div.daggerheart.views.multiclass { scrollbar-width: thin; scrollbar-color: light-dark(#18162e, #f3c267) transparent; } +.application.sheet.daggerheart.dh-style.class .tab.settings .fieldsets-section { + display: grid; + gap: 10px; + grid-template-columns: 1fr 1.5fr 1.5fr; +} +.application.sheet.daggerheart.dh-style.class .tab.settings .list-items { + margin-bottom: 10px; + width: 100%; +} +.application.sheet.daggerheart.dh-style.class .tab.settings .list-items:last-child { + margin-bottom: 0px; +} +.application.sheet.daggerheart.dh-style.class .tab.settings .list-items .item-line { + display: grid; + align-items: center; + gap: 10px; + grid-template-columns: 1fr 3fr 1fr; +} +.application.sheet.daggerheart.dh-style.class .tab.settings .list-items .item-line h4 { + font-family: 'Montserrat', sans-serif; + font-weight: lighter; + color: light-dark(#222, #efe6d8); +} +.application.sheet.daggerheart.dh-style.class .tab.settings .list-items .item-line .image { + height: 40px; + width: 40px; + object-fit: cover; + border-radius: 6px; + border: none; +} +.application.sheet.daggerheart.dh-style.class .tab.settings .list-items .item-line .controls { + display: flex; + justify-content: center; + gap: 10px; +} +.application.sheet.daggerheart.dh-style.class .tab.settings .list-items .item-line .controls a { + text-shadow: none; +} @font-face { font-family: 'Cinzel'; font-style: normal; @@ -3149,6 +3118,7 @@ div.daggerheart.views.multiclass { align-items: start; gap: 10px; min-height: 64px; + width: 100%; } .application.sheet.dh-style fieldset.two-columns { display: grid; @@ -3238,6 +3208,48 @@ div.daggerheart.views.multiclass { .application.setting.dh-style footer button { flex: 1; } +.system-daggerheart .tagify { + background: light-dark(transparent, transparent); + border: 1px solid light-dark(#222, #efe6d8); + height: 34px; + border-radius: 3px; + margin-right: 1px; +} +.system-daggerheart .tagify tag div { + display: flex; + justify-content: space-between; + align-items: center; + height: 22px; +} +.system-daggerheart .tagify tag div span { + font-weight: 400; +} +.system-daggerheart .tagify tag div img { + margin-left: 8px; + height: 20px; + width: 20px; +} +.system-daggerheart .tagify__dropdown { + border: 1px solid light-dark(#222, #efe6d8) !important; +} +.system-daggerheart .tagify__dropdown .tagify__dropdown__wrapper { + background-image: url(../assets/parchments/dh-parchment-dark.png); + background-color: transparent; + border: 0; +} +.system-daggerheart .tagify__dropdown .tagify__dropdown__wrapper .tagify__dropdown__item--active { + background-color: light-dark(#222, #efe6d8); + color: var(--color-dark-3); +} +.system-daggerheart.theme-light .tagify__dropdown { + color: black; +} +.system-daggerheart.theme-light .tagify__dropdown .tagify__dropdown__wrapper { + background-image: url(../assets/parchments/dh-parchment-light.png); +} +.system-daggerheart.theme-light .tagify__dropdown .tagify__dropdown__item--active { + color: #efe6d8; +} .theme-light .application .component.dh-style.card.card-preview-container { background-image: url('../assets/parchments/dh-parchment-light.png'); } diff --git a/styles/daggerheart.less b/styles/daggerheart.less index 7fd91e23..6e1a793f 100755 --- a/styles/daggerheart.less +++ b/styles/daggerheart.less @@ -6,8 +6,7 @@ @import './chat.less'; @import './item.less'; @import './application.less'; -@import './sheets//sheets.less'; -@import './components.less'; +@import './sheets/sheets.less'; @import './dialog.less'; @import './levelup.less'; @import '../node_modules/@yaireo/tagify/dist/tagify.css'; @@ -15,6 +14,7 @@ // new styles imports @import './less/items/feature.less'; @import './less/items/domainCard.less'; +@import './less/items/class.less'; @import './less/utils/colors.less'; @import './less/utils/fonts.less'; @@ -96,14 +96,6 @@ cursor: pointer; } } - - // .window-content { - // background: crimson; - - // > form, >div { - // background: url(../ui/parchment.jpg) repeat; - // } - // } } #players { diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index 9001e65e..e82d60d3 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -96,6 +96,7 @@ align-items: start; gap: 10px; min-height: 64px; + width: 100%; } &.two-columns { @@ -212,3 +213,136 @@ } } } + +.system-daggerheart { + .tagify { + background: light-dark(transparent, transparent); + border: 1px solid light-dark(@dark, @beige); + height: 34px; + + border-radius: 3px; + margin-right: 1px; + + tag { + div { + display: flex; + justify-content: space-between; + align-items: center; + height: 22px; + + span { + font-weight: 400; + } + + img { + margin-left: 8px; + height: 20px; + width: 20px; + } + } + } + } + + .tagify__dropdown { + border: 1px solid light-dark(@dark, @beige) !important; + + .tagify__dropdown__wrapper { + background-image: url(../assets/parchments/dh-parchment-dark.png); + background-color: transparent; + border: 0; + + .tagify__dropdown__item--active { + background-color: light-dark(@dark, @beige); + color: var(--color-dark-3); + } + } + } + + &.theme-light { + .tagify__dropdown { + color: black; + + .tagify__dropdown__wrapper { + background-image: url(../assets/parchments/dh-parchment-light.png); + } + + .tagify__dropdown__item--active { + color: @beige; + } + } + } +} + +.theme-light { + .application { + .component.dh-style.card { + &.card-preview-container { + background-image: url('../assets/parchments/dh-parchment-light.png'); + + .preview-text-container { + background-image: url(../assets/parchments/dh-parchment-dark.png); + } + } + } + } +} + +.application { + .component.dh-style { + &.card-preview-container { + border-radius: 6px; + border: 2px solid var(--color-tabs-border); + display: flex; + flex-direction: column; + aspect-ratio: 0.75; + background-image: url('../assets/parchments/dh-parchment-dark.png'); + + &.empty { + cursor: pointer; + } + + .preview-image-container { + flex: 1; + border-radius: 4px 4px 0; + } + + .preview-text-container { + flex: 1; + border-radius: 0 0 4px 4px; + display: flex; + align-items: center; + justify-content: center; + font-size: 18px; + text-align: center; + color: var(--color-text-selection-bg); + background-image: url(../assets/parchments/dh-parchment-light.png); + } + + .preview-empty-container { + display: flex; + align-items: center; + justify-content: center; + flex: 1; + + .preview-empty-inner-container { + position: relative; + width: 100%; + display: flex; + justify-content: center; + + .preview-add-icon { + font-size: 48px; + } + + .preview-empty-subtext { + position: absolute; + bottom: -48px; + font-size: 18px; + font-variant: small-caps; + text-align: center; + } + } + } + } + } +} diff --git a/styles/less/items/class.css b/styles/less/items/class.css new file mode 100644 index 00000000..19f17576 --- /dev/null +++ b/styles/less/items/class.css @@ -0,0 +1,132 @@ +@font-face { + font-family: 'Cinzel'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/cinzel/v23/8vIU7ww63mVu7gtR-kwKxNvkNOjw-tbnTYo.ttf) format('truetype'); +} +@font-face { + font-family: 'Cinzel'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/cinzel/v23/8vIU7ww63mVu7gtR-kwKxNvkNOjw-jHgTYo.ttf) format('truetype'); +} +@font-face { + font-family: 'Cinzel Decorative'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/cinzeldecorative/v17/daaHSScvJGqLYhG8nNt8KPPswUAPniZoaelD.ttf) + format('truetype'); +} +@font-face { + font-family: 'Montserrat'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/montserrat/v30/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Ew-.ttf) format('truetype'); +} +@font-face { + font-family: 'Montserrat'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/montserrat/v30/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCu170w-.ttf) format('truetype'); +} +.application.sheet.daggerheart.dh-style h1 { + font-family: 'Cinzel Decorative', serif; + margin: 0; + border: none; + font-weight: normal; +} +.application.sheet.daggerheart.dh-style h2, +.application.sheet.daggerheart.dh-style h3 { + font-family: 'Cinzel', serif; + margin: 0; + border: none; + font-weight: normal; +} +.application.sheet.daggerheart.dh-style h4 { + font-family: 'Montserrat', sans-serif; + font-size: 14px; + border: none; + font-weight: 700; + margin: 0; + text-shadow: none; + color: #f3c267; + font-weight: normal; +} +.application.sheet.daggerheart.dh-style h5 { + font-size: 14px; + color: #f3c267; + margin: 0; + font-weight: normal; +} +.application.sheet.daggerheart.dh-style p, +.application.sheet.daggerheart.dh-style span { + font-family: 'Montserrat', sans-serif; +} +.application.sheet.daggerheart.dh-style small { + font-family: 'Montserrat', sans-serif; + opacity: 0.8; +} +.application.sheet.daggerheart.dh-style.class .tagify { + background: light-dark(transparent, transparent); + border: 1px solid light-dark(#222, #efe6d8); + height: 34px; + border-radius: 3px; + margin-right: 1px; +} +.application.sheet.daggerheart.dh-style.class .tagify tag div { + display: flex; + justify-content: space-between; + align-items: center; + height: 22px; +} +.application.sheet.daggerheart.dh-style.class .tagify tag div span { + font-weight: 400; +} +.application.sheet.daggerheart.dh-style.class .tagify tag div img { + margin-left: 8px; + height: 20px; + width: 20px; +} +.application.sheet.daggerheart.dh-style.class .tab.settings .fieldsets-section { + display: grid; + gap: 10px; + grid-template-columns: 1fr 1.5fr 1.5fr; +} +.application.sheet.daggerheart.dh-style.class .tab.settings .list-items { + margin-bottom: 10px; + width: 100%; +} +.application.sheet.daggerheart.dh-style.class .tab.settings .list-items:last-child { + margin-bottom: 0px; +} +.application.sheet.daggerheart.dh-style.class .tab.settings .list-items .item-line { + display: grid; + align-items: center; + gap: 10px; + grid-template-columns: 1fr 3fr 1fr; +} +.application.sheet.daggerheart.dh-style.class .tab.settings .list-items .item-line h4 { + font-family: 'Montserrat', sans-serif; + font-weight: lighter; + color: light-dark(#222, #efe6d8); +} +.application.sheet.daggerheart.dh-style.class .tab.settings .list-items .item-line .image { + height: 40px; + width: 40px; + object-fit: cover; + border-radius: 6px; + border: none; +} +.application.sheet.daggerheart.dh-style.class .tab.settings .list-items .item-line .controls { + display: flex; + justify-content: center; + gap: 10px; +} +.application.sheet.daggerheart.dh-style.class .tab.settings .list-items .item-line .controls a { + text-shadow: none; +} diff --git a/styles/less/items/class.less b/styles/less/items/class.less new file mode 100644 index 00000000..61974778 --- /dev/null +++ b/styles/less/items/class.less @@ -0,0 +1,46 @@ +@import '../utils/colors.less'; +@import '../utils/fonts.less'; + +.application.sheet.daggerheart.dh-style.class { + .tab.settings { + .fieldsets-section { + display: grid; + gap: 10px; + grid-template-columns: 1fr 1.5fr 1.5fr; + } + + .list-items { + margin-bottom: 10px; + width: 100%; + &:last-child { + margin-bottom: 0px; + } + .item-line { + display: grid; + align-items: center; + gap: 10px; + grid-template-columns: 1fr 3fr 1fr; + h4 { + font-family: @font-body; + font-weight: lighter; + color: light-dark(@dark, @beige); + } + .image { + height: 40px; + width: 40px; + object-fit: cover; + border-radius: 6px; + border: none; + } + .controls { + display: flex; + justify-content: center; + gap: 10px; + a { + text-shadow: none; + } + } + } + } + } +} diff --git a/styles/sheets/class.less b/styles/sheets/class.less index 07008699..09dafcff 100644 --- a/styles/sheets/class.less +++ b/styles/sheets/class.less @@ -1,119 +1,65 @@ -.daggerheart.sheet.class { - .guide { - .guide-section { - gap: @fullMargin; - } - - .drop-section { - width: 100%; - - legend { - margin-left: auto; - margin-right: auto; - font-size: 12px; - } - - .drop-section-body { - min-height: 40px; - display: flex; - flex-direction: column; - align-items: center; - } - } - - .trait-input { - text-align: center; - min-width: 24px; - } - - .suggested-item { - padding: @smallPadding @fullPadding; - border-radius: 6px; - border: @thinBorder solid black; - background: @primaryAccent; - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; - - &:not(:last-child) { - margin: @halfMargin; - } - - img { - width: 30px; - } - - div { - text-align: center; - } - - i { - border-radius: 50%; - margin-right: 4px; - font-size: 11px; - } - } - - .extra-section { - display: flex; - flex-direction: column; - align-items: center; - - .extra-title { - font-size: 14px; - font-weight: bold; - } - - .extra-input { - margin-bottom: @halfMargin; - } - } - } - - .guide-section-title-centered { - font-weight: bold; - font-size: 18px; - } - - .inventory-section { - width: 100%; - border: 2px solid black; - border-style: dotted; - min-height: 80px; - - .inventory-title { - font-weight: bold; - font-size: 14px; - text-align: center; - } - } - - .tagify { - background: var(--color-light-1); - border: 1px solid var(--color-border); - height: 34px; - width: 100%; - border-radius: 3px; - margin-right: 1px; - - tag { - div { - display: flex; - justify-content: space-between; - align-items: center; - height: 22px; - - span { - font-weight: 400; - } - - img { - margin-left: 8px; - height: 20px; - width: 20px; - } - } - } - } +.daggerheart.sheet.class .guide .drop-section { + width: 100%; +} +.daggerheart.sheet.class .guide .drop-section legend { + margin-left: auto; + margin-right: auto; + font-size: 12px; +} +.daggerheart.sheet.class .guide .drop-section .drop-section-body { + min-height: 40px; + display: flex; + flex-direction: column; + align-items: center; +} +.daggerheart.sheet.class .guide .trait-input { + text-align: center; + min-width: 24px; +} +.daggerheart.sheet.class .guide .suggested-item { + border-radius: 6px; + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; +} +.daggerheart.sheet.class .guide .suggested-item img { + width: 30px; +} +.daggerheart.sheet.class .guide .suggested-item div { + text-align: center; +} +.daggerheart.sheet.class .guide .suggested-item i { + border-radius: 50%; + margin-right: 4px; + font-size: 11px; +} +.daggerheart.sheet.class .guide .extra-section { + display: flex; + flex-direction: column; + align-items: center; +} +.daggerheart.sheet.class .guide .extra-section .extra-title { + font-size: 14px; + font-weight: bold; +} +.daggerheart.sheet.class .guide-section-title-centered { + font-weight: bold; + font-size: 18px; +} +.daggerheart.sheet.class .inventory-section { + width: 100%; + border: 2px solid black; + border-style: dotted; + min-height: 80px; +} +.daggerheart.sheet.class .inventory-section .inventory-title { + font-weight: bold; + font-size: 14px; + text-align: center; +} +.daggerheart.sheet.class .domain-section { + display: flex; + align-items: center; + gap: 5px; } diff --git a/system.json b/system.json index 2450788a..dd875adb 100644 --- a/system.json +++ b/system.json @@ -435,6 +435,35 @@ "distance": 5, "units": "feet" }, + "documentTypes": { + "Actor": { + "pc": {}, + "npc": {}, + "adversary": {}, + "environment": {} + }, + "Item": { + "ancestry": {}, + "community": {}, + "class": {}, + "subclass": {}, + "feature": {}, + "domainCard": {}, + "miscellaneous": {}, + "consumable": {}, + "weapon": {}, + "armor": {} + }, + "Combat": { + "combat": {} + }, + "ChatMessage": { + "dualityRoll": {}, + "adversaryRoll": {}, + "damageRoll": {}, + "abilityUse": {} + } + }, "primaryTokenAttribute": "resources.health", "secondaryTokenAttribute": "resources.stress", "url": "https://your/hosted/system/repo/", diff --git a/template.json b/template.json deleted file mode 100644 index 7e6c3c67..00000000 --- a/template.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "Actor": { - "types": ["pc", "npc", "adversary", "environment"], - "pc": {}, - "npc": {}, - "adversary": {}, - "environment": {} - }, - "Item": { - "types": [ - "ancestry", - "community", - "class", - "subclass", - "feature", - "domainCard", - "miscellaneous", - "consumable", - "weapon", - "armor", - "test" - ], - "ancestry": {}, - "community": {}, - "class": {}, - "subclass": {}, - "feature": {}, - "domainCard": {}, - "miscellaneous": {}, - "consumable": {}, - "weapon": {}, - "armor": {}, - "test": {} - }, - "Combat": { - "types": ["combat"], - "combat": {} - }, - "ChatMessage": { - "types": ["dualityRoll", "adversaryRoll", "damageRoll", "abilityUse"], - "dualityRoll": {}, - "adversaryRoll": {}, - "damageRoll": {}, - "abilityUse": {} - } -} diff --git a/templates/chat/attack-roll.hbs b/templates/chat/attack-roll.hbs index ccc93087..4deaf45b 100644 --- a/templates/chat/attack-roll.hbs +++ b/templates/chat/attack-roll.hbs @@ -164,7 +164,7 @@ {{/if}}
- +
diff --git a/templates/chat/damage-roll.hbs b/templates/chat/damage-roll.hbs index 9097331d..7cee09ed 100644 --- a/templates/chat/damage-roll.hbs +++ b/templates/chat/damage-roll.hbs @@ -23,7 +23,6 @@ -
{{this.damage.total}}
diff --git a/templates/components/slider.hbs b/templates/components/slider.hbs deleted file mode 100644 index 7cbf08d0..00000000 --- a/templates/components/slider.hbs +++ /dev/null @@ -1,5 +0,0 @@ -
-
- -
-
\ No newline at end of file diff --git a/templates/sheets/class.hbs b/templates/sheets/class.hbs deleted file mode 100644 index 935b1019..00000000 --- a/templates/sheets/class.hbs +++ /dev/null @@ -1,289 +0,0 @@ -
-
- -
-
-
-
- -
- -
-
- {{formField systemFields.evasion value=source.system.evasion label=(localize "DAGGERHEART.Sheets.Class.Evasion")}} - {{!--
- -
- -
-
--}} -
-

{{localize "DAGGERHEART.Sheets.Class.ClassFeatures"}}

-
- {{#each source.system.features as |feature index|}} -
-
- -
{{feature.name}}
-
-
- - -
-
- {{/each}} -
-
-
-

{{localize "DAGGERHEART.Sheets.Class.Subclasses"}}

-
- {{#each source.system.subclasses as |subclass index|}} -
-
- -
{{subclass.name}}
-
-
- - -
-
- {{/each}} -
-
-
-
-
-
-
-
{{localize "DAGGERHEART.Sheets.Class.Guide.Suggestions.Title"}}
-
- - {{localize "DAGGERHEART.Sheets.Class.Guide.Suggestions.Traits.Title"}} - - -
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
- - {{localize "DAGGERHEART.Sheets.Class.Guide.SuggestedPrimaryWeaponTitle"}} - - -
- {{#if source.system.characterGuide.suggestedPrimaryWeapon}} -
- -
{{source.system.characterGuide.suggestedPrimaryWeapon.name}}
- -
- {{/if}} -
-
-
- - {{localize "DAGGERHEART.Sheets.Class.Guide.SuggestedSecondaryWeaponTitle"}} - - -
- {{#if source.system.characterGuide.suggestedSecondaryWeapon}} -
- -
{{source.system.characterGuide.suggestedSecondaryWeapon.name}}
- -
- {{/if}} -
-
-
- - {{localize "DAGGERHEART.Sheets.Class.Guide.SuggestedArmorTitle"}} - - -
- {{#if source.system.characterGuide.suggestedArmor}} -
- -
{{source.system.characterGuide.suggestedArmor.name}}
- -
- {{/if}} -
-
-
-
-
{{localize "DAGGERHEART.Sheets.Class.Guide.Inventory.Title"}}
-
- - {{localize "DAGGERHEART.Sheets.Class.Guide.Inventory.Take"}} - - -
- {{#each source.system.inventory.take}} -
- -
{{this.name}}
- -
- {{/each}} -
-
-
- - {{localize "DAGGERHEART.Sheets.Class.Guide.Inventory.ThenChoose"}} - - -
- {{#each source.system.inventory.choiceA}} -
- -
{{this.name}}
- -
- {{/each}} -
-
-
- - {{localize "DAGGERHEART.Sheets.Class.Guide.Inventory.AndEither"}} - - -
- {{#each source.system.inventory.choiceB}} -
- -
{{this.name}}
- -
- {{/each}} -
-
-
-
-
{{localize "DAGGERHEART.Sheets.Class.Guide.Description.Title"}}
-
-
{{localize "DAGGERHEART.Sheets.Class.Guide.Description.Explanation"}}
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
- - {{localize "DAGGERHEART.Sheets.Class.Guide.Extra.Title"}} - - -
-
{{localize "DAGGERHEART.Sheets.Class.Guide.Extra.Subtitle"}}
- - -
-
-
-
-
-
- {{localize "DAGGERHEART.Sheets.Class.Guide.BackgroundQuestions.Title"}} - -
- {{#times 3}} -
{{localize "DAGGERHEART.Sheets.Class.Guide.BackgroundQuestions.Question"}} {{add this 1}}
- - {{/times}} -
-
- -
- - {{localize "DAGGERHEART.Sheets.Class.Guide.Connections.Title"}} - - -
- {{#times 3}} -
{{localize "DAGGERHEART.Sheets.Class.Guide.Connections.Question"}} {{add this 1}}
- - {{/times}} -
-
-
-
-
-
-
\ No newline at end of file diff --git a/templates/sheets/items/class/features.hbs b/templates/sheets/items/class/features.hbs new file mode 100644 index 00000000..dfa386d1 --- /dev/null +++ b/templates/sheets/items/class/features.hbs @@ -0,0 +1,49 @@ +
+ +
+ {{localize "DAGGERHEART.Sheets.Feature.Tabs.Features"}} +
+ {{#each source.system.features as |feature index|}} + {{> 'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs' feature=feature}} + {{/each}} +
+
+ +
+ {{localize "TYPES.Item.subclass"}} +
+ {{#each source.system.subclasses as |subclass index|}} +
  • +
    + +

    + {{subclass.name}} +

    + +
    +
  • + {{/each}} +
    +
    +
    \ No newline at end of file diff --git a/templates/sheets/items/class/header.hbs b/templates/sheets/items/class/header.hbs new file mode 100644 index 00000000..6d601987 --- /dev/null +++ b/templates/sheets/items/class/header.hbs @@ -0,0 +1,13 @@ +
    + +
    +

    +
    +

    {{localize 'TYPES.Item.class'}}

    +

    + {{localize "DAGGERHEART.Sheets.Class.Domains"}} + +

    +
    +
    +
    \ No newline at end of file diff --git a/templates/sheets/items/class/settings.hbs b/templates/sheets/items/class/settings.hbs new file mode 100644 index 00000000..3ae98111 --- /dev/null +++ b/templates/sheets/items/class/settings.hbs @@ -0,0 +1,132 @@ +
    + +
    + {{localize tabs.settings.label}} + {{localize "DAGGERHEART.Sheets.Class.Evasion"}} + {{formField systemFields.evasion value=source.system.evasion}} +
    + +
    +
    + {{localize "DAGGERHEART.Sheets.Class.Guide.Suggestions.Traits.Title"}} + + {{localize "DAGGERHEART.Abilities.agility.name"}} + + + {{localize "DAGGERHEART.Abilities.strength.name"}} + + + {{localize "DAGGERHEART.Abilities.finesse.name"}} + + + {{localize "DAGGERHEART.Abilities.instinct.name"}} + + + {{localize "DAGGERHEART.Abilities.presence.name"}} + + + {{localize "DAGGERHEART.Abilities.knowledge.name"}} + +
    + +
    + {{localize "DAGGERHEART.Sheets.Class.Guide.Suggestions.Title"}} +
    + {{localize "DAGGERHEART.Sheets.Class.Guide.SuggestedPrimaryWeaponTitle"}} +
    + {{#if source.system.characterGuide.suggestedPrimaryWeapon}} +
    + + {{source.system.characterGuide.suggestedPrimaryWeapon.name}} +
    + +
    +
    + {{/if}} +
    +
    + +
    + {{localize "DAGGERHEART.Sheets.Class.Guide.SuggestedSecondaryWeaponTitle"}} +
    + {{#if source.system.characterGuide.suggestedSecondaryWeapon}} +
    + + {{source.system.characterGuide.suggestedSecondaryWeapon.name}} +
    + +
    +
    + {{/if}} +
    +
    + +
    + {{localize "DAGGERHEART.Sheets.Class.Guide.SuggestedArmorTitle"}} +
    + {{#if source.system.characterGuide.suggestedArmor}} +
    + + {{source.system.characterGuide.suggestedArmor.name}} +
    + +
    +
    + {{/if}} +
    +
    +
    + +
    + {{localize "DAGGERHEART.Sheets.Class.Guide.Inventory.Title"}} +
    + {{localize "DAGGERHEART.Sheets.Class.Guide.Inventory.Take"}} +
    + {{#each source.system.inventory.take}} +
    + + {{this.name}} +
    + +
    +
    + {{/each}} +
    +
    + +
    + {{localize "DAGGERHEART.Sheets.Class.Guide.Inventory.ThenChoose"}} +
    + {{#each source.system.inventory.choiceA}} +
    + + {{this.name}} +
    + +
    +
    + {{/each}} +
    +
    + +
    + {{localize "DAGGERHEART.Sheets.Class.Guide.Inventory.AndEither"}} +
    + {{#each source.system.inventory.choiceB}} +
    + + {{this.name}} +
    + +
    +
    + {{/each}} +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/templates/sheets/items/subclass/features.hbs b/templates/sheets/items/subclass/features.hbs new file mode 100644 index 00000000..eb2010c4 --- /dev/null +++ b/templates/sheets/items/subclass/features.hbs @@ -0,0 +1,26 @@ +
    +
    + {{localize "DAGGERHEART.Sheets.Subclass.Tabs.Foundation"}} + {{#each source.system.foundationFeature.abilities as |feature key|}} + {{> 'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs' feature=feature}} + {{/each}} +
    + +
    + {{localize "DAGGERHEART.Sheets.Subclass.Tabs.Specialization"}} + {{#each source.system.specializationFeature.abilities as |feature key|}} + {{> 'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs' feature=feature}} + {{/each}} +
    + +
    + {{localize "DAGGERHEART.Sheets.Subclass.Tabs.Mastery"}} + {{#each source.system.masteryFeature.abilities as |feature key|}} + {{> 'systems/daggerheart/templates/sheets/global/partials/feature-section-item.hbs' feature=feature}} + {{/each}} +
    +
    \ No newline at end of file diff --git a/templates/sheets/items/subclass/header.hbs b/templates/sheets/items/subclass/header.hbs new file mode 100644 index 00000000..4e6d10e9 --- /dev/null +++ b/templates/sheets/items/subclass/header.hbs @@ -0,0 +1,10 @@ +
    + +
    +

    +
    +

    {{localize 'TYPES.Item.subclass'}}

    +

    {{localize (concat 'DAGGERHEART.Abilities.' source.system.spellcastingTrait '.name')}}

    +
    +
    +
    \ No newline at end of file diff --git a/templates/sheets/items/subclass/settings.hbs b/templates/sheets/items/subclass/settings.hbs new file mode 100644 index 00000000..2d8c3381 --- /dev/null +++ b/templates/sheets/items/subclass/settings.hbs @@ -0,0 +1,12 @@ +
    + +
    + {{localize tabs.settings.label}} + {{localize "DAGGERHEART.Sheets.Subclass.SpellcastingTrait"}} + {{formField systemFields.spellcastingTrait value=source.system.spellcastingTrait localize=true}} +
    +
    \ No newline at end of file diff --git a/templates/sheets/subclass.hbs b/templates/sheets/subclass.hbs deleted file mode 100644 index 6768a719..00000000 --- a/templates/sheets/subclass.hbs +++ /dev/null @@ -1,45 +0,0 @@ -
    -
    -
    - -
    - {{formInput fields.name value=source.name rootId=partId}} -
    -
    - -
    -
    -
    - {{formField systemFields.spellcastingTrait value=source.system.spellcastingTrait label=(localize "DAGGERHEART.Sheets.Subclass.SpellcastingTrait") localize=true}} - {{!--
    - -
    - -
    -
    --}} -
    - - {{formInput systemFields.description value=source.system.description enriched=source.system.description localize=true toggled=true}} - {{!-- {{editor item.system.description target="system.description" button=true}} --}} -
    -
    -
    - {{> "systems/daggerheart/templates/sheets/parts/subclassFeature.hbs" field=systemFields.foundationFeature.fields feature=source.system.foundationFeature featureType="foundation" }} -
    -
    - {{> "systems/daggerheart/templates/sheets/parts/subclassFeature.hbs" field=systemFields.specializationFeature.fields feature=source.system.specializationFeature featureType="specialization" }} -
    -
    - {{> "systems/daggerheart/templates/sheets/parts/subclassFeature.hbs" field=systemFields.masteryFeature.fields feature=source.system.masteryFeature featureType="mastery" }} -
    -
    -
    \ No newline at end of file