Add possibility to roll spells from sheet adnrequire spells and weapons to be equipped to be rolled

This commit is contained in:
Johannes Loher 2021-03-04 01:54:51 +01:00
parent 68c20ccdc6
commit 74ad0c7f24
4 changed files with 77 additions and 9 deletions

View file

@ -189,6 +189,8 @@
"DS4.ErrorRollingForItemTypeNotPossible": "Würfeln ist für Items vom Typ '{type}' nicht möglich.",
"DS4.ErrorWrongItemType": "Ein Item vom Type '{expectedType}' wurde erwartet aber das Item '{name}' ({id}) ist vom Typ '{actualType}'.",
"DS4.ErrorUnexpectedAttackType": "Unerwartete Angriffsart '{actualType}', erwartete Angriffarten: {expectedTypes}",
"DS4.ErrorItemMustBeEquippedToBeRolled": "Um für das Item '{name}' ({id}) vom Typ {type} zu würfeln, muss es ausgerüstet sein.",
"DS4.InfoManuallyEnterSpellBonus": "Der korrekte Wert für den Zauberbonus '{spellBonus}' des Zaubers '{name}' musss manuell angegeben werden.",
"DS4.InfoSystemUpdateStart": "Aktualisiere DS4 System von Migrationsversion {currentVersion} auf {targetVersion}. Bitte haben Sie etwas Geduld, schließen Sie nicht das Spiel und fahren Sie nicht den Server herunter.",
"DS4.InfoSystemUpdateCompleted": "Aktualisierung des DS4 Systems von Migrationsversion {currentVersion} auf {targetVersion} erfolgreich!",
"DS4.UnitRounds": "Runden",

View file

@ -189,6 +189,8 @@
"DS4.ErrorRollingForItemTypeNotPossible": "Rolling is not possible for items of type '{type}'.",
"DS4.ErrorWrongItemType": "Expected an item of type '{expectedType}' but item '{name}' ({id}) is of type '{actualType}'.",
"DS4.ErrorUnexpectedAttackType": "Unexpected attack type '{actualType}', expected it to be one of: {expectedTypes}",
"DS4.ErrorItemMustBeEquippedToBeRolled": "To roll for item '{name}' ({id}) of type {type}, it needs to be equipped.",
"DS4.InfoManuallyEnterSpellBonus": "The correct value of the spell bons '{spellBonus}' of the spell '{name}' needs to be entered by manually.",
"DS4.InfoSystemUpdateStart": "Migrating DS4 system from migration version {currentVersion} to {targetVersion}. Please be patient and do not close your game or shut down your server.",
"DS4.InfoSystemUpdateCompleted": "Migration of DS4 system from migration version {currentVersion} to {targetVersion} successful!",
"DS4.UnitRounds": "Rounds",

View file

@ -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;
}

View file

@ -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 };