[v14] Add toggle for critical damage (#1762)

* Fix rolling critical damage after rerolling into a crit

* Add toggle for critical damage

---------

Co-authored-by: WBHarry <williambjrklund@gmail.com>
This commit is contained in:
Carlos Fernandez 2026-04-01 13:39:26 -04:00 committed by GitHub
parent e3b433cce9
commit 2b8e4cb2fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 51 additions and 2 deletions

View file

@ -55,6 +55,7 @@
}, },
"damage": { "damage": {
"name": "Damage", "name": "Damage",
"critical": "Damage (Critical)",
"tooltip": "Direct damage without a roll." "tooltip": "Direct damage without a roll."
}, },
"effect": { "effect": {

View file

@ -22,6 +22,7 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application
}, },
actions: { actions: {
toggleSelectedEffect: this.toggleSelectedEffect, toggleSelectedEffect: this.toggleSelectedEffect,
toggleCritical: this.toggleCritical,
submitRoll: this.submitRoll submitRoll: this.submitRoll
}, },
form: { form: {
@ -53,6 +54,7 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application
context.hasHealing = this.config.hasHealing; context.hasHealing = this.config.hasHealing;
context.directDamage = this.config.directDamage; context.directDamage = this.config.directDamage;
context.selectedMessageMode = this.config.selectedMessageMode; context.selectedMessageMode = this.config.selectedMessageMode;
context.isCritical = this.config.isCritical;
context.rollModes = Object.entries(CONFIG.ChatMessage.modes).map(([action, { label, icon }]) => ({ context.rollModes = Object.entries(CONFIG.ChatMessage.modes).map(([action, { label, icon }]) => ({
action, action,
label, label,
@ -74,6 +76,11 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application
this.render(); this.render();
} }
static toggleCritical() {
this.config.isCritical = !this.config.isCritical;
this.render();
}
static toggleSelectedEffect(_event, button) { static toggleSelectedEffect(_event, button) {
this.selectedEffects[button.dataset.key].selected = !this.selectedEffects[button.dataset.key].selected; this.selectedEffects[button.dataset.key].selected = !this.selectedEffects[button.dataset.key].selected;
this.render(); this.render();

View file

@ -7,6 +7,10 @@ export default class DamageRoll extends DHRoll {
super(formula, data, options); super(formula, data, options);
} }
get isCritical() {
return !!this.options.isCritical;
}
static DefaultDialog = DamageDialog; static DefaultDialog = DamageDialog;
static async buildEvaluate(roll, config = {}, message = {}) { static async buildEvaluate(roll, config = {}, message = {}) {
@ -138,6 +142,7 @@ export default class DamageRoll extends DHRoll {
} }
constructFormula(config) { constructFormula(config) {
this.options.isCritical = config.isCritical;
for (const [index, part] of this.options.roll.entries()) { for (const [index, part] of this.options.roll.entries()) {
part.roll = new Roll(Roll.replaceFormulaData(part.formula, config.data)); part.roll = new Roll(Roll.replaceFormulaData(part.formula, config.data));
part.roll.terms = Roll.parse(part.roll.formula, config.data); part.roll.terms = Roll.parse(part.roll.formula, config.data);

View file

@ -17,6 +17,30 @@
} }
} }
.bonuses {
gap: 4px;
.critical-chip {
flex: 0;
display: flex;
align-items: center;
border-radius: 5px;
width: fit-content;
gap: 5px;
cursor: pointer;
padding: 5px;
transition: all 0.3s ease;
background: @green-10;
color: @green;
&.selected {
color: @beige;
background: @gradient-green;
}
}
}
.damage-section-controls { .damage-section-controls {
display: flex; display: flex;
align-items: center; align-items: center;

View file

@ -34,8 +34,12 @@
{{/unless}} {{/unless}}
</span> </span>
</div> </div>
<div class="form-group"> <div class="bonuses form-group flexrow">
<input type="text" value="{{extraFormula}}" name="roll.{{ @index }}.extraFormula" placeholder="Situational Bonus"> <input type="text" value="{{extraFormula}}" name="roll.{{ @index }}.extraFormula" placeholder="Situational Bonus">
<button class="critical-chip" data-action="toggleCritical">
<span><i class="{{#if @root.isCritical}}fa-solid{{else}}fa-regular{{/if}} fa-circle"></i></span>
<span class="label">{{localize "DAGGERHEART.GENERAL.criticalShort"}}</span>
</button>
</div> </div>
{{/each}} {{/each}}
{{#unless (empty @root.modifiers)}} {{#unless (empty @root.modifiers)}}

View file

@ -1,5 +1,13 @@
<div class="roll-part damage-section dice-roll" data-action="expandRoll"{{#if (empty damage)}} hidden{{/if}}> <div class="roll-part damage-section dice-roll" data-action="expandRoll"{{#if (empty damage)}} hidden{{/if}}>
<div class="roll-part-header"><div><span>{{localize (ifThen hasHealing "DAGGERHEART.ACTIONS.TYPES.healing.name" "DAGGERHEART.ACTIONS.TYPES.damage.name")}}</span></div></div> <div class="roll-part-header">
<div>
{{#if hasHealing}}
<span>{{localize "DAGGERHEART.ACTIONS.TYPES.healing.name"}}</span>
{{else}}
<span>{{localize (ifThen roll.isCritical "DAGGERHEART.ACTIONS.TYPES.damage.critical" "DAGGERHEART.ACTIONS.TYPES.damage.name")}}</span>
{{/if}}
</div>
</div>
<div class="roll-part-extra on-reduced"> <div class="roll-part-extra on-reduced">
<div class="wrapper"> <div class="wrapper">
{{#each damage as | roll index | }} {{#each damage as | roll index | }}