Improve CheckFactory
This commit is contained in:
parent
a2014c53d4
commit
d5b872e74b
5 changed files with 63 additions and 47 deletions
|
@ -66,6 +66,8 @@
|
||||||
"DS4.ItemTypeAlphabetPlural": "Schriftzeichen",
|
"DS4.ItemTypeAlphabetPlural": "Schriftzeichen",
|
||||||
"DS4.ItemTypeSpecialCreatureAbility": "Besondere Kreaturenfähigkeit",
|
"DS4.ItemTypeSpecialCreatureAbility": "Besondere Kreaturenfähigkeit",
|
||||||
"DS4.ItemTypeSpecialCreatureAbilityPlural": "Besondere Kreaturenfähigkeiten",
|
"DS4.ItemTypeSpecialCreatureAbilityPlural": "Besondere Kreaturenfähigkeiten",
|
||||||
|
"DS4.ItemWeaponCheckFlavor": "{actor} greift mit {item} an.",
|
||||||
|
"DS4.ItemSpellCheckFlavor": "{actor} wirkt {item}.",
|
||||||
"DS4.ArmorType": "Panzerungstyp",
|
"DS4.ArmorType": "Panzerungstyp",
|
||||||
"DS4.ArmorTypeAbbr": "PAT",
|
"DS4.ArmorTypeAbbr": "PAT",
|
||||||
"DS4.ArmorMaterialType": "Materialtyp",
|
"DS4.ArmorMaterialType": "Materialtyp",
|
||||||
|
@ -231,5 +233,7 @@
|
||||||
"DS4.RollDialogRollModeLabel": "Sichtbarkeit",
|
"DS4.RollDialogRollModeLabel": "Sichtbarkeit",
|
||||||
"DS4.TooltipBaseValue": "Basiswert",
|
"DS4.TooltipBaseValue": "Basiswert",
|
||||||
"DS4.TooltipModifier": "Modifikator",
|
"DS4.TooltipModifier": "Modifikator",
|
||||||
"DS4.TooltipEffects": "Effekte"
|
"DS4.TooltipEffects": "Effekte",
|
||||||
|
"DS4.SettingUseSlayingDiceForAutomatedChecksName": "Slayende Würfel",
|
||||||
|
"DS4.SettingUseSlayingDiceForAutomatedChecksHint": "Benutze Slayende Würfel bei automatisierten Proben."
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,8 @@
|
||||||
"DS4.ItemTypeAlphabetPlural": "Alphabets",
|
"DS4.ItemTypeAlphabetPlural": "Alphabets",
|
||||||
"DS4.ItemTypeSpecialCreatureAbility": "Special Creature Ability",
|
"DS4.ItemTypeSpecialCreatureAbility": "Special Creature Ability",
|
||||||
"DS4.ItemTypeSpecialCreatureAbilityPlural": "Special Creature Abilities",
|
"DS4.ItemTypeSpecialCreatureAbilityPlural": "Special Creature Abilities",
|
||||||
|
"DS4.ItemWeaponCheckFlavor": "{actor} attacks with {item}.",
|
||||||
|
"DS4.ItemSpellCheckFlavor": "{actor} casts {item}.",
|
||||||
"DS4.ArmorType": "Armor Type",
|
"DS4.ArmorType": "Armor Type",
|
||||||
"DS4.ArmorTypeAbbr": "AT",
|
"DS4.ArmorTypeAbbr": "AT",
|
||||||
"DS4.ArmorMaterialType": "Material Type",
|
"DS4.ArmorMaterialType": "Material Type",
|
||||||
|
@ -231,5 +233,7 @@
|
||||||
"DS4.RollDialogRollModeLabel": "Visibility",
|
"DS4.RollDialogRollModeLabel": "Visibility",
|
||||||
"DS4.TooltipBaseValue": "Base Value",
|
"DS4.TooltipBaseValue": "Base Value",
|
||||||
"DS4.TooltipModifier": "Modifier",
|
"DS4.TooltipModifier": "Modifier",
|
||||||
"DS4.TooltipEffects": "Effects"
|
"DS4.TooltipEffects": "Effects",
|
||||||
|
"DS4.SettingUseSlayingDiceForAutomatedChecksName": "Slaying Dice",
|
||||||
|
"DS4.SettingUseSlayingDiceForAutomatedChecksHint": "Use Slaying Dice for automated checks."
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ export class DS4Item extends Item<DS4ItemData> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Roll a check for a action with this item.
|
* Roll a check for an action with this item.
|
||||||
*/
|
*/
|
||||||
async roll(): Promise<void> {
|
async roll(): Promise<void> {
|
||||||
if (!this.isOwnedItem()) {
|
if (!this.isOwnedItem()) {
|
||||||
|
@ -87,14 +87,17 @@ export class DS4Item extends Item<DS4ItemData> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ownerDataData = ((this.actor as unknown) as DS4Actor).data.data; // TODO(types): Improve so that the concrete Actor type is known here
|
const actor = (this.actor as unknown) as DS4Actor; // TODO(types): Improve so that the concrete Actor type is known here
|
||||||
|
const ownerDataData = actor.data.data;
|
||||||
const weaponBonus = this.data.data.weaponBonus;
|
const weaponBonus = this.data.data.weaponBonus;
|
||||||
const combatValue = await this.getCombatValueKeyForAttackType(this.data.data.attackType);
|
const combatValue = await this.getCombatValueKeyForAttackType(this.data.data.attackType);
|
||||||
const checkTargetValue = (ownerDataData.combatValues[combatValue].total as number) + weaponBonus;
|
const checkTargetNumber = (ownerDataData.combatValues[combatValue].total as number) + weaponBonus;
|
||||||
await createCheckRoll(checkTargetValue, {
|
|
||||||
|
await createCheckRoll(checkTargetNumber, {
|
||||||
rollMode: game.settings.get("core", "rollMode"),
|
rollMode: game.settings.get("core", "rollMode"),
|
||||||
maximumCoupResult: ownerDataData.rolling.maximumCoupResult,
|
maximumCoupResult: ownerDataData.rolling.maximumCoupResult,
|
||||||
minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult,
|
minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult,
|
||||||
|
flavor: game.i18n.format("DS4.ItemWeaponCheckFlavor", { actor: actor.name, item: this.name }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +123,8 @@ export class DS4Item extends Item<DS4ItemData> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ownerDataData = ((this.actor as unknown) as DS4Actor).data.data; // TODO(types): Improve so that the concrete Actor type is known here
|
const actor = (this.actor as unknown) as DS4Actor; // TODO(types): Improve so that the concrete Actor type is known here
|
||||||
|
const ownerDataData = actor.data.data;
|
||||||
const spellBonus = Number.isNumeric(this.data.data.bonus) ? parseInt(this.data.data.bonus) : undefined;
|
const spellBonus = Number.isNumeric(this.data.data.bonus) ? parseInt(this.data.data.bonus) : undefined;
|
||||||
if (spellBonus === undefined) {
|
if (spellBonus === undefined) {
|
||||||
notifications.info(
|
notifications.info(
|
||||||
|
@ -131,12 +135,13 @@ export class DS4Item extends Item<DS4ItemData> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const spellType = this.data.data.spellType;
|
const spellType = this.data.data.spellType;
|
||||||
const checkTargetValue = (ownerDataData.combatValues[spellType].total as number) + (spellBonus ?? 0);
|
const checkTargetNumber = (ownerDataData.combatValues[spellType].total as number) + (spellBonus ?? 0);
|
||||||
|
|
||||||
await createCheckRoll(checkTargetValue, {
|
await createCheckRoll(checkTargetNumber, {
|
||||||
rollMode: game.settings.get("core", "rollMode"),
|
rollMode: game.settings.get("core", "rollMode"),
|
||||||
maximumCoupResult: ownerDataData.rolling.maximumCoupResult,
|
maximumCoupResult: ownerDataData.rolling.maximumCoupResult,
|
||||||
minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult,
|
minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult,
|
||||||
|
flavor: game.i18n.format("DS4.ItemSpellCheckFlavor", { actor: actor.name, item: this.name }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ class DefaultCheckOptions implements DS4CheckFactoryOptions {
|
||||||
readonly minimumFumbleResult = 20;
|
readonly minimumFumbleResult = 20;
|
||||||
readonly useSlayingDice = false;
|
readonly useSlayingDice = false;
|
||||||
readonly rollMode: Const.DiceRollMode = "roll";
|
readonly rollMode: Const.DiceRollMode = "roll";
|
||||||
|
readonly flavor: undefined;
|
||||||
|
|
||||||
mergeWith(other: Partial<DS4CheckFactoryOptions>): DS4CheckFactoryOptions {
|
mergeWith(other: Partial<DS4CheckFactoryOptions>): DS4CheckFactoryOptions {
|
||||||
return { ...this, ...other };
|
return { ...this, ...other };
|
||||||
|
@ -22,41 +23,37 @@ const defaultCheckOptions = new DefaultCheckOptions();
|
||||||
*/
|
*/
|
||||||
class CheckFactory {
|
class CheckFactory {
|
||||||
constructor(
|
constructor(
|
||||||
private checkTargetValue: number,
|
private checkTargetNumber: number,
|
||||||
private gmModifier: number,
|
private gmModifier: number,
|
||||||
passedOptions: Partial<DS4CheckFactoryOptions> = {},
|
options: Partial<DS4CheckFactoryOptions> = {},
|
||||||
) {
|
) {
|
||||||
this.checkOptions = defaultCheckOptions.mergeWith(passedOptions);
|
this.options = defaultCheckOptions.mergeWith(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private checkOptions: DS4CheckFactoryOptions;
|
private options: DS4CheckFactoryOptions;
|
||||||
|
|
||||||
async execute(): Promise<ChatMessage | unknown> {
|
async execute(): Promise<ChatMessage> {
|
||||||
const innerFormula = ["ds", this.createTargetValueTerm(), this.createCritTerm()].filterJoin("");
|
const innerFormula = ["ds", this.createTargetNumberModifier(), this.createCoupFumbleModifier()].filterJoin("");
|
||||||
const formula = this.checkOptions.useSlayingDice ? `{${innerFormula}}x` : innerFormula;
|
const formula = this.options.useSlayingDice ? `{${innerFormula}}x` : innerFormula;
|
||||||
const roll = Roll.create(formula);
|
const roll = Roll.create(formula);
|
||||||
|
|
||||||
const rollModeTemplate = this.checkOptions.rollMode;
|
return roll.toMessage(
|
||||||
return roll.toMessage({}, { rollMode: rollModeTemplate, create: true });
|
{ speaker: ChatMessage.getSpeaker(), flavor: this.options.flavor },
|
||||||
|
{ rollMode: this.options.rollMode, create: true },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Term generators
|
createTargetNumberModifier(): string | null {
|
||||||
createTargetValueTerm(): string | null {
|
return "v" + (this.checkTargetNumber + this.gmModifier);
|
||||||
if (this.checkTargetValue !== null) {
|
|
||||||
return "v" + (this.checkTargetValue + this.gmModifier);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createCritTerm(): string | null {
|
createCoupFumbleModifier(): string | null {
|
||||||
const minCritRequired = this.checkOptions.minimumFumbleResult !== defaultCheckOptions.minimumFumbleResult;
|
const isMinimumFumbleResultRequired =
|
||||||
const maxCritRequired = this.checkOptions.maximumCoupResult !== defaultCheckOptions.maximumCoupResult;
|
this.options.minimumFumbleResult !== defaultCheckOptions.minimumFumbleResult;
|
||||||
|
const isMaximumCoupResultRequired = this.options.maximumCoupResult !== defaultCheckOptions.maximumCoupResult;
|
||||||
|
|
||||||
if (minCritRequired || maxCritRequired) {
|
if (isMinimumFumbleResultRequired || isMaximumCoupResultRequired) {
|
||||||
return (
|
return "c" + (this.options.maximumCoupResult ?? "") + ":" + (this.options.minimumFumbleResult ?? "");
|
||||||
"c" + (this.checkOptions.maximumCoupResult ?? "") + ":" + (this.checkOptions.minimumFumbleResult ?? "")
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -65,23 +62,24 @@ class CheckFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asks the user for all unknown/necessary information and passes them on to perform a roll.
|
* Asks the user for all unknown/necessary information and passes them on to perform a roll.
|
||||||
* @param targetValue - The Check Target Number ("CTN")
|
* @param checkTargetNumber - The Check Target Number ("CTN")
|
||||||
* @param options - Options changing the behavior of the roll and message.
|
* @param options - Options changing the behavior of the roll and message.
|
||||||
*/
|
*/
|
||||||
export async function createCheckRoll(
|
export async function createCheckRoll(
|
||||||
targetValue: number,
|
checkTargetNumber: number,
|
||||||
options: Partial<DS4CheckFactoryOptions> = {},
|
options: Partial<DS4CheckFactoryOptions> = {},
|
||||||
): Promise<ChatMessage | unknown> {
|
): Promise<ChatMessage | unknown> {
|
||||||
// Ask for additional required data;
|
// Ask for additional required data;
|
||||||
const gmModifierData = await askGmModifier(targetValue, options);
|
const gmModifierData = await askGmModifier(checkTargetNumber, options);
|
||||||
|
|
||||||
const newTargetValue = gmModifierData.checkTargetNumber ?? targetValue;
|
const newTargetValue = gmModifierData.checkTargetNumber ?? checkTargetNumber;
|
||||||
const gmModifier = gmModifierData.gmModifier ?? 0;
|
const gmModifier = gmModifierData.gmModifier ?? 0;
|
||||||
const newOptions: Partial<DS4CheckFactoryOptions> = {
|
const newOptions: Partial<DS4CheckFactoryOptions> = {
|
||||||
maximumCoupResult: gmModifierData.maximumCoupResult ?? options.maximumCoupResult ?? undefined,
|
maximumCoupResult: gmModifierData.maximumCoupResult ?? options.maximumCoupResult,
|
||||||
minimumFumbleResult: gmModifierData.minimumFumbleResult ?? options.minimumFumbleResult ?? undefined,
|
minimumFumbleResult: gmModifierData.minimumFumbleResult ?? options.minimumFumbleResult,
|
||||||
useSlayingDice: gmModifierData.useSlayingDice ?? options.useSlayingDice ?? undefined,
|
useSlayingDice: game.settings.get("ds4", "useSlayingDiceForAutomatedChecks") ?? false,
|
||||||
rollMode: gmModifierData.rollMode ?? options.rollMode ?? undefined,
|
rollMode: gmModifierData.rollMode ?? options.rollMode,
|
||||||
|
flavor: options.flavor,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create Factory
|
// Create Factory
|
||||||
|
@ -106,7 +104,6 @@ async function askGmModifier(
|
||||||
options: Partial<DS4CheckFactoryOptions> = {},
|
options: Partial<DS4CheckFactoryOptions> = {},
|
||||||
{ template, title }: { template?: string; title?: string } = {},
|
{ template, title }: { template?: string; title?: string } = {},
|
||||||
): Promise<Partial<IntermediateGmModifierData>> {
|
): Promise<Partial<IntermediateGmModifierData>> {
|
||||||
// Render model interface and return value
|
|
||||||
const usedTemplate = template ?? "systems/ds4/templates/roll/roll-options.hbs";
|
const usedTemplate = template ?? "systems/ds4/templates/roll/roll-options.hbs";
|
||||||
const usedTitle = title ?? game.i18n.localize("DS4.RollDialogDefaultTitle");
|
const usedTitle = title ?? game.i18n.localize("DS4.RollDialogDefaultTitle");
|
||||||
const templateData = {
|
const templateData = {
|
||||||
|
@ -114,7 +111,7 @@ async function askGmModifier(
|
||||||
checkTargetNumber: checkTargetNumber,
|
checkTargetNumber: checkTargetNumber,
|
||||||
maximumCoupResult: options.maximumCoupResult ?? defaultCheckOptions.maximumCoupResult,
|
maximumCoupResult: options.maximumCoupResult ?? defaultCheckOptions.maximumCoupResult,
|
||||||
minimumFumbleResult: options.minimumFumbleResult ?? defaultCheckOptions.minimumFumbleResult,
|
minimumFumbleResult: options.minimumFumbleResult ?? defaultCheckOptions.minimumFumbleResult,
|
||||||
rollMode: options.rollMode,
|
rollMode: options.rollMode ?? game.settings.get("core", "rollMode"),
|
||||||
rollModes: CONFIG.Dice.rollModes,
|
rollModes: CONFIG.Dice.rollModes,
|
||||||
};
|
};
|
||||||
const renderedHtml = await renderTemplate(usedTemplate, templateData);
|
const renderedHtml = await renderTemplate(usedTemplate, templateData);
|
||||||
|
@ -200,12 +197,8 @@ interface GmModifierData {
|
||||||
*/
|
*/
|
||||||
interface IntermediateGmModifierData extends GmModifierData {
|
interface IntermediateGmModifierData extends GmModifierData {
|
||||||
checkTargetNumber: number;
|
checkTargetNumber: number;
|
||||||
gmModifier: number;
|
|
||||||
maximumCoupResult: number;
|
maximumCoupResult: number;
|
||||||
minimumFumbleResult: number;
|
minimumFumbleResult: number;
|
||||||
// TODO: In final version from system settings
|
|
||||||
useSlayingDice: boolean;
|
|
||||||
rollMode: Const.DiceRollMode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -216,4 +209,5 @@ export interface DS4CheckFactoryOptions {
|
||||||
minimumFumbleResult: number;
|
minimumFumbleResult: number;
|
||||||
useSlayingDice: boolean;
|
useSlayingDice: boolean;
|
||||||
rollMode: Const.DiceRollMode;
|
rollMode: Const.DiceRollMode;
|
||||||
|
flavor?: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,4 +9,13 @@ export function registerSystemSettings(): void {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: -1,
|
default: -1,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
game.settings.register("ds4", "useSlayingDiceForAutomatedChecks", {
|
||||||
|
name: "DS4.SettingUseSlayingDiceForAutomatedChecksName",
|
||||||
|
hint: "DS4.SettingUseSlayingDiceForAutomatedChecksHint",
|
||||||
|
scope: "world",
|
||||||
|
config: true,
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue