Fixed rerolling of duality dice

This commit is contained in:
WBHarry 2025-07-22 19:54:23 +02:00
parent 480d04fee5
commit dfd10da324
9 changed files with 93 additions and 54 deletions

View file

@ -2,14 +2,14 @@ import { SYSTEM } from './module/config/system.mjs';
import * as applications from './module/applications/_module.mjs'; import * as applications from './module/applications/_module.mjs';
import * as models from './module/data/_module.mjs'; import * as models from './module/data/_module.mjs';
import * as documents from './module/documents/_module.mjs'; import * as documents from './module/documents/_module.mjs';
import * as dice from './module/dice/_module.mjs';
import RegisterHandlebarsHelpers from './module/helpers/handlebarsHelper.mjs'; import RegisterHandlebarsHelpers from './module/helpers/handlebarsHelper.mjs';
import { enricherConfig, enricherRenderSetup } from './module/enrichers/_module.mjs'; import { enricherConfig, enricherRenderSetup } from './module/enrichers/_module.mjs';
import { getCommandTarget, rollCommandToJSON } from './module/helpers/utils.mjs'; import { getCommandTarget, rollCommandToJSON } from './module/helpers/utils.mjs';
import { NarrativeCountdowns } from './module/applications/ui/countdowns.mjs'; import { NarrativeCountdowns } from './module/applications/ui/countdowns.mjs';
import { DualityRollColor } from './module/data/settings/Appearance.mjs'; import { DualityRollColor } from './module/data/settings/Appearance.mjs';
import { DHRoll, DualityRoll, D20Roll, DamageRoll, DualityDie } from './module/dice/_module.mjs'; import { DHRoll, DualityRoll, D20Roll, DamageRoll, DualityDie } from './module/dice/_module.mjs';
import { enrichedDualityRoll, renderDualityButton } from './module/enrichers/DualityRollEnricher.mjs'; import { enrichedDualityRoll } from './module/enrichers/DualityRollEnricher.mjs';
import { renderMeasuredTemplate } from './module/enrichers/TemplateEnricher.mjs';
import { registerCountdownHooks } from './module/data/countdowns.mjs'; import { registerCountdownHooks } from './module/data/countdowns.mjs';
import { import {
handlebarsRegistration, handlebarsRegistration,
@ -20,14 +20,14 @@ import { placeables } from './module/canvas/_module.mjs';
import { registerRollDiceHooks } from './module/dice/dhRoll.mjs'; import { registerRollDiceHooks } from './module/dice/dhRoll.mjs';
import { registerDHActorHooks } from './module/documents/actor.mjs'; import { registerDHActorHooks } from './module/documents/actor.mjs';
import './node_modules/@yaireo/tagify/dist/tagify.css'; import './node_modules/@yaireo/tagify/dist/tagify.css';
import { renderDamageButton } from './module/enrichers/DamageEnricher.mjs';
Hooks.once('init', () => { Hooks.once('init', () => {
CONFIG.DH = SYSTEM; CONFIG.DH = SYSTEM;
game.system.api = { game.system.api = {
applications, applications,
models, models,
documents documents,
dice
}; };
CONFIG.TextEditor.enrichers.push(...enricherConfig); CONFIG.TextEditor.enrichers.push(...enricherConfig);
@ -49,6 +49,11 @@ Hooks.once('init', () => {
DamageRoll: DamageRoll DamageRoll: DamageRoll
}; };
CONFIG.Dice.terms = {
...CONFIG.Dice.terms,
DualityDie
};
CONFIG.Dice.rolls = [...CONFIG.Dice.rolls, ...[DHRoll, DualityRoll, D20Roll, DamageRoll]]; CONFIG.Dice.rolls = [...CONFIG.Dice.rolls, ...[DHRoll, DualityRoll, D20Roll, DamageRoll]];
CONFIG.MeasuredTemplate.objectClass = placeables.DhMeasuredTemplate; CONFIG.MeasuredTemplate.objectClass = placeables.DhMeasuredTemplate;

View file

@ -1339,6 +1339,7 @@
"quantity": "Quantity", "quantity": "Quantity",
"range": "Range", "range": "Range",
"recovery": "Recovery", "recovery": "Recovery",
"rerollThing": "Reroll {thing}",
"resource": "Resource", "resource": "Resource",
"roll": "Roll", "roll": "Roll",
"rollAll": "Roll All", "rollAll": "Roll All",

View file

@ -1,3 +1,5 @@
import { getDiceSoNicePresets } from '../../config/generalConfig.mjs';
export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLog { export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLog {
constructor(options) { constructor(options) {
super(options); super(options);
@ -313,47 +315,50 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
action.use(event); action.use(event);
}; };
//Reroll Functionality
rerollEvent = async (event, message) => { rerollEvent = async (event, message) => {
let DieTerm = foundry.dice.terms.Die; const target = event.target.closest('button[data-die-index]');
let dicetype = event.target.value;
let originalRoll_parsed = message.rolls.map(roll => JSON.parse(roll))[0]; let originalRoll_parsed = message.rolls.map(roll => JSON.parse(roll))[0];
console.log('Parsed Map:', originalRoll_parsed); let parsedRoll = game.system.api.dice.DualityRoll.fromData({ ...originalRoll_parsed, evaluated: false });
let originalRoll = Roll.fromData(originalRoll_parsed); const term = parsedRoll.terms[target.dataset.dieIndex];
let diceIndex; await term.reroll(`/r1=${term.total}`);
console.log('Dice to reroll is:', dicetype, ', and the message id is:', message._id, originalRoll_parsed); if (game.modules.get('dice-so-nice')?.active) {
console.log('Original Roll Terms:', originalRoll.terms); const diceSoNiceRoll = {
switch (dicetype) { _evaluated: true,
case 'hope': { dice: [new Die({ ...term, faces: term._faces, results: term.results.filter(x => !x.rerolled) })],
diceIndex = 0; //Hope Die options: { appearance: {} }
};
const diceSoNicePresets = getDiceSoNicePresets();
switch (target.dataset.type) {
case 'hope':
diceSoNiceRoll.dice[0].options = { appearance: diceSoNicePresets.hope };
break;
case 'fear':
diceSoNiceRoll.dice[0].options = { appearance: diceSoNicePresets.fear };
break;
case 'advantage':
diceSoNiceRoll.dice[0].options = { appearance: diceSoNicePresets.advantage };
break;
case 'disadvantage':
diceSoNiceRoll.dice[0].options = { appearance: diceSoNicePresets.disadvantage };
break; break;
} }
case 'fear': {
diceIndex = 2; //Fear Die await game.dice3d.showForRoll(diceSoNiceRoll, game.user, true);
break;
} }
default:
ui.notifications.warn('Invalid Dice type selected.'); await parsedRoll.evaluate();
break;
const newRoll = game.system.api.dice.DualityRoll.postEvaluate(parsedRoll, {
targets: message.system.targets,
roll: {
advantage: message.system.roll.advantage?.type,
difficulty: message.system.roll.difficulty ? Number(message.system.roll.difficulty) : null
} }
let rollClone = originalRoll.clone();
let rerolledTerm = originalRoll.terms[diceIndex];
console.log('originalRoll:', originalRoll, 'rerolledTerm', rerolledTerm);
if (!(rerolledTerm instanceof DieTerm)) {
ui.notifications.error('Selected term is not a die.');
return;
}
await rollClone.reroll({ allowStrings: true })[diceIndex];
console.log(rollClone);
await rollClone.evaluate({ allowStrings: true });
console.log(rollClone.result);
/*
const confirm = await foundry.applications.api.DialogV2.confirm({
window: { title: 'Confirm Reroll' },
content: `<p>You have rerolled your <strong>${dicetype}</strong> die to <strong>${rollClone.result}</strong>.</p><p>Apply this new roll?</p>`
}); });
if (!confirm) return; newRoll.extra = newRoll.extra.slice(2);
rollClone.toMessage({flavor: 'Selective reroll applied for ${dicetype}.'});
console.log("Updated Roll",rollClone);*/ await game.messages.get(message._id).update({
'system.roll': newRoll
});
}; };
} }

View file

@ -6,7 +6,7 @@ export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel {
static defineSchema() { static defineSchema() {
return { return {
title: new fields.StringField(), title: new fields.StringField(),
roll: new fields.DataField(), roll: new fields.ObjectField(),
targets: new fields.ArrayField( targets: new fields.ArrayField(
new fields.SchemaField({ new fields.SchemaField({
id: new fields.StringField({}), id: new fields.StringField({}),

View file

@ -147,7 +147,10 @@ export default class D20Roll extends DHRoll {
const difficulty = config.roll.difficulty ?? target.difficulty ?? target.evasion; const difficulty = config.roll.difficulty ?? target.difficulty ?? target.evasion;
target.hit = this.isCritical || roll.total >= difficulty; target.hit = this.isCritical || roll.total >= difficulty;
}); });
} else if (config.roll.difficulty) data.success = roll.isCritical || roll.total >= config.roll.difficulty; } else if (config.roll.difficulty) {
data.difficulty = config.roll.difficulty;
data.success = roll.isCritical || roll.total >= config.roll.difficulty;
}
data.advantage = { data.advantage = {
type: config.roll.advantage, type: config.roll.advantage,
dice: roll.dAdvantage?.denomination, dice: roll.dAdvantage?.denomination,

View file

@ -110,6 +110,13 @@ export default class DualityRoll extends D20Roll {
return [...(hooks ?? []), 'Duality']; return [...(hooks ?? []), 'Duality'];
} }
/** @inheritDoc */
static fromData(data) {
data.terms[0].class = game.system.api.dice.DualityDie.name;
data.terms[2].class = game.system.api.dice.DualityDie.name;
return super.fromData(data);
}
createBaseDice() { createBaseDice() {
if ( if (
this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie && this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie &&

View file

@ -48,7 +48,7 @@ function getDualityMessage(roll) {
> >
<i class="fa-solid fa-circle-half-stroke"></i> <i class="fa-solid fa-circle-half-stroke"></i>
${label} ${label}
${roll.difficulty || advantageLabel ? `(${[roll.difficulty, game.i18n.localize(`DAGGERHEART.GENERAL.${advantageLabel}.short`)].filter(x => x).join(' ')})` : ''} ${roll.difficulty || advantageLabel ? `(${[roll.difficulty, advantageLabel ? game.i18n.localize(`DAGGERHEART.GENERAL.${advantageLabel}.short`) : null].filter(x => x).join(' ')})` : ''}
</button> </button>
`; `;

View file

@ -44,6 +44,21 @@
&.duality { &.duality {
display: flex; display: flex;
gap: 0.25rem; 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);
}
}
}
} }
// margin: 0; // margin: 0;
> .roll { > .roll {
@ -52,6 +67,7 @@
justify-content: center; justify-content: center;
gap: 4px; gap: 4px;
margin-bottom: 4px; margin-bottom: 4px;
.dice-container { .dice-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View file

@ -38,11 +38,11 @@
</header> </header>
<div class="flexrow"> <div class="flexrow">
<ol class="dice-rolls duality"> <ol class="dice-rolls duality">
<li class="roll die {{roll.hope.dice}}" title="{{localize "DAGGERHEART.GENERAL.hope"}}"> <li class="roll die {{roll.hope.dice}}">
<div class="dice-container"> <div class="dice-container">
<div class="dice-title">{{localize "DAGGERHEART.GENERAL.hope"}}</div> <div class="dice-title">{{localize "DAGGERHEART.GENERAL.hope"}}</div>
<div class="dice-inner-container hope" title="{{localize "DAGGERHEART.GENERAL.hope"}}">s <div class="dice-inner-container hope" data-tooltip="{{localize "DAGGERHEART.GENERAL.rerollThing" thing=(localize "DAGGERHEART.GENERAL.hope")}}">
<button type="checkbox" class="reroll-button" id="reroll-dice" value="hope"> <button type="checkbox" class="reroll-button" data-die-index="0" data-type="hope">
<div class="dice-wrapper"> <div class="dice-wrapper">
<img class="dice" src="../icons/svg/{{roll.hope.dice}}-grey.svg"/> <img class="dice" src="../icons/svg/{{roll.hope.dice}}-grey.svg"/>
</div> </div>
@ -51,14 +51,16 @@
</div> </div>
</div> </div>
</li> </li>
<li class="roll die {{roll.fear.dice}}" title="{{localize "DAGGERHEART.GENERAL.fear"}}"> <li class="roll die {{roll.fear.dice}}">
<div class="dice-container"> <div class="dice-container">
<div class="dice-title">{{localize "DAGGERHEART.GENERAL.fear"}}</div> <div class="dice-title">{{localize "DAGGERHEART.GENERAL.fear"}}</div>
<div class="dice-inner-container fear" title="{{localize "DAGGERHEART.GENERAL.fear"}}"> <div class="dice-inner-container fear" data-tooltip="{{localize "DAGGERHEART.GENERAL.rerollThing" thing=(localize "DAGGERHEART.GENERAL.fear")}}">
<button type="checkbox" class="reroll-button" data-die-index="2" data-type="fear">
<div class="dice-wrapper"> <div class="dice-wrapper">
<img class="dice" src="../icons/svg/{{roll.fear.dice}}-grey.svg"/> <img class="dice" src="../icons/svg/{{roll.fear.dice}}-grey.svg"/>
</div> </div>
<div class="dice-value">{{roll.fear.value}}</div> <div class="dice-value">{{roll.fear.value}}</div>
</button>
</div> </div>
</div> </div>
</li> </li>