diff --git a/daggerheart.mjs b/daggerheart.mjs index 1bb9485e..6b2de662 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -129,6 +129,7 @@ Hooks.once('init', () => { CONFIG.ChatMessage.dataModels = models.chatMessages.config; CONFIG.ChatMessage.documentClass = documents.DhChatMessage; + CONFIG.ChatMessage.template = 'systems/daggerheart/templates/ui/chat/chat-message.hbs'; CONFIG.Canvas.rulerClass = placeables.DhRuler; CONFIG.Canvas.layers.templates.layerClass = placeables.DhTemplateLayer; diff --git a/lang/en.json b/lang/en.json index c6e6d5fd..950af403 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1646,6 +1646,9 @@ }, "UI": { "Chat": { + "action": { + "title": "Action" + }, "applyEffect": { "title": "Apply Effects - {name}" }, diff --git a/module/applications/dialogs/deathMove.mjs b/module/applications/dialogs/deathMove.mjs index 81808790..ef227aa6 100644 --- a/module/applications/dialogs/deathMove.mjs +++ b/module/applications/dialogs/deathMove.mjs @@ -54,6 +54,8 @@ export default class DhpDeathMove extends HandlebarsApplicationMixin(Application { player: this.actor.name, actor: { name: this.actor.name, img: this.actor.img }, + author: game.users.get(game.user.id), + speaker: cls.getSpeaker(), title: game.i18n.localize(this.selectedMove.name), img: this.selectedMove.img, description: game.i18n.localize(this.selectedMove.description) diff --git a/module/applications/dialogs/downtime.mjs b/module/applications/dialogs/downtime.mjs index 7911ecb9..756918df 100644 --- a/module/applications/dialogs/downtime.mjs +++ b/module/applications/dialogs/downtime.mjs @@ -139,6 +139,10 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV moves: moves, actor: this.actor.uuid }, + speaker: cls.getSpeaker(), + title: game.i18n.localize( + `DAGGERHEART.APPLICATIONS.Downtime.${this.shortrest ? 'shortRest' : 'longRest'}.title` + ), content: await foundry.applications.handlebars.renderTemplate( 'systems/daggerheart/templates/ui/chat/downtime.hbs', { diff --git a/module/applications/ui/chatLog.mjs b/module/applications/ui/chatLog.mjs index 5e507a3b..47619120 100644 --- a/module/applications/ui/chatLog.mjs +++ b/module/applications/ui/chatLog.mjs @@ -1,4 +1,4 @@ -import { emitAsGM, GMUpdateEvent } from "../../systemRegistration/socket.mjs"; +import { emitAsGM, GMUpdateEvent } from '../../systemRegistration/socket.mjs'; export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLog { constructor(options) { @@ -15,6 +15,11 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo this.setupHooks(); } + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + classes: ['daggerheart'] + }; + addChatListeners = async (app, html, data) => { html.querySelectorAll('.duality-action-damage').forEach(element => element.addEventListener('click', event => this.onRollDamage(event, data.message)) @@ -100,22 +105,24 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo if (message.system.source.item && message.system.source.action) { const action = this.getAction(actor, message.system.source.item, message.system.source.action); if (!action || !action?.hasSave) return; - action.rollSave(token.actor, event, message).then(result => emitAsGM( - GMUpdateEvent.UpdateSaveMessage, - action.updateSaveMessage.bind(action, result, message, token.id), - { - action: action.uuid, - message: message._id, - token: token.id, - result - } - )); + action.rollSave(token.actor, event, message).then(result => + emitAsGM( + GMUpdateEvent.UpdateSaveMessage, + action.updateSaveMessage.bind(action, result, message, token.id), + { + action: action.uuid, + message: message._id, + token: token.id, + result + } + ) + ); } } async onRollAllSave(event, message) { event.stopPropagation(); - if(!game.user.isGM) return; + if (!game.user.isGM) return; const targets = event.target.parentElement.querySelectorAll( '.target-section > [data-token] .target-save-container' ); @@ -124,16 +131,17 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo targets.forEach(async el => { const tokenId = el.closest('[data-token]')?.dataset.token, token = game.canvas.tokens.get(tokenId); - if(!token.actor) return; - if(game.user === token.actor.owner) - el.dispatchEvent(new PointerEvent('click', { shiftKey: true })); + if (!token.actor) return; + if (game.user === token.actor.owner) el.dispatchEvent(new PointerEvent('click', { shiftKey: true })); else { - token.actor.owner.query('reactionRoll', { - actionId: action.uuid, - actorId: token.actor.uuid, - event, - message - }).then(result => action.updateSaveMessage(result, message, token.id)); + token.actor.owner + .query('reactionRoll', { + actionId: action.uuid, + actorId: token.actor.uuid, + event, + message + }) + .then(result => action.updateSaveMessage(result, message, token.id)); } }); } @@ -172,7 +180,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo return { isHit, targets: isHit - ? message.system.targets.filter(t => t.hit === true).map(target => game.canvas.tokens.documentCollection.find(t => t.actor.uuid === target.actorId)) + ? message.system.targets + .filter(t => t.hit === true) + .map(target => game.canvas.tokens.documentCollection.find(t => t.actor.uuid === target.actorId)) : Array.from(game.user.targets) }; } @@ -234,10 +244,8 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo }); } - if(message.system.hasHealing) - target.actor.takeHealing(damages); - else - target.actor.takeDamage(damages); + if (message.system.hasHealing) target.actor.takeHealing(damages); + else target.actor.takeDamage(damages); } } diff --git a/module/data/fields/actionField.mjs b/module/data/fields/actionField.mjs index 3135988b..00948f40 100644 --- a/module/data/fields/actionField.mjs +++ b/module/data/fields/actionField.mjs @@ -254,11 +254,15 @@ export function ActionMixin(Base) { origin: origin, action: { name: this.name, img: this.img, tags: this.tags ? this.tags : ['Spell', 'Arcana', 'Lv 10'] }, itemOrigin: this.item, - description: this.description, + description: this.description }; const msg = { type: 'abilityUse', user: game.user.id, + actor: { name: this.actor.name, img: this.actor.img }, + author: this.author, + speaker: cls.getSpeaker(), + title: game.i18n.localize('DAGGERHEART.UI.Chat.action.title'), system: systemData, content: await foundry.applications.handlebars.renderTemplate( 'systems/daggerheart/templates/ui/chat/action.hbs', diff --git a/module/documents/chatMessage.mjs b/module/documents/chatMessage.mjs index 46f95633..a0c5d2e8 100644 --- a/module/documents/chatMessage.mjs +++ b/module/documents/chatMessage.mjs @@ -6,8 +6,13 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { _source: this.system._source }); + const actor = game.actors.get(this.speaker.actor); + const actorData = actor ?? { + img: this.author.avatar ? this.author.avatar : 'icons/svg/mystery-man.svg', + name: '' + }; /* We can change to fully implementing the renderHTML function if needed, instead of augmenting it. */ - const html = await super.renderHTML(); + const html = await super.renderHTML({ actor: actorData, author: this.author }); this.applyPermission(html); if (this.type === 'dualityRoll') { diff --git a/module/documents/item.mjs b/module/documents/item.mjs index f69bcbc2..b6dfb280 100644 --- a/module/documents/item.mjs +++ b/module/documents/item.mjs @@ -128,7 +128,11 @@ export default class DHItem extends foundry.documents.Item { const msg = new cls({ type: 'abilityUse', user: game.user.id, + actor: this.actor, + author: this.author, + speaker: cls.getSpeaker(), system: systemData, + title: game.i18n.localize('DAGGERHEART.ACTIONS.Config.displayInChat'), content: await foundry.applications.handlebars.renderTemplate( 'systems/daggerheart/templates/ui/chat/ability-use.hbs', systemData diff --git a/styles/less/global/chat.less b/styles/less/global/chat.less index 60e6b69b..54d1ba46 100644 --- a/styles/less/global/chat.less +++ b/styles/less/global/chat.less @@ -1,18 +1,74 @@ -@import '../utils/colors.less'; -@import '../utils/fonts.less'; -@import '../utils/mixin.less'; - -.dh-chat-message { - background-image: url('../assets/parchments/dh-parchment-dark.png'); - border: none !important; - padding: 8px 0; - - .message-header { - padding: 0 8px 8px; - color: @beige; - .message-sender, - .message-metadata { - font-family: @font-body; - } - } -} +@import '../utils/colors.less'; +@import '../utils/fonts.less'; +@import '../utils/mixin.less'; + +.theme-light { + .daggerheart.chat-sidebar .chat-log, + #chat-notifications .chat-log { + .chat-message { + background-image: url('../assets/parchments/dh-parchment-light.png'); + } + } +} + +#chat-message { + font-family: @font-body; + padding: 8px; +} + +.daggerheart.chat-sidebar, +#chat-notifications { + .chat-log { + .chat-message { + border: none !important; + padding: 8px 0; + background-image: url('../assets/parchments/dh-parchment-dark.png'); + + .message-header { + display: flex; + gap: 4px; + padding: 0 8px 8px; + + .message-header-metadata { + flex: none; + display: flex; + + .message-metadata { + font-family: @font-body; + color: light-dark(@dark, @beige); + } + } + + .message-header-main { + display: flex; + align-items: center; + gap: 8px; + flex: 1; + + .actor-img { + border-radius: 50%; + width: 40px; + height: 40px; + object-fit: cover; + } + + .message-sub-header-container { + flex: 1; + display: flex; + flex-direction: column; + justify-content: space-between; + color: light-dark(@dark, @beige); + + h4 { + font-size: 16px; + font-weight: bold; + margin-bottom: 0; + font-family: @font-subtitle; + color: light-dark(@dark-blue, @golden); + } + } + } + } + } + } +} diff --git a/styles/less/ui/chat/ability-use.less b/styles/less/ui/chat/ability-use.less index 3a192835..687579cb 100644 --- a/styles/less/ui/chat/ability-use.less +++ b/styles/less/ui/chat/ability-use.less @@ -15,40 +15,71 @@ object-fit: cover; } - .domain-card-header { - display: flex; - flex-direction: column; - width: 100%; - margin: 8px 8px 0; - padding-bottom: 5px; - width: -webkit-fill-available; - gap: 5px; - border-bottom: 1px solid @golden; + details[open] { + .fa-chevron-down { + transform: rotate(180deg); + transition: all 0.3s ease; + } + } - .title { - font-size: 20px; - color: @golden; - font-family: @font-subtitle; - margin: 0; + .domain-card-move { + width: 100%; + + .fa-chevron-down { + transition: all 0.3s ease; + margin-left: auto; } - .tags { + .domain-card-header { display: flex; - gap: 10px; + flex-direction: row; + align-items: center; + margin: 8px; + padding-bottom: 5px; + width: -webkit-fill-available; + gap: 5px; + border-bottom: 1px solid @golden; - .tag { + &:hover { + background: light-dark(@dark-blue-10, @golden-10); + cursor: pointer; + transition: all 0.3s ease; + } + + .domain-label { display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - padding: 3px 5px; - font-size: 12px; - font-family: @font-body; + flex-direction: column; + width: 100%; + padding-bottom: 5px; + width: -webkit-fill-available; + gap: 5px; - background: light-dark(@dark-15, @beige-15); - border: 1px solid light-dark(@dark, @beige); - color: light-dark(@dark, @beige); - border-radius: 3px; + .title { + font-size: 20px; + color: @golden; + font-family: @font-subtitle; + margin: 0; + } + + .tags { + display: flex; + gap: 10px; + + .tag { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 3px 5px; + font-size: 12px; + font-family: @font-body; + + background: light-dark(@dark-15, @beige-15); + border: 1px solid light-dark(@dark, @beige); + color: light-dark(@dark, @beige); + border-radius: 3px; + } + } } } } diff --git a/styles/less/ui/chat/action.less b/styles/less/ui/chat/action.less index b20ed8a4..c3c51816 100644 --- a/styles/less/ui/chat/action.less +++ b/styles/less/ui/chat/action.less @@ -8,40 +8,62 @@ flex-direction: column; align-items: center; - .action-section { - display: flex; - flex-direction: row; - width: 100%; - margin: 8px 8px 0; - padding-bottom: 5px; - width: -webkit-fill-available; - gap: 5px; - border-bottom: 1px solid @golden; + details[open] { + .fa-chevron-down { + transform: rotate(180deg); + transition: all 0.3s ease; + } + } - .action-img { - width: 40px; - height: 40px; - border-radius: 3px; - object-fit: cover; + .action-move { + width: 100%; + + .fa-chevron-down { + transition: all 0.3s ease; + margin-left: auto; } - .action-header { + .action-section { display: flex; - flex-direction: column; + flex-direction: row; + align-items: center; + margin: 8px 8px 0; + padding-bottom: 5px; + width: -webkit-fill-available; gap: 5px; + border-bottom: 1px solid @golden; - .title { - font-size: 20px; - color: @golden; - font-family: @font-subtitle; - margin: 0; + &:hover { + background: light-dark(@dark-blue-10, @golden-10); + cursor: pointer; + transition: all 0.3s ease; } - .label { - font-size: 12px; - color: @beige; - font-family: @font-body; - margin: 0; + .action-img { + width: 40px; + height: 40px; + border-radius: 3px; + object-fit: cover; + } + + .action-header { + display: flex; + flex-direction: column; + gap: 5px; + + .title { + font-size: 20px; + color: @golden; + font-family: @font-subtitle; + margin: 0; + } + + .label { + font-size: 12px; + color: @beige; + font-family: @font-body; + margin: 0; + } } } } diff --git a/styles/less/ui/chat/chat.less b/styles/less/ui/chat/chat.less index c27f8b3c..5c448a8f 100644 --- a/styles/less/ui/chat/chat.less +++ b/styles/less/ui/chat/chat.less @@ -319,6 +319,9 @@ button { flex: 1; + height: 40px; + font-family: @font-body; + font-weight: 600; } } diff --git a/styles/less/ui/chat/downtime.less b/styles/less/ui/chat/downtime.less index ab9ca3dc..bc702aeb 100644 --- a/styles/less/ui/chat/downtime.less +++ b/styles/less/ui/chat/downtime.less @@ -8,35 +8,10 @@ flex-direction: column; align-items: center; - .downtime-header { - display: flex; - gap: 13px; - flex-direction: row; - align-items: center; - width: 100%; - padding-left: 8px; - margin-bottom: 12px; - - .profile { - width: 40px; - height: 40px; - border-radius: 50%; - object-fit: cover; - } - - .header-label { - .title { - font-size: 20px; - color: @golden; - font-family: @font-subtitle; - margin: 0; - } - .label { - font-size: 12px; - color: @beige; - font-family: @font-body; - margin: 0; - } + details[open] { + .fa-chevron-down { + transform: rotate(180deg); + transition: all 0.3s ease; } } @@ -44,6 +19,12 @@ display: flex; flex-direction: column; gap: 5px; + width: 100%; + + .fa-chevron-down { + transition: all 0.3s ease; + margin-left: auto; + } .downtime-move { width: 100%; @@ -57,6 +38,12 @@ padding-bottom: 5px; width: -webkit-fill-available; + &:hover { + background: light-dark(@dark-blue-10, @golden-10); + cursor: pointer; + transition: all 0.3s ease; + } + .downtime-image { width: 40px; height: 40px; diff --git a/styles/less/ui/chat/sheet.less b/styles/less/ui/chat/sheet.less index 1c41f97e..da66c12f 100644 --- a/styles/less/ui/chat/sheet.less +++ b/styles/less/ui/chat/sheet.less @@ -1,3 +1,12 @@ +@import '../../utils/colors.less'; +@import '../../utils/fonts.less'; + +.chat-message.dh-chat-message { + .message-content { + padding: 0; + } +} + .chat-message { .duality-modifiers, .duality-result, @@ -6,6 +15,66 @@ } .message-content { + padding: 0 8px; + font-family: @font-body; + color: light-dark(@dark, @beige); + + blockquote { + border-left: 5px solid light-dark(@dark-blue-40, @golden-40); + } + + a[href] { + color: light-dark(@dark-blue, @golden); + } + + a[href]:hover, + a[href].active { + font-weight: bold; + text-shadow: 0 0 8px light-dark(@dark-blue, @golden); + } + + button { + background: light-dark(transparent, @golden); + border: 1px solid light-dark(@dark-blue, @dark-blue); + color: light-dark(@dark-blue, @dark-blue); + outline: none; + box-shadow: none; + + &:hover { + background: light-dark(@light-black, @dark-blue); + color: light-dark(@dark-blue, @golden); + } + + &.glow { + animation: glow 0.75s infinite alternate; + } + + &:disabled { + background: light-dark(transparent, @golden); + color: light-dark(@dark-blue, @dark-blue); + opacity: 0.6; + cursor: not-allowed; + + &:hover { + background: light-dark(transparent, @golden); + color: light-dark(@dark-blue, @dark-blue); + } + } + + &.reverted { + background: light-dark(@dark-blue-10, @golden-10); + color: light-dark(@dark-blue, @golden); + border: 1px solid light-dark(@dark, transparent); + &:hover { + background: light-dark(transparent, @golden); + color: light-dark(@dark-blue, @dark-blue); + } + img { + border-radius: 3px; + } + } + } + .enriched-effect { display: flex; align-items: center; @@ -24,6 +93,24 @@ white-space: nowrap; } } + + .dice-roll .dice-formula, + .dice-roll .dice-total { + box-shadow: none; + border: none; + background: light-dark(@dark-blue-40, @golden-40); + color: light-dark(@dark-blue, @golden); + font-weight: 600; + align-content: center; + } + + .dice-roll .dice-formula { + height: 27px; + } + + .dice-roll .dice-total { + height: 34px; + } } } diff --git a/templates/ui/chat/ability-use.hbs b/templates/ui/chat/ability-use.hbs index 338fcd59..30c5ebb9 100644 --- a/templates/ui/chat/ability-use.hbs +++ b/templates/ui/chat/ability-use.hbs @@ -1,14 +1,19 @@