From 8b834036fa0dcf4b94549aa31d0a7c6479bd0c17 Mon Sep 17 00:00:00 2001 From: Dapoulp <74197441+Dapoulp@users.noreply.github.com> Date: Tue, 1 Jul 2025 19:04:53 +0200 Subject: [PATCH] Feature/165 action save (#231) * Roll All Save button + Merge Attack & Roll Chat message * Fix conflicts again --- daggerheart.mjs | 2 +- lang/en.json | 5 +- module/applications/roll.mjs | 9 ++- module/config/generalConfig.mjs | 32 +++++--- module/data/action/action.mjs | 64 +++++++-------- module/data/chat-message/adversaryRoll.mjs | 15 +++- module/data/chat-message/damageRoll.mjs | 6 ++ module/data/chat-message/dualityRoll.mjs | 42 +--------- module/data/chat-message/hitRoll.mjs | 0 module/documents/actor.mjs | 4 +- module/ui/chatLog.mjs | 49 +++++++++--- styles/chat.less | 91 +++++++++++++++++++++- styles/daggerheart.css | 84 +++++++++++++++++++- templates/chat/adversary-roll.hbs | 21 ++++- templates/chat/damage-roll.hbs | 27 +------ templates/chat/duality-roll.hbs | 14 ++++ templates/chat/parts/damage-chat.hbs | 27 +++++++ templates/chat/parts/target-chat.hbs | 17 ++-- 18 files changed, 369 insertions(+), 140 deletions(-) create mode 100644 module/data/chat-message/hitRoll.mjs create mode 100644 templates/chat/parts/damage-chat.hbs diff --git a/daggerheart.mjs b/daggerheart.mjs index 27c01dd6..5433c586 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -324,7 +324,7 @@ const preloadHandlebarsTemplates = async function () { 'systems/daggerheart/templates/views/actionTypes/range-target.hbs', 'systems/daggerheart/templates/views/actionTypes/effect.hbs', 'systems/daggerheart/templates/settings/components/settings-item-line.hbs', - + 'systems/daggerheart/templates/chat/parts/damage-chat.hbs', 'systems/daggerheart/templates/chat/parts/target-chat.hbs' ]); }; diff --git a/lang/en.json b/lang/en.json index 2f9790da..de29b88a 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1063,7 +1063,10 @@ "DamageRoll": { "Title": "Damage - {damage}", "DealDamageToTargets": "Damage Hit Targets", - "DealDamage": "Deal Damage" + "DealDamage": "Deal Damage", + "RollDamage": "Roll Damage", + "HitTarget": "Hit Targets", + "SelectedTarget": "Selected" }, "ApplyEffect": { "Title": "Apply Effects - {name}" diff --git a/module/applications/roll.mjs b/module/applications/roll.mjs index eaf4747b..cb7d0dff 100644 --- a/module/applications/roll.mjs +++ b/module/applications/roll.mjs @@ -1,3 +1,4 @@ +import DHDamageRoll from '../data/chat-message/damageRoll.mjs'; import D20RollDialog from '../dialogs/d20RollDialog.mjs'; import DamageDialog from '../dialogs/damageDialog.mjs'; @@ -53,12 +54,13 @@ export class DHRoll extends Roll { } static async buildPost(roll, config, message) { + console.log(config) for (const hook of config.hooks) { if (Hooks.call(`${SYSTEM.id}.postRoll${hook.capitalize()}`, config, message) === false) return null; } // Create Chat Message - if (message.data) { + if (config.source?.message) { } else { const messageData = {}; config.message = await this.toMessage(roll, config); @@ -393,7 +395,6 @@ export class DualityRoll extends D20Roll { total: roll.dHope.total + roll.dFear.total, label: roll.totalLabel }; - console.log(roll, config); } } @@ -409,5 +410,9 @@ export class DamageRoll extends DHRoll { static async postEvaluate(roll, config = {}) { super.postEvaluate(roll, config); config.roll.type = config.type; + if(config.source?.message) { + const chatMessage = ui.chat.collection.get(config.source.message); + chatMessage.update({'system.damage': config}); + } } } diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index 28cfc576..6710d3ed 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -342,39 +342,53 @@ export const refreshTypes = { export const abilityCosts = { hope: { id: 'hope', - label: 'Hope' + label: 'Hope', + group: 'TYPES.Actor.character' }, stress: { id: 'stress', - label: 'DAGGERHEART.HealingType.Stress.Name' + label: 'DAGGERHEART.HealingType.Stress.Name', + group: 'TYPES.Actor.character' }, armor: { id: 'armor', - label: 'Armor Stack' + label: 'Armor Stack', + group: 'TYPES.Actor.character' }, hp: { id: 'hp', - label: 'DAGGERHEART.HealingType.HitPoints.Name' + label: 'DAGGERHEART.HealingType.HitPoints.Name', + group: 'TYPES.Actor.character' }, prayer: { id: 'prayer', - label: 'Prayer Dice' + label: 'Prayer Dice', + group: 'TYPES.Actor.character' }, favor: { id: 'favor', - label: 'Favor Points' + label: 'Favor Points', + group: 'TYPES.Actor.character' }, slayer: { id: 'slayer', - label: 'Slayer Dice' + label: 'Slayer Dice', + group: 'TYPES.Actor.character' }, tide: { id: 'tide', - label: 'Tide' + label: 'Tide', + group: 'TYPES.Actor.character' }, chaos: { id: 'chaos', - label: 'Chaos' + label: 'Chaos', + group: 'TYPES.Actor.character' + }, + fear: { + id: 'fear', + label: 'Fear', + group: 'TYPES.Actor.adversary' } }; diff --git a/module/data/action/action.mjs b/module/data/action/action.mjs index da776df8..bc0f6524 100644 --- a/module/data/action/action.mjs +++ b/module/data/action/action.mjs @@ -320,14 +320,14 @@ export class DHBaseAction extends foundry.abstract.DataModel { prepareTarget() { let targets; if (this.target?.type === SYSTEM.ACTIONS.targetTypes.self.id) - targets = this.formatTarget(this.actor.token ?? this.actor.prototypeToken); + targets = this.constructor.formatTarget(this.actor.token ?? this.actor.prototypeToken); targets = Array.from(game.user.targets); // foundry.CONST.TOKEN_DISPOSITIONS.FRIENDLY if (this.target?.type && this.target.type !== SYSTEM.ACTIONS.targetTypes.any.id) { targets = targets.filter(t => this.isTargetFriendly(t)); if (this.target.amount && targets.length > this.target.amount) targets = []; } - targets = targets.map(t => this.formatTarget(t)); + targets = targets.map(t => this.constructor.formatTarget(t)); return targets; } @@ -400,11 +400,13 @@ export class DHBaseAction extends foundry.abstract.DataModel { } hasCost(costs) { - const realCosts = this.getRealCosts(costs); - return realCosts.reduce( - (a, c) => a && this.actor.system.resources[c.type]?.value >= (c.total ?? c.value), - true - ); + const realCosts = this.getRealCosts(costs), + hasFearCost = realCosts.findIndex(c => c.type === 'fear'); + if(hasFearCost > -1) { + const fearCost = realCosts.splice(hasFearCost, 1); + if(!game.user.isGM || fearCost[0].total > game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear)) return false; + } + return realCosts.reduce((a, c) => a && this.actor.system.resources[c.type]?.value >= (c.total ?? c.value), true); } /* COST */ @@ -435,7 +437,7 @@ export class DHBaseAction extends foundry.abstract.DataModel { ); } - formatTarget(actor) { + static formatTarget(actor) { return { id: actor.id, actorId: actor.actor.uuid, @@ -452,10 +454,11 @@ export class DHBaseAction extends foundry.abstract.DataModel { /* RANGE */ /* EFFECTS */ - async applyEffects(event, data, force = false) { - if (!this.effects?.length || !data.system.targets.length) return; + async applyEffects(event, data, targets) { + targets ??= data.system.targets; + if (!this.effects?.length || !targets.length) return; let effects = this.effects; - data.system.targets.forEach(async token => { + targets.forEach(async token => { if (!token.hit && !force) return; if (this.hasSave && token.saved.success === true) { effects = this.effects.filter(e => e.onSave === true); @@ -495,25 +498,19 @@ export class DHBaseAction extends foundry.abstract.DataModel { /* SAVE */ async rollSave(target, event, message) { - if (!target?.actor) return; - target.actor - .diceRoll({ - event, - title: 'Roll Save', - roll: { - trait: this.save.trait, - difficulty: this.save.difficulty, - type: 'reaction' - }, - data: target.actor.getRollData() - }) - .then(async result => { - if (result) - this.updateChatMessage(message, target.id, { - result: result.roll.total, - success: result.roll.success - }); - }); + if(!target?.actor) return; + return target.actor.diceRoll({ + event, + title: 'Roll Save', + roll: { + trait: this.save.trait, + difficulty: this.save.difficulty, + type: "reaction" + }, + data: target.actor.getRollData() + }).then(async (result) => { + if(result) this.updateChatMessage(message, target.id, {result: result.roll.total, success: result.roll.success}); + }) } async updateChatMessage(message, targetId, changes, chain = true) { @@ -539,13 +536,6 @@ export class DHBaseAction extends foundry.abstract.DataModel { export class DHDamageAction extends DHBaseAction { static extraSchemas = ['damage', 'target', 'effects']; - /* async use(event, ...args) { - const config = await super.use(event, args); - if (!config || ['error', 'warning'].includes(config.type)) return; - if (!this.directDamage) return; - return await this.rollDamage(event, config); - } */ - getFormulaValue(part, data) { let formulaValue = part.value; if (this.hasRoll && part.resultBased && data.system.roll.result.duality === -1) return part.valueAlt; diff --git a/module/data/chat-message/adversaryRoll.mjs b/module/data/chat-message/adversaryRoll.mjs index d97783c8..dffeeb20 100644 --- a/module/data/chat-message/adversaryRoll.mjs +++ b/module/data/chat-message/adversaryRoll.mjs @@ -1,7 +1,9 @@ +import { DHBaseAction } from "../action/action.mjs"; + +const fields = foundry.data.fields; + export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel { static defineSchema() { - const fields = foundry.data.fields; - return { title: new fields.StringField(), roll: new fields.DataField(), @@ -20,6 +22,7 @@ export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel { }) }) ), + targetSelection: new fields.BooleanField({ initial: true }), hasDamage: new fields.BooleanField({ initial: false }), hasHealing: new fields.BooleanField({ initial: false }), hasEffect: new fields.BooleanField({ initial: false }), @@ -28,11 +31,17 @@ export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel { actor: new fields.StringField(), item: new fields.StringField(), action: new fields.StringField() - }) + }), + damage: new fields.ObjectField() }; } get messageTemplate() { return 'systems/daggerheart/templates/chat/adversary-roll.hbs'; } + + prepareDerivedData() { + this.hasHitTarget = this.targets.filter(t => t.hit === true).length > 0; + this.currentTargets = this.targetSelection !== true ? Array.from(game.user.targets).map(t => DHBaseAction.formatTarget(t)) : this.targets; + } } diff --git a/module/data/chat-message/damageRoll.mjs b/module/data/chat-message/damageRoll.mjs index 29ad6fbd..9c83a58a 100644 --- a/module/data/chat-message/damageRoll.mjs +++ b/module/data/chat-message/damageRoll.mjs @@ -19,6 +19,7 @@ export default class DHDamageRoll extends foundry.abstract.TypeDataModel { }) }) ), + targetSelection: new fields.BooleanField({ initial: true }), hasSave: new fields.BooleanField({ initial: false }), onSave: new fields.StringField(), source: new fields.SchemaField({ @@ -34,4 +35,9 @@ export default class DHDamageRoll extends foundry.abstract.TypeDataModel { get messageTemplate() { return `systems/daggerheart/templates/chat/${this.messageType}-roll.hbs`; } + + prepareDerivedData() { + this.hasHitTarget = this.targets.filter(t => t.hit === true).length > 0; + this.currentTargets = this.targetSelection !== true ? Array.from(game.user.targets).map(t => DHBaseAction.formatTarget(t)) : this.targets; + } } diff --git a/module/data/chat-message/dualityRoll.mjs b/module/data/chat-message/dualityRoll.mjs index 1fdb537c..8b817ab1 100644 --- a/module/data/chat-message/dualityRoll.mjs +++ b/module/data/chat-message/dualityRoll.mjs @@ -1,44 +1,6 @@ -const fields = foundry.data.fields; - -export default class DHDualityRoll extends foundry.abstract.TypeDataModel { - static dualityResult = { - hope: 1, - fear: 2, - critical: 3 - }; - - static defineSchema() { - return { - title: new fields.StringField(), - roll: new fields.DataField({}), - targets: new fields.ArrayField( - new fields.SchemaField({ - id: new fields.StringField({}), - actorId: new fields.StringField({}), - name: new fields.StringField({}), - img: new fields.StringField({}), - difficulty: new fields.NumberField({ integer: true, nullable: true }), - evasion: new fields.NumberField({ integer: true }), - hit: new fields.BooleanField({ initial: false }), - saved: new fields.SchemaField({ - result: new fields.NumberField(), - success: new fields.BooleanField({ nullable: true, initial: null }) - }) - }) - ), - costs: new fields.ArrayField(new fields.ObjectField()), - hasDamage: new fields.BooleanField({ initial: false }), - hasHealing: new fields.BooleanField({ initial: false }), - hasEffect: new fields.BooleanField({ initial: false }), - hasSave: new fields.BooleanField({ initial: false }), - source: new fields.SchemaField({ - actor: new fields.StringField(), - item: new fields.StringField(), - action: new fields.StringField() - }) - }; - } +import DHAdversaryRoll from "./adversaryRoll.mjs"; +export default class DHDualityRoll extends DHAdversaryRoll { get messageTemplate() { return 'systems/daggerheart/templates/chat/duality-roll.hbs'; } diff --git a/module/data/chat-message/hitRoll.mjs b/module/data/chat-message/hitRoll.mjs new file mode 100644 index 00000000..e69de29b diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 49282385..15001bec 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -484,6 +484,9 @@ export default class DhpActor extends Actor { let updates = { actor: { target: this, resources: {} }, armor: { target: this.system.armor, resources: {} } }; resources.forEach(r => { switch (r.type) { + case 'fear': + ui.resources.updateFear(game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Resources.Fear) + r.value); + break; case 'armorStack': updates.armor.resources['system.marks.value'] = Math.max( Math.min(this.system.armor.system.marks.value + r.value, this.system.armorScore), @@ -502,7 +505,6 @@ export default class DhpActor extends Actor { } }); Object.values(updates).forEach(async u => { - console.log(updates, u); if (Object.keys(u.resources).length > 0) { if (game.user.isGM) { await u.target.update(u.resources); diff --git a/module/ui/chatLog.mjs b/module/ui/chatLog.mjs index eeb515cf..719a5428 100644 --- a/module/ui/chatLog.mjs +++ b/module/ui/chatLog.mjs @@ -25,6 +25,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo html.querySelectorAll('.target-save-container').forEach(element => element.addEventListener('click', event => this.onRollSave(event, data.message)) ); + html.querySelectorAll('.roll-all-save-button').forEach(element => + element.addEventListener('click', event => this.onRollAllSave(event, data.message)) + ); html.querySelectorAll('.duality-action-effect').forEach(element => element.addEventListener('click', event => this.onApplyEffect(event, data.message)) ); @@ -33,6 +36,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo element.addEventListener('mouseleave', this.unhoverTarget); element.addEventListener('click', this.clickTarget); }); + html.querySelectorAll('.button-target-selection').forEach(element => { + element.addEventListener('click', event => this.onTargetSelection(event, data.message)) + }); html.querySelectorAll('.damage-button').forEach(element => element.addEventListener('click', event => this.onDamage(event, data.message)) ); @@ -107,7 +113,6 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo tokenId = event.target.closest('[data-token]')?.dataset.token, token = game.canvas.tokens.get(tokenId); if (!token?.actor || !token.isOwner) return true; - console.log(token.actor.canUserModify(game.user, 'update')); 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; @@ -115,6 +120,14 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo } }; + onRollAllSave = async (event, message) => { + event.stopPropagation(); + const targets = event.target.parentElement.querySelectorAll('.target-section > [data-token] .target-save-container'); + targets.forEach((el) => { + el.dispatchEvent(new PointerEvent("click", { shiftKey: true})) + }) + } + onApplyEffect = async (event, message) => { event.stopPropagation(); const actor = await this.getActor(message.system.source.actor); @@ -122,10 +135,30 @@ 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?.applyEffects) return; - await action.applyEffects(event, message); + const { isHit, targets } = this.getTargetList(event, message); + if (targets.length === 0) + ui.notifications.info(game.i18n.localize('DAGGERHEART.Notification.Info.NoTargetsSelected')); + await action.applyEffects(event, message, targets); } }; + onTargetSelection = async (event, message) => { + event.stopPropagation(); + const targetSelection = Boolean(event.target.dataset.targetHit), + msg = ui.chat.collection.get(message._id); + if(msg.system.targetSelection === targetSelection) return; + if(targetSelection !== true && !Array.from(game.user.targets).length) return ui.notifications.info(game.i18n.localize('DAGGERHEART.Notification.Info.NoTargetsSelected')); + msg.system.targetSelection = targetSelection; + msg.system.prepareDerivedData(); + ui.chat.updateMessage(msg); + } + + getTargetList = (event, message) => { + const targetSelection = event.target.closest('.message-content').querySelector('.button-target-selection.target-selected'), + isHit = Boolean(targetSelection.dataset.targetHit); + return {isHit, targets: isHit ? message.system.targets.filter(t => t.hit === true).map(target => game.canvas.tokens.get(target.id)) : Array.from(game.user.targets)}; + } + hoverTarget = event => { event.stopPropagation(); const token = canvas.tokens.get(event.currentTarget.dataset.token); @@ -150,15 +183,11 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo onDamage = async (event, message) => { event.stopPropagation(); - const targets = event.currentTarget.dataset.targetHit - ? message.system.targets.map(target => game.canvas.tokens.get(target.id)) - : Array.from(game.user.targets); + const { isHit, targets } = this.getTargetList(event, message); - if (message.system.onSave && event.currentTarget.dataset.targetHit) { - const pendingingSaves = message.system.targets.filter( - target => target.hit && target.saved.success === null - ); - if (pendingingSaves.length) { + if(message.system.onSave && isHit) { + const pendingingSaves = message.system.targets.filter(target => target.hit && target.saved.success === null); + if(pendingingSaves.length) { const confirm = await foundry.applications.api.DialogV2.confirm({ window: { title: 'Pending Reaction Rolls found' }, content: `

Some Tokens still need to roll their Reaction Roll.

Are you sure you want to continue ?

Undone reaction rolls will be considered as failed

` diff --git a/styles/chat.less b/styles/chat.less index 15ff39e7..77aa892b 100644 --- a/styles/chat.less +++ b/styles/chat.less @@ -11,6 +11,23 @@ fieldset.daggerheart.chat { border-left-width: 0; border-right-width: 0; border-bottom-width: 0; + legend { + display: flex; + align-items: center; + gap: 5px; + &:before, &:after { + content: '\f0d8'; + font-family: "Font Awesome 6 Pro"; + } + } + &.expanded { + legend:before, legend:after { + content: '\f0d7'; + } + } + .daggerheart.chat { + margin-top: 5px; + } } .daggerheart.chat { @@ -209,6 +226,28 @@ fieldset.daggerheart.chat { 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: .75; + } + } + label { + cursor: pointer; + opacity: .75; + &.target-selected { + text-shadow: 0px 0px 4px #CE5937; + opacity: 1; + } + } + } + .target-section { margin-top: 5px; @@ -284,6 +323,10 @@ fieldset.daggerheart.chat { margin-top: 5px; } } + + &:not(.expanded) .dice-tooltip { + grid-template-rows: 0fr; + } } &.domain-card { @@ -337,6 +380,17 @@ fieldset.daggerheart.chat { width: 80px; } } + button { + &.inner-button { + --button-size: 1.25rem; + --input-height: 1.25rem; + padding: 0 0.25rem; + margin: 5px 1px -4px auto; + &.inner-button-right { + margin-left: auto; + } + } + } [data-use-perm='false'] { pointer-events: none; @@ -359,6 +413,11 @@ fieldset.daggerheart.chat { fieldset.daggerheart.chat { border-top-width: 0; display: contents; + legend { + &:before, &:after { + display: none; + } + } } .message-header { color: var(--color-light-3); @@ -434,7 +493,7 @@ fieldset.daggerheart.chat { align-items: end; gap: 0.25rem; .dice { - .dice-rolls { + .dice-rolls.duality { margin-bottom: 0; li { display: flex; @@ -457,6 +516,11 @@ fieldset.daggerheart.chat { } } } + .target-selection { + label { + color: var(--color-light-1); + } + } .target-section { margin: 4px 0; border: 2px solid; @@ -500,6 +564,31 @@ fieldset.daggerheart.chat { margin-right: -8px; } } + .duality-result { + display: flex; + color: var(--color-light-1); + text-shadow: 0 0 1px black; + font-weight: bold; + background: var(--color-dark-1); + padding: 4px; + border-color: black; + min-height: unset; + height: 26px; + flex: unset; + margin: 0; + margin-left: auto; + align-self: center; + border-radius: 6px; + } + } + } + button { + &.inner-button { + color: var(--color-light-1); + text-shadow: 0 0 1px black; + font-weight: bold; + background: var(--color-dark-1); + border-color: black; } } } diff --git a/styles/daggerheart.css b/styles/daggerheart.css index e7b6da48..5cf696a1 100755 --- a/styles/daggerheart.css +++ b/styles/daggerheart.css @@ -1406,6 +1406,23 @@ fieldset.daggerheart.chat { border-right-width: 0; border-bottom-width: 0; } +fieldset.daggerheart.chat legend { + display: flex; + align-items: center; + gap: 5px; +} +fieldset.daggerheart.chat legend:before, +fieldset.daggerheart.chat legend:after { + content: '\f0d8'; + font-family: "Font Awesome 6 Pro"; +} +fieldset.daggerheart.chat.expanded legend:before, +fieldset.daggerheart.chat.expanded legend:after { + content: '\f0d7'; +} +fieldset.daggerheart.chat .daggerheart.chat { + margin-top: 5px; +} .daggerheart.chat.downtime { display: flex; flex-direction: column; @@ -1538,6 +1555,27 @@ fieldset.daggerheart.chat { font-variant: all-small-caps; margin: -8px 0; } +.daggerheart.chat.roll .target-selection { + display: flex; + justify-content: space-around; +} +.daggerheart.chat.roll .target-selection input[type="radio"] { + display: none; +} +.daggerheart.chat.roll .target-selection input[type="radio"]:checked + label { + text-shadow: 0px 0px 4px #CE5937; +} +.daggerheart.chat.roll .target-selection input[type="radio"]:not(:checked) + label { + opacity: 0.75; +} +.daggerheart.chat.roll .target-selection label { + cursor: pointer; + opacity: 0.75; +} +.daggerheart.chat.roll .target-selection label.target-selected { + text-shadow: 0px 0px 4px #CE5937; + opacity: 1; +} .daggerheart.chat.roll .target-section { margin-top: 5px; } @@ -1599,6 +1637,9 @@ fieldset.daggerheart.chat { .daggerheart.chat.roll .dice-result .duality-action { margin-top: 5px; } +.daggerheart.chat.roll:not(.expanded) .dice-tooltip { + grid-template-rows: 0fr; +} .daggerheart.chat.domain-card { display: flex; flex-direction: column; @@ -1642,6 +1683,15 @@ fieldset.daggerheart.chat { .daggerheart.chat.domain-card img { width: 80px; } +.daggerheart.chat button.inner-button { + --button-size: 1.25rem; + --input-height: 1.25rem; + padding: 0 0.25rem; + margin: 5px 1px -4px auto; +} +.daggerheart.chat button.inner-button.inner-button-right { + margin-left: auto; +} .daggerheart.chat [data-use-perm='false'] { pointer-events: none; border-color: transparent; @@ -1660,6 +1710,10 @@ fieldset.daggerheart.chat { border-top-width: 0; display: contents; } +.theme-colorful .chat-message.duality fieldset.daggerheart.chat legend:before, +.theme-colorful .chat-message.duality fieldset.daggerheart.chat legend:after { + display: none; +} .theme-colorful .chat-message.duality .message-header { color: var(--color-light-3); padding: 0 8px; @@ -1732,10 +1786,10 @@ fieldset.daggerheart.chat { align-items: end; gap: 0.25rem; } -.theme-colorful .chat-message.duality .message-content .dice-result .dice-tooltip .wrapper .tooltip-part .dice .dice-rolls { +.theme-colorful .chat-message.duality .message-content .dice-result .dice-tooltip .wrapper .tooltip-part .dice .dice-rolls.duality { margin-bottom: 0; } -.theme-colorful .chat-message.duality .message-content .dice-result .dice-tooltip .wrapper .tooltip-part .dice .dice-rolls li { +.theme-colorful .chat-message.duality .message-content .dice-result .dice-tooltip .wrapper .tooltip-part .dice .dice-rolls.duality li { display: flex; align-items: center; justify-content: center; @@ -1751,6 +1805,9 @@ fieldset.daggerheart.chat { text-shadow: 0 0 1px black; font-size: var(--font-size-16); } +.theme-colorful .chat-message.duality .message-content .dice-result .target-selection label { + color: var(--color-light-1); +} .theme-colorful .chat-message.duality .message-content .dice-result .target-section { margin: 4px 0; border: 2px solid; @@ -1794,6 +1851,29 @@ fieldset.daggerheart.chat { border-radius: 6px 0 0 0; margin-right: -8px; } +.theme-colorful .chat-message.duality .message-content .dice-result .duality-result { + display: flex; + color: var(--color-light-1); + text-shadow: 0 0 1px black; + font-weight: bold; + background: var(--color-dark-1); + padding: 4px; + border-color: black; + min-height: unset; + height: 26px; + flex: unset; + margin: 0; + margin-left: auto; + align-self: center; + border-radius: 6px; +} +.theme-colorful .chat-message.duality button.inner-button { + color: var(--color-light-1); + text-shadow: 0 0 1px black; + font-weight: bold; + background: var(--color-dark-1); + border-color: black; +} .daggerheart.sheet.feature .editable { display: flex; flex-direction: column; diff --git a/templates/chat/adversary-roll.hbs b/templates/chat/adversary-roll.hbs index 92bb1c96..7794d683 100644 --- a/templates/chat/adversary-roll.hbs +++ b/templates/chat/adversary-roll.hbs @@ -31,13 +31,30 @@ +
+ Damage +
+
+
+ {{> 'systems/daggerheart/templates/chat/parts/damage-chat.hbs' damage=damage noTitle=true}} +
+
+
+
{{> 'systems/daggerheart/templates/chat/parts/target-chat.hbs'}} {{#if hasDamage}}
-
- + {{#if damage.roll}} +
+ {{!-- --}} +
+ {{else}} +
+ +
+ {{/if}}
{{/if}} \ No newline at end of file diff --git a/templates/chat/damage-roll.hbs b/templates/chat/damage-roll.hbs index 9442fe5a..2b6452b7 100644 --- a/templates/chat/damage-roll.hbs +++ b/templates/chat/damage-roll.hbs @@ -1,29 +1,4 @@ -
-
{{title}}
-
-
{{roll.formula}}
-
-
-
- {{#each roll.dice}} -
-
- {{formula}} - {{total}} -
-
    - {{#each results}} -
  1. {{result}}
  2. - {{/each}} -
-
- {{/each}} -
-
-
-
{{roll.total}}
-
-
+{{> 'systems/daggerheart/templates/chat/parts/damage-chat.hbs' damage=this}} {{> 'systems/daggerheart/templates/chat/parts/target-chat.hbs'}}
diff --git a/templates/chat/duality-roll.hbs b/templates/chat/duality-roll.hbs index 2d77f815..65ec1676 100644 --- a/templates/chat/duality-roll.hbs +++ b/templates/chat/duality-roll.hbs @@ -94,12 +94,26 @@
+
+ Damage +
+
+
+ {{> 'systems/daggerheart/templates/chat/parts/damage-chat.hbs' damage=damage noTitle=true}} +
+
+
+
{{> 'systems/daggerheart/templates/chat/parts/target-chat.hbs'}}
{{#if hasDamage}} + {{#if damage.roll}} + + {{else}} + {{/if}} {{else}} {{#if hasHealing}} diff --git a/templates/chat/parts/damage-chat.hbs b/templates/chat/parts/damage-chat.hbs new file mode 100644 index 00000000..096f09dc --- /dev/null +++ b/templates/chat/parts/damage-chat.hbs @@ -0,0 +1,27 @@ +
+ {{#unless noTitle}}
{{damage.title}}
{{/unless}} +
+
{{damage.roll.formula}}
+
+
+
+ {{#each damage.roll.dice}} +
+
+ {{formula}} + {{total}} +
+
    + {{#each results}} +
  1. {{result}}
  2. + {{/each}} +
+
+ {{/each}} +
Total: {{damage.roll.total}}
+
+
+
+
{{damage.roll.total}}
+
+
\ No newline at end of file diff --git a/templates/chat/parts/target-chat.hbs b/templates/chat/parts/target-chat.hbs index d2fc81ea..9ac993cc 100644 --- a/templates/chat/parts/target-chat.hbs +++ b/templates/chat/parts/target-chat.hbs @@ -1,22 +1,29 @@ -{{#if (gt targets.length 0)}} +{{#if (gt currentTargets.length 0)}}
Targets
+
+ + +
+ {{#if (and hasSave @root.targetSelection @root.hasHitTarget)}} + + {{/if}}
- {{#each targets as |target|}} + {{#each currentTargets as |target|}}
- {{#if ../directDamage}} + {{#if (or ../directDamage (not @root.targetSelection))}}
{{target.name}}
{{else}} {{#if target.hit}}{{localize "Hit"}}{{else}}{{#if (not ../total.alternate)}}{{localize "Miss"}}{{else}}?{{/if}}{{/if}} {{/if}}
- {{#if ../hasSave}} -