ds4/src/item/weapon/weapon.ts
2022-05-29 17:48:49 +02:00

89 lines
3.7 KiB
TypeScript

// SPDX-FileCopyrightText: 2022 Johannes Loher
//
// SPDX-License-Identifier: MIT
import { DS4 } from "../../config";
import { getGame } from "../../helpers";
import { createCheckRoll } from "../../rolls/check-factory";
import notifications from "../../ui/notifications";
import { DS4Item } from "../item";
import type { AttackType } from "./weapon-data-source";
export class DS4Weapon extends DS4Item {
override prepareDerivedData(): void {
this.data.data.rollable = this.data.data.equipped;
}
override async roll(options: { speaker?: { token?: TokenDocument; alias?: string } } = {}): Promise<void> {
const game = getGame();
if (!this.data.data.equipped) {
return notifications.warn(
game.i18n.format("DS4.WarningItemMustBeEquippedToBeRolled", {
name: this.name,
id: this.id,
type: this.data.type,
}),
);
}
if (!this.actor) {
throw new Error(game.i18n.format("DS4.ErrorCannotRollUnownedItem", { name: this.name, id: this.id }));
}
const ownerDataData = this.actor.data.data;
const weaponBonus = this.data.data.weaponBonus;
const combatValue = await this.getCombatValueKeyForAttackType(this.data.data.attackType);
const checkTargetNumber = ownerDataData.combatValues[combatValue].total + weaponBonus;
const speaker = ChatMessage.getSpeaker({ actor: this.actor, ...options.speaker });
await createCheckRoll(checkTargetNumber, {
rollMode: getGame().settings.get("core", "rollMode"),
maximumCoupResult: ownerDataData.rolling.maximumCoupResult,
minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult,
flavor: "DS4.ItemWeaponCheckFlavor",
flavorData: { actor: speaker.alias ?? this.actor.name, weapon: this.name },
speaker,
});
Hooks.callAll("ds4.rollItem", this);
}
private async getCombatValueKeyForAttackType(attackType: AttackType): Promise<"meleeAttack" | "rangedAttack"> {
if (attackType === "meleeRanged") {
const { melee, ranged } = { ...DS4.i18n.attackTypes };
const identifier = "attack-type-selection";
return Dialog.prompt({
title: getGame().i18n.localize("DS4.DialogAttackTypeSelection"),
content: await renderTemplate("systems/ds4/templates/dialogs/simple-select-form.hbs", {
selects: [
{
label: getGame().i18n.localize("DS4.AttackType"),
identifier,
options: { melee, ranged },
},
],
}),
label: getGame().i18n.localize("DS4.GenericOkButton"),
callback: (html) => {
const selectedAttackType = html.find(`#${identifier}`).val();
if (selectedAttackType !== "melee" && selectedAttackType !== "ranged") {
throw new Error(
getGame().i18n.format("DS4.ErrorUnexpectedAttackType", {
actualType: selectedAttackType,
expectedTypes: "'melee', 'ranged'",
}),
);
}
return `${selectedAttackType}Attack` as const;
},
});
} else {
return `${attackType}Attack` as const;
}
}
}
export interface DS4Weapon {
data: foundry.data.ItemData & { type: "weapon"; _source: { type: "weapon" } };
}