diff --git a/module/applications/dialogs/d20RollDialog.mjs b/module/applications/dialogs/d20RollDialog.mjs index 4a4b1556..8e79ba58 100644 --- a/module/applications/dialogs/d20RollDialog.mjs +++ b/module/applications/dialogs/d20RollDialog.mjs @@ -165,9 +165,10 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio } if (rest.hasOwnProperty('trait')) { this.config.roll.trait = rest.trait; - this.config.title = game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { - ability: game.i18n.localize(abilities[this.config.roll.trait]?.label) - }); + if (!this.config.source.item) + this.config.title = game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { + ability: game.i18n.localize(abilities[this.config.roll.trait]?.label) + }); } this.config.extraFormula = rest.extraFormula; this.render(); diff --git a/module/data/action/baseAction.mjs b/module/data/action/baseAction.mjs index e843027b..f6ffe75f 100644 --- a/module/data/action/baseAction.mjs +++ b/module/data/action/baseAction.mjs @@ -229,7 +229,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel if (Hooks.call(`${CONFIG.DH.id}.postUseAction`, this, config) === false) return; - if (this.chatDisplay) await this.toChat(); + if (this.chatDisplay && !config.actionChatMessageHandled) await this.toChat(); return config; } @@ -240,9 +240,13 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel * @returns {object} */ prepareBaseConfig(event) { + const isActor = this.item instanceof CONFIG.Actor.documentClass; + const actionTitle = game.i18n.localize(this.name); + const itemTitle = isActor || this.item.name === actionTitle ? '' : `${this.item.name} - `; + const config = { event, - title: `${this.item instanceof CONFIG.Actor.documentClass ? '' : `${this.item.name}: `}${game.i18n.localize(this.name)}`, + title: `${itemTitle}${actionTitle}`, source: { item: this.item._id, originItem: this.originItem, diff --git a/module/data/chat-message/actorRoll.mjs b/module/data/chat-message/actorRoll.mjs index 61262529..1ea7ff93 100644 --- a/module/data/chat-message/actorRoll.mjs +++ b/module/data/chat-message/actorRoll.mjs @@ -31,6 +31,7 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { static defineSchema() { return { title: new fields.StringField(), + actionDescription: new fields.HTMLField(), roll: new fields.ObjectField(), targets: targetsField(), hasRoll: new fields.BooleanField({ initial: false }), diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index ef91c64e..56eb51e5 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -68,6 +68,8 @@ export default class DamageField extends fields.SchemaField { const damageResult = await CONFIG.Dice.daggerheart.DamageRoll.build(damageConfig); if (!damageResult) return false; + if (damageResult.actionChatMessageHandled) config.actionChatMessageHandled = true; + config.damage = damageResult.damage; config.message ??= damageConfig.message; } diff --git a/module/data/settings/Appearance.mjs b/module/data/settings/Appearance.mjs index d7a638d7..cd98d6f9 100644 --- a/module/data/settings/Appearance.mjs +++ b/module/data/settings/Appearance.mjs @@ -37,7 +37,7 @@ export default class DhAppearance extends foundry.abstract.DataModel { extendEnvironmentDescriptions: new BooleanField(), extendItemDescriptions: new BooleanField(), expandRollMessage: new SchemaField({ - desc: new BooleanField(), + desc: new BooleanField({ initial: true }), roll: new BooleanField(), damage: new BooleanField(), target: new BooleanField() diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs index 1977c7ea..d8e5f6dd 100644 --- a/module/dice/dhRoll.mjs +++ b/module/dice/dhRoll.mjs @@ -96,6 +96,19 @@ export default class DHRoll extends Roll { } static async toMessage(roll, config) { + const item = config.data.parent?.items?.get?.(config.source.item) ?? null; + const action = item ? item.system.actions.get(config.source.action) : null; + let actionDescription = null; + if (action?.chatDisplay) { + actionDescription = action + ? await foundry.applications.ux.TextEditor.implementation.enrichHTML(action.description, { + relativeTo: config.data, + rollData: config.data.getRollData?.() ?? {} + }) + : null; + config.actionChatMessageHandled = true; + } + const cls = getDocumentClass('ChatMessage'), msgData = { type: this.messageType, @@ -103,7 +116,7 @@ export default class DHRoll extends Roll { title: roll.title, speaker: cls.getSpeaker({ actor: roll.data?.parent }), sound: config.mute ? null : CONFIG.sounds.dice, - system: config, + system: { ...config, actionDescription }, rolls: [roll] }; diff --git a/module/documents/chatMessage.mjs b/module/documents/chatMessage.mjs index 1d2c6c41..668ad06b 100644 --- a/module/documents/chatMessage.mjs +++ b/module/documents/chatMessage.mjs @@ -110,6 +110,8 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { } else if (s.classList.contains('damage-section')) s.classList.toggle('expanded', autoExpandRoll.damage); else if (s.classList.contains('target-section')) s.classList.toggle('expanded', autoExpandRoll.target); + else if (s.classList.contains('description-section')) + s.classList.toggle('expanded', autoExpandRoll.desc); }); if (itemDesc && autoExpandRoll.desc) itemDesc.setAttribute('open', ''); } diff --git a/module/systemRegistration/handlebars.mjs b/module/systemRegistration/handlebars.mjs index 97769181..ad8c741a 100644 --- a/module/systemRegistration/handlebars.mjs +++ b/module/systemRegistration/handlebars.mjs @@ -39,6 +39,7 @@ export const preloadHandlebarsTemplates = async function () { 'systems/daggerheart/templates/dialogs/downtime/activities.hbs', 'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs', 'systems/daggerheart/templates/ui/chat/parts/roll-part.hbs', + 'systems/daggerheart/templates/ui/chat/parts/description-part.hbs', 'systems/daggerheart/templates/ui/chat/parts/damage-part.hbs', 'systems/daggerheart/templates/ui/chat/parts/target-part.hbs', 'systems/daggerheart/templates/ui/chat/parts/button-part.hbs', diff --git a/styles/less/ui/chat/action.less b/styles/less/ui/chat/action.less index a3d2f3cc..6eeb7a52 100644 --- a/styles/less/ui/chat/action.less +++ b/styles/less/ui/chat/action.less @@ -38,124 +38,6 @@ flex-direction: column; align-items: center; - details[open] { - .fa-chevron-down { - transform: rotate(180deg); - transition: all 0.3s ease; - } - } - - .action-move { - width: 100%; - - .fa-chevron-down { - transition: all 0.3s ease; - margin-left: auto; - } - - .action-section { - display: flex; - flex-direction: row; - align-items: center; - margin: 8px 8px 0; - padding-bottom: 5px; - width: -webkit-fill-available; - gap: 5px; - border-bottom: 1px solid @golden; - - &:hover { - background: @golden-10; - cursor: pointer; - transition: all 0.3s ease; - } - - .action-img { - width: 40px; - height: 40px; - border-radius: 3px; - object-fit: cover; - } - - .action-header { - display: flex; - flex-direction: column; - gap: 5px; - color: @beige; - - .title { - font-size: var(--font-size-20); - color: @golden; - font-weight: 700; - } - - .label { - font-size: var(--font-size-12); - color: @beige; - margin: 0; - } - } - } - } - - .description { - padding: 8px; - - .summons-header { - font-size: var(--font-size-14); - text-align: center; - display: flex; - align-items: center; - justify-content: center; - - span { - width: 100%; - } - - &:before, - &:after { - content: ' '; - height: 1px; - width: 100%; - } - - &:before { - background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, light-dark(@dark-blue, @golden) 100%); - } - - &:after { - background: linear-gradient(90deg, light-dark(@dark-blue, @golden) 0%, rgba(0, 0, 0, 0) 100%); - } - } - - .summons-container { - display: flex; - flex-direction: column; - gap: 4px; - - .summon-container { - display: flex; - align-items: center; - justify-content: space-between; - - .summon-label-container { - flex: 1; - display: flex; - align-items: center; - gap: 4px; - - img { - height: 32px; - } - - label { - display: flex; - flex-wrap: wrap; - } - } - } - } - } - .ability-card-footer { display: flex; flex-wrap: wrap; diff --git a/styles/less/ui/chat/chat.less b/styles/less/ui/chat/chat.less index 494af5f1..8728fbda 100644 --- a/styles/less/ui/chat/chat.less +++ b/styles/less/ui/chat/chat.less @@ -228,6 +228,15 @@ font-size: var(--font-size-12); padding: 0 20px; + .roll-part-title { + text-align: center; + font-family: @font-subtitle; + font-size: var(--font-size-18); + font-weight: bold; + color: var(--text-color); + margin-bottom: -2px; + } + > .roll-part-header { font-size: var(--font-size-14); } @@ -286,6 +295,7 @@ > :first-child:not(.target-selector) { margin-top: 5px; + text-align: center; } > :last-child { @@ -573,6 +583,30 @@ } } + .chat-roll .description-section { + .roll-part-content { + .dice-tooltip { + .wrapper { + i { + margin: 0; + + :first-child { + margin-top: 0; + } + + :last-child { + margin-bottom: 0; + } + } + + > :first-child:not(.target-selector) { + margin: 0; + } + } + } + } + } + .roll-buttons { display: flex; gap: 5px; @@ -590,5 +624,124 @@ .dice-roll .dice-tooltip fieldset { margin-bottom: 5px; } + + details[open] { + .fa-chevron-down { + transform: rotate(180deg); + transition: all 0.3s ease; + } + } + + .action-move { + width: 100%; + + .fa-chevron-down { + transition: all 0.3s ease; + margin-left: auto; + } + + .action-section { + display: flex; + flex-direction: row; + align-items: center; + margin: 8px 8px 0; + padding-bottom: 5px; + width: -webkit-fill-available; + gap: 5px; + border-bottom: 1px solid @golden; + + &:hover { + background: @golden-10; + cursor: pointer; + transition: all 0.3s ease; + } + + .action-img { + width: 40px; + height: 40px; + border-radius: 3px; + object-fit: cover; + } + + .action-header { + display: flex; + flex-direction: column; + gap: 5px; + color: @beige; + + .title { + font-size: var(--font-size-20); + color: @golden; + font-weight: 700; + margin: 0; + } + + .label { + font-size: var(--font-size-12); + color: @beige; + margin: 0; + } + } + } + } + + .description { + padding: 8px; + + .summons-header { + font-size: var(--font-size-14); + text-align: center; + display: flex; + align-items: center; + justify-content: center; + + span { + width: 100%; + } + + &:before, + &:after { + content: ' '; + height: 1px; + width: 100%; + } + + &:before { + background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, light-dark(@dark-blue, @golden) 100%); + } + + &:after { + background: linear-gradient(90deg, light-dark(@dark-blue, @golden) 0%, rgba(0, 0, 0, 0) 100%); + } + } + + .summons-container { + display: flex; + flex-direction: column; + gap: 4px; + + .summon-container { + display: flex; + align-items: center; + justify-content: space-between; + + .summon-label-container { + flex: 1; + display: flex; + align-items: center; + gap: 4px; + + img { + height: 32px; + } + + label { + display: flex; + flex-wrap: wrap; + } + } + } + } + } } } diff --git a/templates/ui/chat/parts/description-part.hbs b/templates/ui/chat/parts/description-part.hbs new file mode 100644 index 00000000..2e73a753 --- /dev/null +++ b/templates/ui/chat/parts/description-part.hbs @@ -0,0 +1,11 @@ +
+
{{localize "DAGGERHEART.GENERAL.description"}}
+ +
+
+
+ {{{actionDescription}}} +
+
+
+
\ No newline at end of file diff --git a/templates/ui/chat/roll.hbs b/templates/ui/chat/roll.hbs index be51969f..c7b17b21 100644 --- a/templates/ui/chat/roll.hbs +++ b/templates/ui/chat/roll.hbs @@ -1,6 +1,10 @@
-
{{title}}
- {{#if hasRoll}}{{> 'systems/daggerheart/templates/ui/chat/parts/roll-part.hbs'}}{{/if}} +
{{title}}
+ {{#if actionDescription}}{{> 'systems/daggerheart/templates/ui/chat/parts/description-part.hbs'}}{{/if}} + {{#if hasRoll}} +
{{localize "Result"}}
+ {{> 'systems/daggerheart/templates/ui/chat/parts/roll-part.hbs'}} + {{/if}} {{#if (or hasDamage hasHealing)}}{{> 'systems/daggerheart/templates/ui/chat/parts/damage-part.hbs'}}{{/if}} {{#if hasTarget}}{{> 'systems/daggerheart/templates/ui/chat/parts/target-part.hbs'}}{{/if}}