diff --git a/module/data/chat-message/adversaryRoll.mjs b/module/data/chat-message/adversaryRoll.mjs index c0c218e3..10c0ba03 100644 --- a/module/data/chat-message/adversaryRoll.mjs +++ b/module/data/chat-message/adversaryRoll.mjs @@ -64,9 +64,9 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { return actionItem.system.actionsList?.find(a => a.id === this.source.action); } - get messageTemplate() { - return 'systems/daggerheart/templates/ui/chat/roll.hbs'; - } + // get messageTemplate() { + // return 'systems/daggerheart/templates/ui/chat/roll.hbs'; + // } get targetMode() { return this.targetSelection; @@ -100,7 +100,7 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { this.oldTargets.push(ct); }); if(this.hasSave) this.setPendingSaves(); - if(this.currentTargets.length) { + // if(this.currentTargets.length) { if(!this.parent._id) return; const updates = await this.parent.update( { @@ -111,7 +111,7 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { ); if(!updates && ui.chat.collection.get(this.parent.id)) ui.chat.updateMessage(this.parent); - } + // } } } diff --git a/module/data/fields/actionField.mjs b/module/data/fields/actionField.mjs index 00948f40..0247c72a 100644 --- a/module/data/fields/actionField.mjs +++ b/module/data/fields/actionField.mjs @@ -275,6 +275,7 @@ export function ActionMixin(Base) { } }; + ChatMessage.applyRollMode(msg, game.settings.get('core', 'rollMode')); cls.create(msg); } } diff --git a/module/dice/damageRoll.mjs b/module/dice/damageRoll.mjs index 11d317aa..699de672 100644 --- a/module/dice/damageRoll.mjs +++ b/module/dice/damageRoll.mjs @@ -31,16 +31,17 @@ export default class DamageRoll extends DHRoll { } static async buildPost(roll, config, message) { + const chatMessage = config.source?.message ? ui.chat.collection.get(config.source.message) : getDocumentClass('ChatMessage').applyRollMode({}, config.rollMode); if (game.modules.get('dice-so-nice')?.active) { const pool = foundry.dice.terms.PoolTerm.fromRolls( Object.values(config.damage).flatMap(r => r.parts.map(p => p.roll)) ), diceRoll = Roll.fromTerms([pool]); - await game.dice3d.showForRoll(diceRoll, game.user, true); + await game.dice3d.showForRoll(diceRoll, game.user, true, chatMessage.whisper, chatMessage.blind); } await super.buildPost(roll, config, message); if (config.source?.message) { - const chatMessage = ui.chat.collection.get(config.source.message); + // const chatMessage = ui.chat.collection.get(config.source.message); chatMessage.update({ 'system.damage': config.damage }); } } diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs index 1b490921..65292800 100644 --- a/module/dice/dhRoll.mjs +++ b/module/dice/dhRoll.mjs @@ -15,6 +15,8 @@ export default class DHRoll extends Roll { static messageType = 'adversaryRoll'; + static CHAT_TEMPLATE = 'systems/daggerheart/templates/ui/chat/roll.hbs'; + static DefaultDialog = D20RollDialog; static async build(config = {}, message = {}) { @@ -95,6 +97,39 @@ export default class DHRoll extends Roll { if(roll._evaluated) return await cls.create(msg, { rollMode: config.selectedRollMode }); return msg; } + + /** @inheritDoc */ + async render({flavor, template=this.constructor.CHAT_TEMPLATE, isPrivate=false, ...options}={}) { + if ( !this._evaluated ) return; + const chatData = await this._prepareChatRenderContext({flavor, isPrivate, ...options}); + return foundry.applications.handlebars.renderTemplate(template, chatData); + } + + /** @inheritDoc */ + async _prepareChatRenderContext({flavor, isPrivate=false, ...options}={}) { + if(isPrivate) { + return { + user: game.user.id, + flavor: null, + title: "???", + roll: { + total: "??" + }, + hasRoll: true, + isPrivate + } + } else { + options.message.system.user = game.user.id; + return options.message.system; + } + // return { + // formula: isPrivate ? "???" : this._formula, + // flavor: isPrivate ? null : flavor ?? this.options.flavor, + // user: game.user.id, + // tooltip: isPrivate ? "" : await this.getTooltip(), + // total: isPrivate ? "?" : Math.round(this.total * 100) / 100 + // }; + } static applyKeybindings(config) { if (config.event) diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index 35bae725..030b4df2 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -149,7 +149,7 @@ export default class DualityRoll extends D20Roll { } if (this.rallyFaces) this.terms.push( - new foundry.dice.terms.OperatorTerm({ operator: this.hasDisadvantage ? '-' : '+' }), + new foundry.dice.terms.OperatorTerm({ operator: '+' }), new foundry.dice.terms.Die({ faces: this.rallyFaces }) ); } diff --git a/module/documents/chatMessage.mjs b/module/documents/chatMessage.mjs index 302ba1d8..fb167cc7 100644 --- a/module/documents/chatMessage.mjs +++ b/module/documents/chatMessage.mjs @@ -1,21 +1,48 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { async renderHTML() { - if (this.system.messageTemplate) - this.content = await foundry.applications.handlebars.renderTemplate(this.system.messageTemplate, { - ...this.system, - _source: this.system._source - }); + // if (this.system.messageTemplate) + // this.content = await foundry.applications.handlebars.renderTemplate(this.system.messageTemplate, { + // ...this.system, + // _source: this.system._source + // }); const actor = game.actors.get(this.speaker.actor); - const actorData = actor ?? { + const actorData = actor && this.isContentVisible ? 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({ actor: actorData, author: this.author }); - this.applyPermission(html); - if (this.type === 'dualityRoll') { + this.enrichChatMessage(html); + this.addChatListeners(html); + + return html; + } + + /* async _preCreate(data, options, user) { + options.speaker = ChatMessage.getSpeaker(); + const rollActorOwner = data.rolls?.[0]?.data?.parent?.owner; + if (rollActorOwner) { + data.author = rollActorOwner ? rollActorOwner.id : data.author; + await this.updateSource({ author: rollActorOwner ?? user }); + } + + return super._preCreate(data, options, rollActorOwner ?? user); + } */ + + enrichChatMessage(html) { + const elements = html.querySelectorAll('[data-perm-id]'); + elements.forEach(e => { + const uuid = e.dataset.permId, + document = fromUuidSync(uuid); + if (!document) return; + + e.setAttribute('data-view-perm', document.testUserPermission(game.user, 'OBSERVER')); + e.setAttribute('data-use-perm', document.testUserPermission(game.user, 'OWNER')); + }); + + if (this.isContentVisible && this.type === 'dualityRoll') { html.classList.add('duality'); switch (this.system.roll?.result?.duality) { case 1: @@ -29,36 +56,9 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { break; } } - - this.enrichChatMessage(html); - - return html; } - applyPermission(html) { - const elements = html.querySelectorAll('[data-perm-id]'); - elements.forEach(e => { - const uuid = e.dataset.permId, - document = fromUuidSync(uuid); - if (!document) return; - - e.setAttribute('data-view-perm', document.testUserPermission(game.user, 'OBSERVER')); - e.setAttribute('data-use-perm', document.testUserPermission(game.user, 'OWNER')); - }); - } - - async _preCreate(data, options, user) { - options.speaker = ChatMessage.getSpeaker(); - const rollActorOwner = data.rolls?.[0]?.data?.parent?.owner; - if (rollActorOwner) { - data.author = rollActorOwner ? rollActorOwner.id : data.author; - await this.updateSource({ author: rollActorOwner ?? user }); - } - - return super._preCreate(data, options, rollActorOwner ?? user); - } - - enrichChatMessage(html) { + addChatListeners(html) { html.querySelectorAll('.damage-button').forEach(element => element.addEventListener('click', this.onDamage.bind(this)) ); @@ -66,6 +66,12 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { html.querySelectorAll('.duality-action-effect').forEach(element => element.addEventListener('click', this.onApplyEffect.bind(this)) ); + + html.querySelectorAll('.roll-target').forEach(element => { + element.addEventListener('mouseenter', this.hoverTarget); + element.addEventListener('mouseleave', this.unhoverTarget); + element.addEventListener('click', this.clickTarget); + }); } getTargetList() { @@ -146,4 +152,25 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { if (action) action.consume(this.system, true); } } + + hoverTarget(event) { + event.stopPropagation(); + const token = canvas.tokens.get(event.currentTarget.dataset.token); + if (!token?.controlled) token._onHoverIn(event, { hoverOutOthers: true }); + } + + unhoverTarget(event) { + const token = canvas.tokens.get(event.currentTarget.dataset.token); + if (!token?.controlled) token._onHoverOut(event); + } + + clickTarget(event) { + event.stopPropagation(); + const token = canvas.tokens.get(event.currentTarget.dataset.token); + if (!token) { + ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.attackTargetDoesNotExist')); + return; + } + game.canvas.pan(token); + } } diff --git a/styles/less/global/chat.less b/styles/less/global/chat.less index 1e37309d..37ec993d 100644 --- a/styles/less/global/chat.less +++ b/styles/less/global/chat.less @@ -32,6 +32,7 @@ .message-header-metadata { flex: none; display: flex; + flex-direction: column; .message-metadata { font-family: @font-body; @@ -73,6 +74,13 @@ .message-content { padding-bottom: 8px; + .flavor-text { + font-size: var(--font-size-12); + line-height: 20px; + color: var(--color-dark-4); + text-align: center; + display: block; + } } } } diff --git a/styles/less/ui/chat/chat.less b/styles/less/ui/chat/chat.less index 9afa32d3..b66e6477 100644 --- a/styles/less/ui/chat/chat.less +++ b/styles/less/ui/chat/chat.less @@ -11,333 +11,6 @@ } } - /* &.roll { - .dice-flavor { - text-align: center; - font-weight: bold; - } - .dice-tooltip { - .dice-rolls { - &.duality { - display: flex; - gap: 0.25rem; - - > .roll { - background-image: none; - - .reroll-button { - border: none; - background: initial; - width: 42px; - - &:hover { - background: var(--button-background-color); - border: 1px solid var(--button-border-color); - } - } - } - } - - &.rerollable { - position: relative; - flex: none; - - .dice-rerolled { - z-index: 2; - position: absolute; - right: 0; - font-size: 12px; - cursor: help; - } - - .reroll-button { - border: none; - background: initial; - - &:hover { - background: var(--button-background-color); - border: 1px solid var(--button-border-color); - } - } - } - - // margin: 0; - > .roll { - display: flex; - align-items: center; - justify-content: center; - gap: 4px; - margin-bottom: 4px; - - .dice-container { - display: flex; - flex-direction: column; - gap: 2px; - position: relative; - - .dice-title { - color: var(--color-light-1); - text-shadow: 0 0 1px black; - } - - .dice-rerolled { - z-index: 2; - position: absolute; - right: -2px; - font-size: 12px; - cursor: help; - } - - .dice-inner-container { - display: flex; - align-items: center; - justify-content: center; - position: relative; - &.hope, - &.fear { - .dice-wrapper { - clip-path: polygon( - 50% 0%, - 80% 10%, - 100% 35%, - 100% 70%, - 80% 90%, - 50% 100%, - 20% 90%, - 0% 70%, - 0% 35%, - 20% 10% - ); - } - } - .dice-wrapper { - height: 24px; - width: 24px; - position: relative; - display: flex; - align-items: center; - justify-content: center; - - .dice { - height: 26px; - width: 26px; - max-width: unset; - position: absolute; - } - } - - .dice-value { - position: absolute; - font-weight: bold; - font-size: 16px; - } - - &.hope { - .dice-wrapper { - background: black; - - .dice { - filter: brightness(0) saturate(100%) invert(79%) sepia(79%) saturate(333%) - hue-rotate(352deg) brightness(102%) contrast(103%); - } - } - - .dice-value { - color: var(--color-dark-1); - text-shadow: 0 0 4px white; - } - } - - &.fear { - .dice-wrapper { - background: white; - - .dice { - filter: brightness(0) saturate(100%) invert(12%) sepia(88%) saturate(4321%) - hue-rotate(221deg) brightness(92%) contrast(110%); - } - } - - .dice-value { - color: var(--color-light-1); - text-shadow: 0 0 4px black; - } - } - - &.advantage { - .dice-wrapper { - .dice { - filter: brightness(0) saturate(100%) invert(18%) sepia(92%) saturate(4133%) - hue-rotate(96deg) brightness(104%) contrast(107%); - } - } - } - - &.disadvantage { - .dice-wrapper { - .dice { - filter: brightness(0) saturate(100%) invert(9%) sepia(78%) saturate(6903%) - hue-rotate(11deg) brightness(93%) contrast(117%); - } - } - } - } - } - } - } - - .damage-resource { - font-weight: 600; - margin-top: 5px; - } - } - - .dice-total { - &.duality { - &.hope { - border-color: @hope; - border-width: 3px; - background: rgba(@hope, 0.5); - } - &.fear { - border-color: @fear; - border-width: 3px; - background: rgba(@fear, 0.5); - } - &.critical { - border-color: @critical; - border-width: 3px; - background: rgba(@critical, 0.5); - } - } - - .dice-total-value { - .hope { - color: @hope; - } - .fear { - color: @fear; - } - .critical { - color: @critical; - } - } - } - - .dice-total-label { - font-size: 12px; - font-weight: bold; - font-variant: all-small-caps; - margin: -@fullMargin 0; - } - - .target-selection { - display: flex; - justify-content: space-around; - input[type='radio'] { - display: none; - &:checked + label { - text-shadow: 0px 0px 4px #ce5937; - } - &:not(:checked) + label { - opacity: 0.75; - } - } - label { - cursor: pointer; - opacity: 0.75; - &.target-selected { - text-shadow: 0px 0px 4px #ce5937; - opacity: 1; - } - } - } - - .target-section { - margin-top: 5px; - - .target-container { - display: flex; - transition: all 0.2s ease-in-out; - - &:hover { - filter: drop-shadow(0 0 3px @secondaryShadow); - border-color: gold; - } - - &.hidden { - display: none; - border: 0; - } - - &.hit { - background: @hit; - } - - &.miss { - background: @miss; - } - - img, - .target-save-container { - width: 22px; - height: 22px; - align-self: center; - border-color: transparent; - } - - img { - flex: 0; - margin-left: 8px; - } - - .target-save-container { - margin-right: 8px; - justify-content: center; - display: flex; - align-items: center; - min-height: unset; - border: 1px solid black; - } - - .target-inner-container { - flex: 1; - display: flex; - justify-content: center; - font-size: var(--font-size-16); - } - - &:not(:has(.target-save-container)) .target-inner-container { - margin-right: @hugeMargin; - } - } - } - - .dice-actions { - display: flex; - gap: 4px; - - button { - flex: 1; - height: 40px; - font-family: @font-body; - font-weight: 600; - } - } - - .dice-result { - .roll-damage-button, - .damage-button, - .duality-action { - margin-top: 5px; - } - } - - &:not(.expanded) .dice-tooltip { - grid-template-rows: 0fr; - } - } */ - button { &.inner-button { --button-size: 1.25rem; @@ -412,7 +85,7 @@ grid-template-columns: 1fr auto 1fr; align-items: center; color: light-dark(@dark, @beige); - margin: 5px 0; + margin: 10px 0; span { display: flex; @@ -450,7 +123,7 @@ flex-direction: column; align-items: center; gap: 5px; - padding: 5px 0; + // padding: 5px 0; .dice-tooltip { width: 100%; @@ -489,6 +162,7 @@ color: var(--text-color); font-weight: 700; font-family: 'Cinzel', sans-serif; + line-height: .75; .roll-result-value { font-size: var(--font-size-24); @@ -600,6 +274,11 @@ width: 100%; gap: 10px; align-items: center; + border-radius: 3px; + + &:hover { + background-color: rgba(255,255,255,.1); + } .target-img { border-radius: 50%; @@ -640,6 +319,7 @@ padding: 3px 5px; width: fit-content; margin: auto; + white-space: nowrap; } .roll-difficulty, @@ -706,6 +386,19 @@ margin-top: 0; } + .damage-section[data-action='expandRoll'] { + .on-reduced { + .wrapper { + flex-wrap: wrap; + gap: 10px 5px; + } + + .roll-formula { + font-size: var(--font-size-16); + } + } + } + .target-section { .roll-part-content { gap: 10px; diff --git a/templates/ui/chat/chat-message.hbs b/templates/ui/chat/chat-message.hbs index 85cf03e2..94527f16 100644 --- a/templates/ui/chat/chat-message.hbs +++ b/templates/ui/chat/chat-message.hbs @@ -3,17 +3,19 @@
\ No newline at end of file diff --git a/templates/ui/chat/parts/roll-part.hbs b/templates/ui/chat/parts/roll-part.hbs index d4e46b1f..db810bcd 100644 --- a/templates/ui/chat/parts/roll-part.hbs +++ b/templates/ui/chat/parts/roll-part.hbs @@ -22,6 +22,7 @@ {{/if}} + {{#unless isPrivate}}