Working on an update for DialogManager#ask that allows multiple inputs in the Dialog
This commit is contained in:
parent
7a6fa6d10d
commit
7b1db343ce
5 changed files with 124 additions and 45 deletions
|
|
@ -1,17 +1,29 @@
|
||||||
async function rollDice() {
|
async function rollDice() {
|
||||||
|
|
||||||
const statBase = await DialogManager.ask({
|
|
||||||
question: `How many dice to roll?`,
|
|
||||||
initialValue: 2,
|
|
||||||
inputType: `number`,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!statBase) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const sidesOnDice = 6;
|
const sidesOnDice = 6;
|
||||||
const successThreshold = 4;
|
|
||||||
|
const answers = await DialogManager.ask({
|
||||||
|
id: `eat-the-reich-dice-pool`,
|
||||||
|
question: `Set up your dice pool:`,
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
inputType: `number`,
|
||||||
|
defaultValue: 2,
|
||||||
|
label: `Number of Dice`,
|
||||||
|
autofocus: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputType: `number`,
|
||||||
|
defaultValue: 4,
|
||||||
|
label: `Success Threshold (d${sidesOnDice} >= X)`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputType: `checkbox`,
|
||||||
|
defaultValue: true,
|
||||||
|
label: `Enable Criticals`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const [ statBase, successThreshold, critsEnabled ] = Object.values(answers);
|
||||||
|
|
||||||
let successes = 0;
|
let successes = 0;
|
||||||
const results = [];
|
const results = [];
|
||||||
|
|
@ -22,14 +34,17 @@ async function rollDice() {
|
||||||
if (r.total >= successThreshold) {
|
if (r.total >= successThreshold) {
|
||||||
successes++;
|
successes++;
|
||||||
}
|
}
|
||||||
if (r.total === sidesOnDice) {
|
if (r.total === sidesOnDice && critsEnabled) {
|
||||||
successes++;
|
successes++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await ChatMessage.create({
|
const m = new ChatMessage({
|
||||||
|
title: `Dice Pool`,
|
||||||
content: `Rolled: ${results.join(`, `)}<br>Successes: ${successes}`,
|
content: `Rolled: ${results.join(`, `)}<br>Successes: ${successes}`,
|
||||||
});
|
});
|
||||||
|
m.applyRollMode(game.settings.get(`core`, `rollMode`));
|
||||||
|
ui.chat.postOne(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
rollDice()
|
rollDice()
|
||||||
|
|
@ -79,35 +79,68 @@ export class DialogManager {
|
||||||
/**
|
/**
|
||||||
* Asks the user to provide a simple piece of information, this is primarily
|
* Asks the user to provide a simple piece of information, this is primarily
|
||||||
* intended to be used within macros so that it can have better info gathering
|
* intended to be used within macros so that it can have better info gathering
|
||||||
* as needed.
|
* as needed. This returns an object of input labels to the value the user
|
||||||
|
* input for that label, if there is only one input, this will return the value
|
||||||
|
* without an object wrapper, allowing for easier access.
|
||||||
*/
|
*/
|
||||||
static async ask(data, opts = {}) {
|
static async ask(data, opts = {}) {
|
||||||
if (!data.question) {
|
if (!data.id) {
|
||||||
throw new Error(`Asking the user for input must contain a question`);
|
throw new Error(`Asking the user for input must contain an ID`);
|
||||||
|
}
|
||||||
|
if (!data.inputs.length) {
|
||||||
|
throw new Error(`Must include at least one input specification when prompting the user`);
|
||||||
}
|
}
|
||||||
data.inputType ??= `text`;
|
|
||||||
data.initialValue ??= ``;
|
|
||||||
|
|
||||||
opts.title ??= `System Question`;
|
let autofocusClaimed = false;
|
||||||
|
for (const i of data.inputs) {
|
||||||
|
i.id ??= foundry.utils.randomID(16);
|
||||||
|
i.inputType ??= `text`;
|
||||||
|
|
||||||
|
// Only ever allow one input to claim autofocus
|
||||||
|
i.autofocus &&= !autofocusClaimed;
|
||||||
|
autofocusClaimed ||= i.autofocus;
|
||||||
|
|
||||||
|
// Set the value's attribute name if it isn't specified explicitly
|
||||||
|
if (!i.valueAttribute) {
|
||||||
|
switch (i.inputType) {
|
||||||
|
case `checkbox`:
|
||||||
|
i.valueAttribute = `checked`;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
i.valueAttribute = `value`;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
opts.jQuery = true;
|
opts.jQuery = true;
|
||||||
|
data.default ??= `confirm`;
|
||||||
|
data.title ??= `System Question`;
|
||||||
|
|
||||||
const content = await renderTemplate(
|
data.content = await renderTemplate(
|
||||||
`systems/${game.system.id}/templates/Dialogs/ask.hbs`,
|
`systems/${game.system.id}/templates/Dialogs/ask.hbs`,
|
||||||
data,
|
data,
|
||||||
);
|
);
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
DialogManager.createOrFocus(
|
DialogManager.createOrFocus(
|
||||||
data.question,
|
data.id,
|
||||||
{
|
{
|
||||||
content,
|
...data,
|
||||||
buttons: {
|
buttons: {
|
||||||
confirm: {
|
confirm: {
|
||||||
label: `Confirm`,
|
label: `Confirm`,
|
||||||
callback: (html) => {
|
callback: (html) => {
|
||||||
const element = html.find(`.user-input`)[0];
|
const answers = {};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Retrieve the answer for every input provided using the ID
|
||||||
|
determined during initial data prep, and assign the value
|
||||||
|
to the property of the label in the object.
|
||||||
|
*/
|
||||||
|
for (const i of data.inputs) {
|
||||||
|
const element = html.find(`#${i.id}`)[0];
|
||||||
let value = element.value;
|
let value = element.value;
|
||||||
switch (data.inputType) {
|
switch (i.inputType) {
|
||||||
case `number`:
|
case `number`:
|
||||||
value = parseFloat(value);
|
value = parseFloat(value);
|
||||||
break;
|
break;
|
||||||
|
|
@ -116,12 +149,19 @@ export class DialogManager {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Logger.debug(`Ask response: ${value} (type: ${typeof value})`);
|
Logger.debug(`Ask response: ${value} (type: ${typeof value})`);
|
||||||
|
answers[i.label] = value;
|
||||||
|
if (data.inputs.length === 1) {
|
||||||
resolve(value);
|
resolve(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(answers);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
cancel: {
|
cancel: {
|
||||||
label: `Cancel`,
|
label: `Cancel`,
|
||||||
callback: () => reject(),
|
callback: () => reject(`User cancelled the prompt`),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,12 @@
|
||||||
.dialog-content:not(:only-child) {
|
.dialog-content:not(:only-child) {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dialog-content {
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.prompt {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "taf",
|
"id": "taf",
|
||||||
"title": "Text-Based Actors",
|
"title": "Text-Based Actors",
|
||||||
"description": "",
|
"description": "",
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"download": "https://github.com/Oliver-Akins/Text-Actors-Foundry/releases/latest/download/dotdungeon.zip",
|
"download": "https://github.com/Oliver-Akins/Text-Actors-Foundry/releases/latest/download/dotdungeon.zip",
|
||||||
"manifest": "https://github.com/Oliver-Akins/Text-Actors-Foundry/releases/latest/download/system.json",
|
"manifest": "https://github.com/Oliver-Akins/Text-Actors-Foundry/releases/latest/download/system.json",
|
||||||
"url": "https://github.com/Oliver-Akins/Text-Actors-Foundry",
|
"url": "https://github.com/Oliver-Akins/Text-Actors-Foundry",
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,27 @@
|
||||||
<div>
|
<div class="ask-dialog">
|
||||||
<p>
|
<p>
|
||||||
{{ question }}
|
{{ question }}
|
||||||
</p>
|
</p>
|
||||||
<input
|
{{#each inputs as | i | }}
|
||||||
type="{{inputType}}"
|
<div class="prompt">
|
||||||
value="{{initialValue}}"
|
<label
|
||||||
checked="{{initialValue}}"
|
for="{{i.id}}"
|
||||||
class="user-input"
|
class="prompt__label"
|
||||||
autofocus
|
|
||||||
>
|
>
|
||||||
|
{{ i.label }}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="{{i.inputType}}"
|
||||||
|
id="{{i.id}}"
|
||||||
|
class="patrons__input"
|
||||||
|
{{i.valueAttribute}}="{{i.defaultValue}}"
|
||||||
|
{{#if i.autofocus}}autofocus{{/if}}
|
||||||
|
>
|
||||||
|
{{#if i.details}}
|
||||||
|
<p class="prompt__details">
|
||||||
|
{{{ i.details }}}
|
||||||
|
</p>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue