From 5a501d67695b2396c980141ea4594fd06e77b874 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Sat, 24 May 2025 16:56:01 +0200 Subject: [PATCH] Fixed Check Rolls, Attack Rolls and Damage Rolls for PCs --- lang/en.json | 6 +- module/applications/sheets/adversary.mjs | 1 + module/applications/sheets/pc.mjs | 16 +++- module/data/adversaryRoll.mjs | 36 +++++--- module/data/damageRoll.mjs | 1 + module/data/dualityRoll.mjs | 18 +++- module/documents/actor.mjs | 10 +-- module/ui/chatLog.mjs | 1 + styles/chat.less | 11 ++- styles/daggerheart.css | 11 ++- templates/chat/adversary-attack-roll.hbs | 5 +- templates/chat/attack-roll.hbs | 77 +++++++++++------ templates/chat/damage-roll.hbs | 1 + templates/chat/duality-roll.hbs | 101 +++++++++++++---------- templates/sheets/adversary.hbs | 2 +- templates/sheets/parts/attributes.hbs | 2 +- 16 files changed, 204 insertions(+), 95 deletions(-) diff --git a/lang/en.json b/lang/en.json index 497a8003..a99266ed 100644 --- a/lang/en.json +++ b/lang/en.json @@ -735,9 +735,13 @@ }, "Chat": { "DualityRoll": { - "AdvantageChooseTitle": "Select Hope Dice" + "AbilityCheckTitle": "{ability} Check" + }, + "AttackRoll": { + "Title": "Attack - {attack}" }, "DamageRoll": { + "Title": "Damage - {damage}", "DealDamageToTargets": "Damage Hit Targets", "DealDamage": "Deal Damage" }, diff --git a/module/applications/sheets/adversary.mjs b/module/applications/sheets/adversary.mjs index c1637dc9..9066e194 100644 --- a/module/applications/sheets/adversary.mjs +++ b/module/applications/sheets/adversary.mjs @@ -367,6 +367,7 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) { type: 'adversaryRoll', sound: CONFIG.sounds.dice, system: { + title: button.dataset.name, origin: this.document.id, roll: roll._formula, advantageState, diff --git a/module/applications/sheets/pc.mjs b/module/applications/sheets/pc.mjs index 8112a697..36d8b49b 100644 --- a/module/applications/sheets/pc.mjs +++ b/module/applications/sheets/pc.mjs @@ -4,6 +4,7 @@ import DhpDowntime from '../downtime.mjs'; import DhpLevelup from '../levelup.mjs'; import AncestrySelectionDialog from '../ancestrySelectionDialog.mjs'; import DaggerheartSheet from './daggerheart-sheet.mjs'; +import { abilities } from '../../config/actorConfig.mjs'; const { ActorSheetV2 } = foundry.applications.sheets; export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { @@ -480,9 +481,9 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { this.render(); } - static async rollAttribute(event, target) { + static async rollAttribute(event, button) { const { roll, hope, fear, advantage, disadvantage, modifiers } = await this.document.dualityRoll( - { title: 'Attribute Bonus', value: event.target.dataset.value }, + { title: 'Attribute Bonus', value: button.dataset.value }, event.shiftKey ); @@ -490,6 +491,10 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { const msgData = { type: 'dualityRoll', 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, @@ -550,8 +555,8 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { await this.document.update({ [update]: newValue }); } - static async attackRoll(_, event) { - const weapon = await fromUuid(event.currentTarget.dataset.weapon); + static async attackRoll(event, button) { + const weapon = await fromUuid(button.dataset.weapon); const damage = { value: `${this.document.system.proficiency.value}${weapon.system.damage.value}`, type: weapon.system.damage.type, @@ -579,7 +584,10 @@ export default class PCSheet extends DaggerheartSheet(ActorSheetV2) { 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, diff --git a/module/data/adversaryRoll.mjs b/module/data/adversaryRoll.mjs index 3619b143..e7086c55 100644 --- a/module/data/adversaryRoll.mjs +++ b/module/data/adversaryRoll.mjs @@ -3,6 +3,7 @@ export default class DhpAdversaryRoll extends foundry.abstract.TypeDataModel { const fields = foundry.data.fields; return { + title: new fields.StringField(), origin: new fields.StringField({ required: true }), roll: new fields.StringField({}), total: new fields.NumberField({ integer: true }), @@ -37,18 +38,31 @@ export default class DhpAdversaryRoll extends foundry.abstract.TypeDataModel { prepareDerivedData() { const diceKeys = Object.keys(this.dice.rolls); - const highestIndex = 0; - for (var index in diceKeys) { - const resultIndex = Number.parseInt(index); - if (highestIndex === resultIndex) continue; - - const current = this.dice.rolls[resultIndex]; - const highest = this.dice.rolls[highestIndex]; - - if (current.value > highest.value) this.dice.rolls[highestIndex].discarded = true; - else this.dice.rolls[resultIndex].discarded = true; + const highestDiceIndex = + diceKeys.length < 2 + ? null + : this.dice.rolls[diceKeys[0]].value > this.dice.rolls[diceKeys[1]].value + ? 0 + : 1; + if (highestDiceIndex !== null) { + this.dice.rolls = this.dice.rolls.map((roll, index) => ({ + ...roll, + discarded: this.advantageState === 1 ? index !== highestDiceIndex : index === highestDiceIndex + })); } + // const highestIndex = 0; + // for (var index in diceKeys) { + // const resultIndex = Number.parseInt(index); + // if (highestIndex === resultIndex) continue; + + // const current = this.dice.rolls[resultIndex]; + // const highest = this.dice.rolls[highestIndex]; + + // if (current.value > highest.value) this.dice.rolls[highestIndex].discarded = true; + // else this.dice.rolls[resultIndex].discarded = true; + // } + this.targets.forEach(target => { target.hit = target.difficulty ? this.total >= target.difficulty : this.total >= target.evasion; }); @@ -71,6 +85,6 @@ class DhpAdversaryRollDice extends foundry.abstract.DataModel { } get rollTotal() { - return this.rolls.reduce((acc, roll) => acc + roll.value, 0); + return this.rolls.reduce((acc, roll) => acc + (!roll.discarded ? roll.value : 0), 0); } } diff --git a/module/data/damageRoll.mjs b/module/data/damageRoll.mjs index c44819c5..20392b35 100644 --- a/module/data/damageRoll.mjs +++ b/module/data/damageRoll.mjs @@ -3,6 +3,7 @@ export default class DhpDamageRoll extends foundry.abstract.TypeDataModel { const fields = foundry.data.fields; return { + title: new fields.StringField(), roll: new fields.StringField({ required: true }), damage: new fields.SchemaField({ total: new fields.NumberField({ required: true, integer: true }), diff --git a/module/data/dualityRoll.mjs b/module/data/dualityRoll.mjs index d6c4471c..d071f84f 100644 --- a/module/data/dualityRoll.mjs +++ b/module/data/dualityRoll.mjs @@ -8,6 +8,8 @@ const diceField = () => export default class DhpDualityRoll extends foundry.abstract.TypeDataModel { static defineSchema() { return { + title: new fields.StringField(), + origin: new fields.StringField({ required: true }), roll: new fields.StringField({}), modifiers: new fields.ArrayField( new fields.SchemaField({ @@ -20,7 +22,6 @@ export default class DhpDualityRoll extends foundry.abstract.TypeDataModel { fear: diceField(), advantage: diceField(), disadvantage: diceField(), - advantageSelected: new fields.NumberField({ initial: 0 }), targets: new fields.ArrayField( new fields.SchemaField({ id: new fields.StringField({}), @@ -57,8 +58,16 @@ export default class DhpDualityRoll extends foundry.abstract.TypeDataModel { get total() { const modifiers = this.modifiers.reduce((acc, x) => acc + x.value, 0); - const advantage = (this.advantage.value ?? this.disadvantage.value) ? -this.disadvantage.value : 0; - return this.hope.value + this.fear.value + advantage + modifiers; + const advantage = this.advantage.value + ? this.advantage.value + : this.disadvantage.value + ? -this.disadvantage.value + : 0; + return this.highestRoll + advantage + modifiers; + } + + get highestRoll() { + return Math.max(this.hope.value, this.fear.value); } get totalLabel() { @@ -75,6 +84,9 @@ export default class DhpDualityRoll extends foundry.abstract.TypeDataModel { prepareDerivedData() { const total = this.total; + this.hope.discarded = this.hope.value < this.fear.value; + this.fear.discarded = this.fear.value < this.hope.value; + this.targets.forEach(target => { target.hit = target.difficulty ? total >= target.difficulty : total >= target.evasion; }); diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 5c9429f9..2da03417 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -207,10 +207,9 @@ export default class DhpActor extends Actor { } const hope = rollResult.dice[0].results[0].result; - const advantage = advantageDice ? rollResult.dice[1].results[0].result : null; - const disadvantage = disadvantageDice ? rollResult.dice[1].results[0].result : null; - const fear = - advantage || disadvantage ? rollResult.dice[2].results[0].result : rollResult.dice[1].results[0].result; + const fear = rollResult.dice[1].results[0].result; + const advantage = advantageDice ? rollResult.dice[2].results[0].result : null; + const disadvantage = disadvantageDice ? rollResult.dice[2].results[0].result : null; if (disadvantage) { rollResult = { ...rollResult, total: rollResult.total - Math.max(hope, disadvantage) }; @@ -250,7 +249,7 @@ export default class DhpActor extends Actor { }; } - async damageRoll(damage, targets, shiftKey) { + async damageRoll(title, damage, targets, shiftKey) { let rollString = damage.value; let bonusDamage = damage.bonusDamage?.filter(x => x.initiallySelected) ?? []; if (!shiftKey) { @@ -291,6 +290,7 @@ export default class DhpActor extends Actor { 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, diff --git a/module/ui/chatLog.mjs b/module/ui/chatLog.mjs index e6553e3c..ec5e257f 100644 --- a/module/ui/chatLog.mjs +++ b/module/ui/chatLog.mjs @@ -55,6 +55,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo if (!actor || !game.user.isGM) return true; await actor.damageRoll( + message.system.title, message.system.damage, message.system.targets.filter(x => x.hit).map(x => ({ id: x.id, name: x.name, img: x.img })), event.shiftKey diff --git a/styles/chat.less b/styles/chat.less index e39fbc2e..1494966c 100644 --- a/styles/chat.less +++ b/styles/chat.less @@ -29,11 +29,14 @@ } &.roll { + .dice-flavor { + text-align: center; + font-weight: bold; + } .dice-tooltip { .dice-rolls.duality { display: flex; align-items: center; - justify-content: space-around; .dice-hope-container { display: flex; @@ -57,12 +60,18 @@ -webkit-text-stroke-color: @hope; -webkit-text-stroke-width: 1.5px; font-weight: 400; + &:not(.discarded) { + filter: none; + } } &.fear { color: white; -webkit-text-stroke-color: @fear; -webkit-text-stroke-width: 1.5px; font-weight: 400; + &:not(.discarded) { + filter: none; + } } &.disadvantage { color: white; diff --git a/styles/daggerheart.css b/styles/daggerheart.css index 745fee57..83bc6ee9 100644 --- a/styles/daggerheart.css +++ b/styles/daggerheart.css @@ -1760,10 +1760,13 @@ .daggerheart.chat.downtime .downtime-refresh-container .refresh-title { font-weight: bold; } +.daggerheart.chat.roll .dice-flavor { + text-align: center; + font-weight: bold; +} .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality { display: flex; align-items: center; - justify-content: space-around; } .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .dice-hope-container { display: flex; @@ -1783,12 +1786,18 @@ -webkit-text-stroke-width: 1.5px; font-weight: 400; } +.daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .roll.die.hope:not(.discarded) { + filter: none; +} .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .roll.die.fear { color: white; -webkit-text-stroke-color: #430070; -webkit-text-stroke-width: 1.5px; font-weight: 400; } +.daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .roll.die.fear:not(.discarded) { + filter: none; +} .daggerheart.chat.roll .dice-tooltip .dice-rolls.duality .roll.die.disadvantage { color: white; -webkit-text-stroke-color: #b30000; diff --git a/templates/chat/adversary-attack-roll.hbs b/templates/chat/adversary-attack-roll.hbs index 2951c803..3e805de9 100644 --- a/templates/chat/adversary-attack-roll.hbs +++ b/templates/chat/adversary-attack-roll.hbs @@ -1,4 +1,5 @@
+
{{localize "DAGGERHEART.Chat.AttackRoll.Title" attack=this.title}}
{{roll}}
@@ -7,7 +8,7 @@
{{this.dice.rolls.length}}{{this.dice.type}} - {{this.total}} + {{this.dice.rollTotal}}
    @@ -23,7 +24,7 @@
-
{{total}}
+
{{this.total}}
{{#if (gt targets.length 0)}}
diff --git a/templates/chat/attack-roll.hbs b/templates/chat/attack-roll.hbs index a32a111f..8a80b103 100644 --- a/templates/chat/attack-roll.hbs +++ b/templates/chat/attack-roll.hbs @@ -1,35 +1,64 @@ -
+
+
{{localize "DAGGERHEART.Chat.AttackRoll.Title" attack=this.title}}
{{roll}}
-
-
    -
    -
  1. {{hope.value}}
  2. + +
    +
    +
    +
    +
    + + 1{{hope.dice}} + | + 1{{fear.dice}} + + {{this.highestRoll}} +
    +
    +
      +
    1. {{hope.value}}
    2. +
    3. {{fear.value}}
    4. +
    +
    +
    {{#if advantage.value}} -
  3. {{ advantage.value}}
  4. +
    +
    + + 1{{advantage.dice}} + + {{advantage.value}} +
    +
    +
      +
    1. {{advantage.value}}
    2. +
    +
    +
    {{/if}} {{#if disadvantage.value}} -
  5. {{disadvantage.value}}
  6. +
    +
    + + 1{{disadvantage.dice}} + + {{disadvantage.value}} +
    +
    +
      +
    1. {{disadvantage.value}}
    2. +
    +
    +
    {{/if}} -
    -
  7. {{fear.value}}
  8. -
    - {{#each modifiers}} -
  9. {{this.label}}
  10. - {{/each}} -
    -
+ +
{{totalLabel}}
- {{#if total.alternate}} - {{#with dualityDiceStates}} - {{../total.normal}} - {{../total.alternate}} - {{/with}} - {{else}} - {{total.normal}} - {{/if}} + {{this.total}}
{{#if (gt targets.length 0)}} @@ -44,6 +73,8 @@ {{/each}}
{{/if}} - +
+ +
\ No newline at end of file diff --git a/templates/chat/damage-roll.hbs b/templates/chat/damage-roll.hbs index 81ea7c7a..9097331d 100644 --- a/templates/chat/damage-roll.hbs +++ b/templates/chat/damage-roll.hbs @@ -1,4 +1,5 @@
+
{{this.title}}
{{this.roll}}
diff --git a/templates/chat/duality-roll.hbs b/templates/chat/duality-roll.hbs index 8a6f6809..eed124ff 100644 --- a/templates/chat/duality-roll.hbs +++ b/templates/chat/duality-roll.hbs @@ -1,7 +1,62 @@ -
+
+
{{this.title}}
{{roll}}
-
+ +
+
+
+
+
+ + 1{{hope.dice}} + | + 1{{fear.dice}} + + {{this.highestRoll}} +
+
+
    +
  1. {{hope.value}}
  2. +
  3. {{fear.value}}
  4. +
+
+
+ {{#if advantage.value}} +
+
+ + 1{{advantage.dice}} + + {{advantage.value}} +
+
+
    +
  1. {{advantage.value}}
  2. +
+
+
+ {{/if}} + {{#if disadvantage.value}} +
+
+ + 1{{disadvantage.dice}} + + {{disadvantage.value}} +
+
+
    +
  1. {{disadvantage.value}}
  2. +
+
+
+ {{/if}} +
+
+
+ + {{!--
  1. {{hope.value}}
  2. @@ -19,7 +74,7 @@ {{/each}}
-
+
--}}
{{totalLabel}}
@@ -27,42 +82,4 @@
-
- -{{!-- V1.3 --}} -{{!--
-
-
{{roll}}
-
-
    -
    -
  1. {{hope.value}}
  2. - {{#if advantage.value}} -
  3. {{ advantage.value}}
  4. - {{/if}} - {{#if disadvantage.value}} -
  5. {{disadvantage.value}}
  6. - {{/if}} -
    -
  7. {{fear.value}}
  8. -
    - {{#each modifiers}} -
  9. {{this.label}}
  10. - {{/each}} -
    -
-
-
-
{{totalLabel}}
-
- {{#if total.alternate}} - {{#with dualityDiceStates}} - {{../total.normal}} - {{../total.alternate}} - {{/with}} - {{else}} - {{total.normal}} - {{/if}} -
-
-
-
--}} \ No newline at end of file +
\ No newline at end of file diff --git a/templates/sheets/adversary.hbs b/templates/sheets/adversary.hbs index 0f6fd81c..a9c5619f 100644 --- a/templates/sheets/adversary.hbs +++ b/templates/sheets/adversary.hbs @@ -175,7 +175,7 @@
+{{this.data.attack.attackModifier}} - +
diff --git a/templates/sheets/parts/attributes.hbs b/templates/sheets/parts/attributes.hbs index 77d0248a..46a15317 100644 --- a/templates/sheets/parts/attributes.hbs +++ b/templates/sheets/parts/attributes.hbs @@ -7,7 +7,7 @@ {{#each this.attributes as |attribute key|}}
- +
{{key}}