Merge pull request #225 from reyzor1991/dialogv2-skill-improvement

use DialogV2 for SkillImprovements
This commit is contained in:
Jalen
2025-08-06 00:45:14 -04:00
committed by GitHub
7 changed files with 207 additions and 174 deletions
+13 -3
View File
@@ -8,9 +8,19 @@
grid-gap: 10px 15px;
}
.numeric-label-field {
width: 50px !important;
text-align: center !important;
.plusMinusNumberFieldBox {
display: flex;
gap: 10px;
select[name="plusOrMinus"] {
flex: 1;
}
.numeric-label-field {
flex: 1;
text-align: center !important;
}
}
.damage-modify-label-grid {
+2
View File
@@ -192,6 +192,8 @@
"DG.Mental.Motivations": "Motivation",
"DG.Mental.Disorders": "Disorder",
"DG.Gear.WeaponTypes.Firearms": "Firearms",
"DG.Gear.WeaponTypes.Melee": "Melee",
"DG.Gear.Weapons": "WEAPONS",
"DG.Gear.Armor": "ARMOR",
"DG.Gear.OtherGear": "OTHER GEAR",
+11 -8
View File
@@ -656,21 +656,24 @@ async function GetUserInput() {
</div>
</form>`;
new Dialog({
title: "Stat Block Parser",
new foundry.applications.api.DialogV2({
window: { title: "Stat Block Parser" },
content,
buttons: {
roll: {
buttons: [
{
label: "PARSE",
callback: async (html) => {
const textInput = html.find("[name=parse-input]")[0].value;
action: "roll",
callback: (event, button, dialog) => {
const textInput =
dialog.element.querySelector("[name=parse-input]")?.value;
const actorType = html.find("[name=actor-type]")[0].value;
const actorType =
dialog.element.querySelector("[name=actor-type]")?.value;
RegexParseNpcStatBlock(textInput, actorType);
},
},
},
],
}).render(true);
}
+108 -109
View File
@@ -3,6 +3,7 @@ import DGUtils from "../other/utility-functions.js";
import DG from "../config.js";
const { renderTemplate } = foundry.applications.handlebars;
const { DialogV2 } = foundry.applications.api;
export class DGRoll extends Roll {
/**
@@ -142,7 +143,9 @@ export class DGPercentileRoll extends DGRoll {
customModifierTarget = parseInt(
this.actor.system.settings.rolling.defaultPercentileModifier,
);
} catch {}
} catch {
/* empty */
}
}
const backingData = {
@@ -158,23 +161,48 @@ export class DGPercentileRoll extends DGRoll {
"systems/deltagreen/templates/dialog/modify-percentile-roll.html";
const content = await renderTemplate(template, backingData);
return new Promise((resolve, reject) => {
new Dialog({
const modButtons = [-40, -20, 20, 40].map((mod) => {
const sign = mod > 0 ? "Positive" : "Negative";
return {
action: `roll${Math.abs(mod)}${sign}`,
label: String(mod),
callback: (event, button, dialog) => {
try {
const rollMode =
dialog.element.querySelector("[name='rollMode']")?.value;
resolve({ targetModifier: mod, rollMode });
} catch (ex) {
reject(console.log(ex));
}
},
};
});
new DialogV2({
content,
title: DGUtils.localizeWithFallback(
"DG.ModifySkillRollDialogue.Title",
"Modify Roll",
),
default: "roll",
buttons: {
roll: {
window: {
title: DGUtils.localizeWithFallback(
"DG.ModifySkillRollDialogue.Title",
"Modify Roll",
),
},
buttons: [
{
default: true,
action: "roll",
label: DGUtils.localizeWithFallback("DG.Roll.Roll", "Roll"),
callback: (html) => {
callback: (event, button, dialog) => {
try {
let targetModifier = html.find("[name='targetModifier']").val(); // this is text as a heads up
let targetModifier = dialog.element.querySelector(
"[name='targetModifier']",
)?.value; // this is text as a heads up
const rollMode = html.find("[name='rollMode']").val();
const rollMode =
dialog.element.querySelector("[name='rollMode']")?.value;
const plusMinus = html.find("[name='plusOrMinus']").val();
const plusMinus = dialog.element.querySelector(
"[name='plusOrMinus']",
)?.value;
if (
targetModifier.trim() !== "" &&
@@ -200,55 +228,8 @@ export class DGPercentileRoll extends DGRoll {
}
},
},
roll40Negative: {
label: "-40",
callback: (html) => {
try {
const rollMode = html.find("[name='rollMode']").val();
const targetModifier = -40;
resolve({ targetModifier, rollMode });
} catch (ex) {
reject(console.log(ex));
}
},
},
roll20Negative: {
label: "-20",
callback: (html) => {
try {
const rollMode = html.find("[name='rollMode']").val();
const targetModifier = -20;
resolve({ targetModifier, rollMode });
} catch (ex) {
reject(console.log(ex));
}
},
},
roll20Positive: {
label: "+20",
callback: (html) => {
try {
const rollMode = html.find("[name='rollMode']").val();
const targetModifier = 20;
resolve({ targetModifier, rollMode });
} catch (ex) {
reject(console.log(ex));
}
},
},
roll40Positive: {
label: "+40",
callback: (html) => {
try {
const rollMode = html.find("[name='rollMode']").val();
const targetModifier = 40;
resolve({ targetModifier, rollMode });
} catch (ex) {
reject(console.log(ex));
}
},
},
},
...modButtons,
],
}).render(true);
});
}
@@ -275,7 +256,7 @@ export class DGPercentileRoll extends DGRoll {
this.options.rollMode = "blindroll";
}
let label = this.createLabel();
const label = this.createLabel();
let resultString = "";
let styleOverride = "";
@@ -288,21 +269,20 @@ export class DGPercentileRoll extends DGRoll {
} else {
resultString = `${game.i18n.localize("DG.Roll.Success")}`;
}
} else if (this.isCritical) {
resultString = `${game.i18n.localize("DG.Roll.CriticalFailure")}`;
resultString = `${resultString.toUpperCase()}`;
styleOverride = "color: red";
} else {
if (this.isCritical) {
resultString = `${game.i18n.localize("DG.Roll.CriticalFailure")}`;
resultString = `${resultString.toUpperCase()}`;
styleOverride = "color: red";
} else {
resultString = `${game.i18n.localize("DG.Roll.Failure")}`;
}
resultString = `${game.i18n.localize("DG.Roll.Failure")}`;
}
const failureMark = !this.isSuccess && this.skillPath
&& !foundry.utils.getProperty(this.actor, `${this.skillPath}.failure`)
&& game.settings.get(DG.ID, "skillFailure");
const failureMark =
!this.isSuccess &&
this.skillPath &&
!foundry.utils.getProperty(this.actor, `${this.skillPath}.failure`) &&
game.settings.get(DG.ID, "skillFailure");
const { renderTemplate } = foundry.applications.handlebars;
const html = await renderTemplate(
"systems/deltagreen/templates/roll/percentile-roll.hbs",
{
@@ -310,26 +290,32 @@ export class DGPercentileRoll extends DGRoll {
resultString,
formula: this.formula,
total: this.total,
failureMark
});
failureMark,
},
);
//TODO: add setting for it?
// TODO: add setting for it?
if (failureMark) {
const keyForUpdate = `${this.skillPath}.failure`;
//TODO: auto-update actor or post icon with manual apply
// TODO: auto-update actor or post icon with manual apply
await this.actor.update({
[keyForUpdate]: true
})
[keyForUpdate]: true,
});
return this.toMessage({ flags: { deltagreen: {
rollbacks: {
[keyForUpdate]: false
}
} }, content: html, flavor: label });
} else {
return this.toMessage({ content: html, flavor: label });
return this.toMessage({
flags: {
deltagreen: {
rollbacks: {
[keyForUpdate]: false,
},
},
},
content: html,
flavor: label,
});
}
return this.toMessage({ content: html, flavor: label });
}
/**
@@ -383,16 +369,21 @@ export class DGPercentileRoll extends DGRoll {
* @returns {string}
*/
createLabel() {
const startOfLabel = game.i18n.localize("DG.Roll.Rolling")
+ ` <b>${this.localizedKey}`
const endOfLabel =`${game.i18n.localize("DG.Roll.Target")} ${this.effectiveTarget}`
const startOfLabel = `${game.i18n.localize("DG.Roll.Rolling")} <b>${
this.localizedKey
}`;
const endOfLabel = `${game.i18n.localize("DG.Roll.Target")} ${
this.effectiveTarget
}`;
let label = this.isInhuman
// "Inhuman" stat being rolled. See function for details.
? `${startOfLabel} [${game.i18n.localize("DG.Roll.Inhuman").toUpperCase()}]</b> ${endOfLabel}`
? // "Inhuman" stat being rolled. See function for details.
`${startOfLabel} [${game.i18n
.localize("DG.Roll.Inhuman")
.toUpperCase()}]</b> ${endOfLabel}`
: `${startOfLabel}</b><br> ${endOfLabel}%`;
const {isExhausted, exhaustedCheckPenalty} = this.exhausted
const { isExhausted, exhaustedCheckPenalty } = this.exhausted;
if (this.modifier || isExhausted) {
label += ` (${this.target}%`;
@@ -429,7 +420,7 @@ export class DGPercentileRoll extends DGRoll {
exhaustedCheckPenalty = -20;
}
return {isExhausted, exhaustedCheckPenalty};
return { isExhausted, exhaustedCheckPenalty };
}
/**
@@ -510,7 +501,7 @@ export class DGPercentileRoll extends DGRoll {
get effectiveTarget() {
let target = 1;
let {isExhausted, exhaustedCheckPenalty} = this.exhausted
const { isExhausted, exhaustedCheckPenalty } = this.exhausted;
if (!this.target || Number.isNaN(this.target)) {
return null;
@@ -715,22 +706,30 @@ export class DGDamageRoll extends DGRoll {
const content = await renderTemplate(template, backingData);
return new Promise((resolve, reject) => {
new Dialog({
new DialogV2({
content,
title: game.i18n.localize("DG.ModifySkillRollDialogue.Title"),
default: "roll",
buttons: {
roll: {
window: {
title: game.i18n.localize("DG.ModifySkillRollDialogue.Title"),
},
buttons: [
{
default: true,
label: game.i18n.translations.DG.Roll.Roll,
callback: (html) => {
action: "roll",
callback: (event, button, dialog) => {
try {
const outerModifier = html.find("[name='outerModifier']").val(); // this is text as a heads up
let innerModifier = html.find("[name='innerModifier']").val(); // this is text as a heads up
const modifiedBaseRoll = html
.find("[name='originalFormula']")
.val(); // this is text as a heads up
const rollMode = html.find("[name='targetRollMode']").val();
const outerModifier = dialog.element.querySelector(
"[name='outerModifier']",
)?.value; // this is text as a heads up
let innerModifier = dialog.element.querySelector(
"[name='innerModifier']",
)?.value; // this is text as a heads up
const modifiedBaseRoll = dialog.element.querySelector(
"[name='originalFormula']",
)?.value; // this is text as a heads up
const rollMode = dialog.element.querySelector(
"[name='targetRollMode']",
)?.value;
if (innerModifier.replace(" ", "") === "+0") {
innerModifier = "";
@@ -749,7 +748,7 @@ export class DGDamageRoll extends DGRoll {
}
},
},
},
],
}).render(true);
});
}
+9 -6
View File
@@ -214,16 +214,19 @@ export default class DGAgentSheet extends DGActorSheet {
},
);
return Dialog.wait({
return foundry.applications.api.DialogV2.wait({
content,
title: game.i18n.localize("DG.Skills.ApplySkillImprovements.Title"),
default: "apply",
buttons: {
apply: {
window: {
title: game.i18n.localize("DG.Skills.ApplySkillImprovements.Title"),
},
buttons: [
{
default: true,
action: "apply",
label: game.i18n.localize("DG.Skills.Apply"),
icon: "<i class='fas fa-check'></i>",
},
},
],
});
}
+63 -47
View File
@@ -8,6 +8,7 @@ import {
import DGSheetMixin from "./base-sheet.js";
const { ActorSheetV2 } = foundry.applications.sheets;
const { DialogV2 } = foundry.applications.api;
export default class DGActorSheet extends DGSheetMixin(ActorSheetV2) {
/** @override */
@@ -841,22 +842,25 @@ export default class DGActorSheet extends DGSheetMixin(ActorSheetV2) {
htmlContent += ` <input type="text" name="new-type-skill-label" value="${currentLabel}" />`;
htmlContent += `</div>`;
new Dialog({
new DialogV2({
content: htmlContent,
title:
game.i18n.translations.DG?.Skills?.EditTypedOrCustomSkill ??
"Edit Typed or Custom Skill",
default: "add",
buttons: {
add: {
window: {
title:
game.i18n.translations.DG?.Skills?.EditTypedOrCustomSkill ??
"Edit Typed or Custom Skill",
},
buttons: [
{
default: true,
action: "add",
label: game.i18n.translations.DG?.Skills?.EditSkill ?? "Edit Skill",
callback: (btn) => {
const newTypeSkillLabel = btn
.find("[name='new-type-skill-label']")
.val();
const newTypeSkillGroup = btn
.find("[name='new-type-skill-group']")
.val();
callback: (event, button, dialog) => {
const newTypeSkillLabel = dialog.element.querySelector(
"[name='new-type-skill-label']",
)?.value;
const newTypeSkillGroup = dialog.element.querySelector(
"[name='new-type-skill-group']",
)?.value;
this._updateTypedSkill(
targetSkill,
newTypeSkillLabel,
@@ -864,7 +868,7 @@ export default class DGActorSheet extends DGSheetMixin(ActorSheetV2) {
);
},
},
},
],
}).render(true);
}
@@ -909,26 +913,30 @@ export default class DGActorSheet extends DGSheetMixin(ActorSheetV2) {
htmlContent += ` <input type="text" name="new-type-skill-label" />`;
htmlContent += `</div>`;
new Dialog({
new DialogV2({
content: htmlContent,
title:
game.i18n.translations.DG?.Skills?.AddTypedOrCustomSkill ??
"Add Typed or Custom Skill",
window: {
title:
game.i18n.translations.DG?.Skills?.AddTypedOrCustomSkill ??
"Add Typed or Custom Skill",
},
default: "add",
buttons: {
add: {
buttons: [
{
default: true,
action: "add",
label: game.i18n.translations.DG?.Skills?.AddSkill ?? "Add Skill",
callback: (btn) => {
const newTypeSkillLabel = btn
.find("[name='new-type-skill-label']")
.val();
const newTypeSkillGroup = btn
.find("[name='new-type-skill-group']")
.val();
callback: (event, button, dialog) => {
const newTypeSkillLabel = dialog.element.querySelector(
"[name='new-type-skill-label']",
)?.value;
const newTypeSkillGroup = dialog.element.querySelector(
"[name='new-type-skill-group']",
)?.value;
this._addNewTypedSkill(newTypeSkillLabel, newTypeSkillGroup);
},
},
},
],
}).render(true);
}
@@ -1072,20 +1080,24 @@ export default class DGActorSheet extends DGSheetMixin(ActorSheetV2) {
);
// Prepare and render dialog with above template.
new Dialog({
new DialogV2({
content,
title: game.i18n.localize("DG.SpecialTraining.Dialog.Title"),
window: {
title: game.i18n.localize("DG.SpecialTraining.Dialog.Title"),
},
default: "confirm",
buttons: {
confirm: {
buttons: [
{
default: true,
action: "confirm",
label: buttonLabel,
callback: (btn) => {
const specialTrainingLabel = btn
.find("[name='special-training-label']")
.val();
const specialTrainingAttribute = btn
.find("[name='special-training-skill']")
.val();
callback: (event, button, dialog) => {
const specialTrainingLabel = dialog.element.querySelector(
"[name='special-training-label']",
)?.value;
const specialTrainingAttribute = dialog.element.querySelector(
"[name='special-training-skill']",
)?.value;
if (action === "create")
this._createSpecialTraining(
specialTrainingLabel,
@@ -1099,7 +1111,7 @@ export default class DGActorSheet extends DGSheetMixin(ActorSheetV2) {
);
},
},
},
],
}).render(true);
}
@@ -1262,17 +1274,21 @@ export default class DGActorSheet extends DGSheetMixin(ActorSheetV2) {
const { packType } = target.dataset;
switch (packType) {
case "weapon": {
new Dialog({
title: "Select Compendium",
buttons: {
firearms: {
new DialogV2({
window: { title: "Select Compendium" },
buttons: [
{
action: "firearms",
label: game.i18n.localize("DG.Gear.WeaponTypes.Firearms"),
icon: '<i class="fas fa-crosshairs"></i>',
callback: () =>
game.packs
.find((k) => k.collection === "deltagreen.firearms")
.render(true),
},
melee: {
{
action: "melee",
label: game.i18n.localize("DG.Gear.WeaponTypes.Melee"),
icon: '<i class="far fa-hand-rock"></i>',
callback: () =>
game.packs
@@ -1281,7 +1297,7 @@ export default class DGActorSheet extends DGSheetMixin(ActorSheetV2) {
)
.render(true),
},
},
],
}).render(true);
break;
}
+1 -1
View File
@@ -16,7 +16,7 @@
<span>{{localize 'DG.ModifySkillRollDialogue.TargetModifier'}}</span>
<div>
<div class="plusMinusNumberFieldBox">
<select name="plusOrMinus">
<option value="+" selected>+</option>
<option value="-">-</option>