Files
DeltaGreen/module/roll/roll-dialogs.js
T
2026-05-29 21:14:23 -07:00

218 lines
5.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { showDgDialog } from "../applications/dg-dialog.js";
import DGUtils from "../utils/utility-functions.js";
const { renderTemplate } = foundry.applications.handlebars;
const PERCENTILE_ROLL_DIALOG_TEMPLATE =
"systems/deltagreen/templates/dialog/modify-percentile-roll.html";
const DAMAGE_ROLL_DIALOG_TEMPLATE =
"systems/deltagreen/templates/dialog/modify-damage-roll.html";
const QUICK_MODIFIER_PRESETS = [
{
action: "modMinus40",
mod: -40,
label: "−40",
explanationKey: "DG.ModifySkillRollDialogue.ModifierMuchHarder",
},
{
action: "modMinus20",
mod: -20,
label: "−20",
explanationKey: "DG.ModifySkillRollDialogue.ModifierHarder",
},
{
action: "modPlus20",
mod: 20,
label: "+20",
explanationKey: "DG.ModifySkillRollDialogue.ModifierEasier",
},
{
action: "modPlus40",
mod: 40,
label: "+40",
explanationKey: "DG.ModifySkillRollDialogue.ModifierMuchEasier",
},
];
/**
* @param {DialogV2} dialog
* @returns {string|undefined}
*/
function readMessageMode(dialog) {
return dialog.element.querySelector("[name='messageMode']")?.value;
}
/**
* @param {object} options
* @param {string} options.label
* @param {number} options.target
* @param {boolean} [options.hideTarget]
* @param {number} [options.defaultModifier]
* @param {Actor|null} [options.actor]
* @returns {Promise<{ targetModifier: number, messageMode?: string }|void>}
*/
export async function showPercentileRollModifyDialog({
label,
target,
targetDisplayClass = "",
hideTarget = false,
defaultModifier = 20,
actor = null,
}) {
const quickModifiers = QUICK_MODIFIER_PRESETS.map((preset) => ({
...preset,
explanation: game.i18n.localize(preset.explanationKey),
}));
const content = await renderTemplate(PERCENTILE_ROLL_DIALOG_TEMPLATE, {
data: {
label,
originalTarget: target,
targetDisplayClass,
targetModifier: defaultModifier,
hideTarget,
},
quickModifiers,
});
/** @type {{ targetModifier: number, messageMode?: string } | null} */
let dialogResult = null;
/**
* @param {DialogV2} dialog
* @param {{ targetModifier: number, messageMode?: string }} result
*/
const resolveAndClose = async (dialog, result) => {
dialogResult = result;
await dialog.close();
return result;
};
// Footer buttons are callback-only; visible controls live in modify-percentile-roll.html.
const hiddenFooterButton = { class: "hidden" };
const presetButtons = QUICK_MODIFIER_PRESETS.map(({ action, mod }) => ({
action,
label: "",
...hiddenFooterButton,
callback: async (_event, _button, dialog) =>
resolveAndClose(dialog, {
targetModifier: mod,
messageMode: readMessageMode(dialog),
}),
}));
return showDgDialog({
modifier: "modify-roll",
content,
form: { closeOnSubmit: false },
position: { width: 420 },
window: {
title: DGUtils.localizeWithFallback(
"DG.ModifySkillRollDialogue.Title",
"Modify Roll",
),
},
close: () => dialogResult,
buttons: [
{
default: true,
action: "roll",
label: "",
...hiddenFooterButton,
callback: async (_event, _button, dialog) => {
const raw =
dialog.element
.querySelector("[name='targetModifier']")
?.value?.trim() ?? "";
const targetModifier = Number(raw);
if (raw === "" || Number.isNaN(targetModifier)) {
ui.notifications.warn(
DGUtils.localizeWithFallback(
"DG.ModifySkillRollDialogue.InvalidModifier",
"Enter a valid modifier to roll.",
),
);
return false;
}
if (actor != null) {
await actor.update({
"system.settings.rolling.defaultPercentileModifier":
targetModifier,
});
}
return resolveAndClose(dialog, {
targetModifier,
messageMode: readMessageMode(dialog),
});
},
},
...presetButtons,
],
});
}
/**
* @param {object} options
* @param {string} [options.itemName]
* @param {string} options.formula
* @returns {Promise<{ newFormula: string, messageMode?: string }|void>}
*/
export async function showDamageRollModifyDialog({ itemName, formula }) {
const content = await renderTemplate(DAMAGE_ROLL_DIALOG_TEMPLATE, {
data: {
label: itemName,
originalFormula: formula,
outerModifier: "2 * ",
innerModifier: "+ 0",
},
});
return showDgDialog({
modifier: "modify-damage-roll",
content,
window: {
title: game.i18n.localize("DG.ModifySkillRollDialogue.Title"),
},
close: () => null,
buttons: [
{
default: true,
label: game.i18n.translations.DG.Roll.Roll,
action: "roll",
callback: (_event, _button, dialog) => {
const outerModifier = dialog.element.querySelector(
"[name='outerModifier']",
)?.value;
let innerModifier = dialog.element.querySelector(
"[name='innerModifier']",
)?.value;
const modifiedBaseRoll = dialog.element.querySelector(
"[name='originalFormula']",
)?.value;
const messageMode = dialog.element.querySelector(
"[name='targetRollMode']",
)?.value;
if (innerModifier.replace(" ", "") === "+0") {
innerModifier = "";
}
let newFormula = "";
if (outerModifier.trim() !== "") {
newFormula += `${outerModifier}(${modifiedBaseRoll}${innerModifier.trim()})`;
} else {
newFormula += modifiedBaseRoll + innerModifier.trim();
}
return { newFormula, messageMode };
},
},
],
});
}