Display (only!) selection options to the user.

This commit is contained in:
Oliver Rümpelein 2021-01-10 16:40:11 +01:00
parent c94ff4a67a
commit a19a996d1d
6 changed files with 88 additions and 28 deletions

View file

@ -14,6 +14,8 @@ class DefaultCheckOptions implements DS4CheckFactoryOptions {
}
}
const defaultCheckOptions = new DefaultCheckOptions();
/**
* Most basic class responsible for generating the chat formula and passing it to the chat as roll.
*/
@ -53,8 +55,8 @@ class CheckFactory {
}
createCritTerm(): string {
const minCritRequired = this.checkOptions.minCritFailure !== CheckFactory.defaultCheckOptions.minCritFailure;
const maxCritRequired = this.checkOptions.maxCritSuccess !== CheckFactory.defaultCheckOptions.maxCritSuccess;
const minCritRequired = this.checkOptions.minCritFailure !== defaultCheckOptions.minCritFailure;
const maxCritRequired = this.checkOptions.maxCritSuccess !== defaultCheckOptions.maxCritSuccess;
if (minCritRequired || maxCritRequired) {
return "c" + (this.checkOptions.maxCritSuccess ?? "") + "," + (this.checkOptions.minCritFailure ?? "");
@ -66,8 +68,6 @@ class CheckFactory {
createSlayingDiceTerm(): string {
return this.checkOptions.useSlayingDice ? "x" : null;
}
static defaultCheckOptions = new DefaultCheckOptions();
}
// TODO: Figure out return of roll (void should be Ok, tough?)
@ -78,10 +78,10 @@ class CheckFactory {
*/
export async function createCheckRoll(targetValue: number, options: Partial<DS4CheckFactoryOptions>): Promise<void> {
// Ask for additional required data;
const gmModifier = await askGmModifier();
const gmModifierData = await askGmModifier(targetValue, options);
// Create Factory
const cf = new CheckFactory(targetValue, gmModifier, options);
const cf = new CheckFactory(targetValue, gmModifierData.gmModifier, options);
// Possibly additional processing
@ -92,11 +92,53 @@ export async function createCheckRoll(targetValue: number, options: Partial<DS4C
/**
* Responsible for rendering the modal interface asking for the modifier specified by GM.
*
* @notes
* At the moment, this asks for more data than it will do after some iterations.
*
* @returns {Promise<number>} The number by the user.
*/
async function askGmModifier(): Promise<number> {
async function askGmModifier(
targetValue: number,
options: Partial<DS4CheckFactoryOptions>,
{ template, title }: { template?: string; title?: string } = {},
): Promise<GmModifierData> {
// Render model interface and return value
return 0;
const usedTemplate = template ?? "systems/ds4/templates/roll/roll-options.hbs";
const templateData = {
cssClass: "roll-option",
title: title ?? "Roll Options",
checkTargetValue: targetValue,
maxCritSuccess: options.maxCritSuccess ?? defaultCheckOptions.maxCritSuccess,
minCritFailure: options.minCritFailure ?? defaultCheckOptions.minCritFailure,
rollModes: rollModes,
};
const renderedHtml = await renderTemplate(usedTemplate, templateData);
// TODO: Localize
const dialogData: DialogData = {
title: title ?? "Roll Options",
close: (html) => null,
content: renderedHtml,
buttons: {
ok: {
label: "OK",
callback: (html) => null,
},
cancel: {
label: "Cancel",
callback: (html) => null,
},
},
default: "ok",
};
const dialog = new Dialog(dialogData, {}).render(true);
return { gmModifier: 0 };
}
interface GmModifierData {
gmModifier: number;
}
export interface DS4CheckFactoryOptions {
@ -106,4 +148,6 @@ export interface DS4CheckFactoryOptions {
rollMode: DS4RollMode;
}
export type DS4RollMode = "roll" | "gmroll" | "blindroll" | "selfroll";
const rollModes = ["roll", "gmroll", "blindroll", "selfroll"] as const;
type DS4RollModeTuple = typeof rollModes;
export type DS4RollMode = DS4RollModeTuple[number];

View file

@ -86,7 +86,7 @@ export class DS4Check extends DiceTerm {
} else {
return ds4roll(targetValueToUse, {
maxCritSuccess: this.maxCritSuccess,
minCritFail: this.minCritFailure,
minCritFailure: this.minCritFailure,
slayingDiceRepetition: slayingDiceRepetition,
useSlayingDice: slayingDiceRepetition,
});

View file

@ -1,13 +1,13 @@
export interface RollOptions {
maxCritSuccess: number;
minCritFail: number;
minCritFailure: number;
useSlayingDice: boolean;
slayingDiceRepetition: boolean;
}
export class DefaultRollOptions implements RollOptions {
public maxCritSuccess = 1;
public minCritFail = 20;
public minCritFailure = 20;
public useSlayingDice = false;
public slayingDiceRepetition = false;

View file

@ -48,7 +48,7 @@ export function rollCheckSingleDie(
if (rolledDie <= usedOptions.maxCritSuccess) {
return new RollResult(checkTargetValue, RollResultStatus.CRITICAL_SUCCESS, usedDice, true);
} else if (rolledDie >= usedOptions.minCritFail && !isSlayingDiceRepetition(usedOptions)) {
} else if (rolledDie >= usedOptions.minCritFailure && !isSlayingDiceRepetition(usedOptions)) {
return new RollResult(0, RollResultStatus.CRITICAL_FAILURE, usedDice, true);
} else {
if (rolledDie <= checkTargetValue) {
@ -90,7 +90,7 @@ export function rollCheckMultipleDice(
const slayingDiceRepetition = isSlayingDiceRepetition(usedOptions);
// Slaying Dice require a different handling.
if (firstResult >= usedOptions.minCritFail && !slayingDiceRepetition) {
if (firstResult >= usedOptions.minCritFailure && !slayingDiceRepetition) {
return new RollResult(0, RollResultStatus.CRITICAL_FAILURE, usedDice, true);
}

View file

@ -0,0 +1,16 @@
<form class="{{cssClass}} grid">
<label for="ctv">Check Target Value</label>
<input id="ctv" type="number" name="ctv" value="{{checkTargetValue}}" />
<label for="gmmod">Game Master Modifier</label>
<input id="gmmod" type="number" name="gmmod" value="0" />
<label for="maxcoup">Coup to</label>
<input id="maxcoup" type="number" name="maxcoup" value="{{maxCritSuccess}}" />
<label for="minfumble">Fumble from</label>
<input id="minfumble" type="number" name="minfumble" value="{{minCritFailure}}" />
<label for="visibility">Visibility</label>
<select id="visibility" data-type="String">
{{#each rollModes as |rollMode|}}
<option value="{{rollMode}}">{{rollMode}}</option>
{{/each}}
</select>
</form>