ds4/src/module/rolls/check-factory.ts

94 lines
2.7 KiB
TypeScript
Raw Normal View History

// TODO: Rename to something sane.
class DefaultCheckOptions implements CheckOptions {
maxCritSuccess = 1;
minCritFailure = 20;
useSlayingDice = false;
rollMode: RollMode = "roll";
mergeWith(other: Partial<CheckOptions>): CheckOptions {
return { ...this, ...other } as CheckOptions;
}
}
class CheckFactory {
constructor(
private checkTargetValue: number,
private gmModifier: number,
passedOptions: Partial<CheckOptions> = {},
) {
this.checkOptions = new DefaultCheckOptions().mergeWith(passedOptions);
}
private checkOptions: CheckOptions;
async execute(): Promise<void> {
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<CheckOptions>): Promise<void> {
// 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<number> {
// Render model interface and return value
return 0;
}
interface CheckOptions {
maxCritSuccess: number;
minCritFailure: number;
useSlayingDice: boolean;
rollMode: RollMode;
}
type RollMode = "roll" | "gmroll" | "blindroll" | "selfroll";