// TODO: Rename to something sane. class DefaultCheckOptions implements CheckOptions { maxCritSuccess = 1; minCritFailure = 20; useSlayingDice = false; rollMode: RollMode = "roll"; mergeWith(other: Partial): CheckOptions { return { ...this, ...other } as CheckOptions; } } class CheckFactory { constructor( private checkTargetValue: number, private gmModifier: number, passedOptions: Partial = {}, ) { this.checkOptions = new DefaultCheckOptions().mergeWith(passedOptions); } private checkOptions: CheckOptions; async execute(): Promise { const rollCls: typeof Roll = CONFIG.Dice.rolls[0]; const formula = [ "ds", this.createTargetValueTerm(), this.createCritTerm(), this.createSlayingDiceTerm(), ].filterJoin(""); const roll = new rollCls(formula); const rollModeTemplate = this.checkOptions.rollMode; return roll.toMessage({}, { rollMode: rollModeTemplate, create: true }); } // Term generators createTargetValueTerm(): string { if (this.checkTargetValue != null) { return "v" + this.checkTargetValue; } else { return null; } } createCritTerm(): string { const minCritRequired = this.checkOptions.minCritFailure !== CheckFactory.defaultCheckOptions.minCritFailure; const maxCritRequired = this.checkOptions.maxCritSuccess !== CheckFactory.defaultCheckOptions.maxCritSuccess; if (minCritRequired || maxCritRequired) { return "c" + (this.checkOptions.maxCritSuccess ?? "") + "," + (this.checkOptions.minCritFailure ?? ""); } else { return null; } } createSlayingDiceTerm(): string { return this.checkOptions.useSlayingDice ? "x" : null; } static defaultCheckOptions = new DefaultCheckOptions(); } // TODO: Figure out return of roll (void should be Ok, tough?) export async function createCheckRoll(targetValue: number, options: Partial): Promise { // Ask for additional required data; const gmModifier = await askGmModifier(); // Create Factory const cf = new CheckFactory(targetValue, gmModifier, options); // Possibly additional processing // Execute roll await cf.execute(); } async function askGmModifier(): Promise { // Render model interface and return value return 0; } interface CheckOptions { maxCritSuccess: number; minCritFailure: number; useSlayingDice: boolean; rollMode: RollMode; } type RollMode = "roll" | "gmroll" | "blindroll" | "selfroll";