Add possibility to roll spells from sheet adnrequire spells and weapons to be equipped to be rolled
This commit is contained in:
parent
68c20ccdc6
commit
74ad0c7f24
4 changed files with 77 additions and 9 deletions
|
@ -34,11 +34,14 @@ type DS4SpecialCreatureAbilityData = DS4ItemDataHelper<DS4SpecialCreatureAbility
|
|||
|
||||
export type AttackType = keyof typeof DS4["i18n"]["attackTypes"];
|
||||
|
||||
interface DS4WeaponDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical, DS4ItemDataDataEquipable {
|
||||
interface DS4WeaponDataData
|
||||
extends DS4ItemDataDataBase,
|
||||
DS4ItemDataDataPhysical,
|
||||
DS4ItemDataDataEquipable,
|
||||
DS4ItemDataDataRollable {
|
||||
attackType: AttackType;
|
||||
weaponBonus: number;
|
||||
opponentDefense: number;
|
||||
rollable?: boolean;
|
||||
}
|
||||
|
||||
interface DS4ArmorDataData
|
||||
|
@ -58,7 +61,7 @@ interface DS4TalentRank extends ModifiableData<number> {
|
|||
max: number;
|
||||
}
|
||||
|
||||
interface DS4SpellDataData extends DS4ItemDataDataBase, DS4ItemDataDataEquipable {
|
||||
interface DS4SpellDataData extends DS4ItemDataDataBase, DS4ItemDataDataEquipable, DS4ItemDataDataRollable {
|
||||
spellType: "spellcasting" | "targetedSpellcasting";
|
||||
bonus: string;
|
||||
spellCategory:
|
||||
|
@ -112,6 +115,10 @@ interface DS4ItemDataDataEquipable {
|
|||
equipped: boolean;
|
||||
}
|
||||
|
||||
interface DS4ItemDataDataRollable {
|
||||
rollable?: boolean;
|
||||
}
|
||||
|
||||
interface DS4ItemDataDataProtective {
|
||||
armorValue: number;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { DS4Actor } from "../actor/actor";
|
||||
import { DS4 } from "../config";
|
||||
import { createCheckRoll } from "../rolls/check-factory";
|
||||
import notifications from "../ui/notifications";
|
||||
import { AttackType, DS4ItemData } from "./item-data";
|
||||
|
||||
/**
|
||||
|
@ -20,8 +21,8 @@ export class DS4Item extends Item<DS4ItemData> {
|
|||
const data = this.data.data;
|
||||
data.rank.total = data.rank.base + data.rank.mod;
|
||||
}
|
||||
if (this.data.type === "weapon") {
|
||||
this.data.data.rollable = true;
|
||||
if (this.data.type === "weapon" || this.data.type === "spell") {
|
||||
this.data.data.rollable = this.data.data.equipped;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,10 +47,14 @@ export class DS4Item extends Item<DS4ItemData> {
|
|||
if (!this.isOwnedItem()) {
|
||||
throw new Error(game.i18n.format("DS4.ErrorCannotRollUnownedItem", { name: this.name, id: this.id }));
|
||||
}
|
||||
if (this.data.type === "weapon") {
|
||||
await this.rollWeapon();
|
||||
} else {
|
||||
throw new Error(game.i18n.format("DS4.ErrorRollingForItemTypeNotPossible", { type: this.data.type }));
|
||||
|
||||
switch (this.data.type) {
|
||||
case "weapon":
|
||||
await this.rollWeapon();
|
||||
case "spell":
|
||||
await this.rollSpell();
|
||||
default:
|
||||
throw new Error(game.i18n.format("DS4.ErrorRollingForItemTypeNotPossible", { type: this.data.type }));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,6 +70,16 @@ export class DS4Item extends Item<DS4ItemData> {
|
|||
);
|
||||
}
|
||||
|
||||
if (!this.data.data.equipped) {
|
||||
throw new Error(
|
||||
game.i18n.format("DS4.ErrorItemMustBeEquippedToBeRolled", {
|
||||
name: this.name,
|
||||
id: this.id,
|
||||
type: this.data.type,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
const ownerDataData = ((this.actor as unknown) as DS4Actor).data.data; // TODO(types): Improve so that the concrete Actor type is known here
|
||||
const weaponBonus = this.data.data.weaponBonus;
|
||||
const combatValue = await this.getCombatValueKeyForAttackType(this.data.data.attackType);
|
||||
|
@ -76,6 +91,48 @@ export class DS4Item extends Item<DS4ItemData> {
|
|||
});
|
||||
}
|
||||
|
||||
private async rollSpell(): Promise<void> {
|
||||
if (!(this.data.type === "spell")) {
|
||||
throw new Error(
|
||||
game.i18n.format("DS4.ErrorWrongItemType", {
|
||||
actualType: this.data.type,
|
||||
expectedType: "spell",
|
||||
id: this.id,
|
||||
name: this.name,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.data.data.equipped) {
|
||||
throw new Error(
|
||||
game.i18n.format("DS4.ErrorItemMustBeEquippedToBeRolled", {
|
||||
name: this.name,
|
||||
id: this.id,
|
||||
type: this.data.type,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
const ownerDataData = ((this.actor as unknown) as DS4Actor).data.data; // TODO(types): Improve so that the concrete Actor type is known here
|
||||
const spellBonus = Number.isNumeric(this.data.data.bonus) ? parseInt(this.data.data.bonus) : undefined;
|
||||
if (spellBonus === undefined) {
|
||||
notifications.info(
|
||||
game.i18n.format("DS4.InfoManuallyEnterSpellBonus", {
|
||||
name: this.name,
|
||||
spellBonus: this.data.data.bonus,
|
||||
}),
|
||||
);
|
||||
}
|
||||
const spellType = this.data.data.spellType;
|
||||
const checkTargetValue = (ownerDataData.combatValues[spellType].total as number) + (spellBonus ?? 0);
|
||||
|
||||
await createCheckRoll(checkTargetValue, {
|
||||
rollMode: game.settings.get("core", "rollMode"),
|
||||
maxCritSuccess: ownerDataData.rolling.maximumCoupResult,
|
||||
minCritFailure: ownerDataData.rolling.minimumFumbleResult,
|
||||
});
|
||||
}
|
||||
|
||||
private async getCombatValueKeyForAttackType(attackType: AttackType): Promise<"meleeAttack" | "rangedAttack"> {
|
||||
if (attackType === "meleeRanged") {
|
||||
const { melee, ranged } = { ...DS4.i18n.attackTypes };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue