Add functionality to create item macros via drag & drop
This commit is contained in:
parent
07bcd3a58e
commit
212295069f
9 changed files with 128 additions and 9 deletions
|
@ -192,7 +192,12 @@
|
||||||
"DS4.ErrorRollingForItemTypeNotPossible": "Würfeln ist für Items vom Typ '{type}' nicht möglich.",
|
"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.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.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.ErrorCanvasIsNotInitialized": "Canvas ist noch nicht initialisiert.",
|
||||||
|
"DS4.WarningItemMustBeEquippedToBeRolled": "Um für das Item '{name}' ({id}) vom Typ '{type}' zu würfeln, muss es ausgerüstet sein.",
|
||||||
|
"DS4.WarningMustControlActorToRollItemMacro": "Um ein Item Makro zu nutzen muss ein Aktor kontolliert werden.",
|
||||||
|
"DS4.WarningControlledActorDoesNotHaveItem": "Der kontrollierte Aktor '{actorName}' ({actorId}) hat kein Item mit der ID '{itemId}'.",
|
||||||
|
"DS4.WarningItemIsNotRollable": "Für das Item '{name}' ({id}) vom Typ '{type}' kann nicht gewürfelt werden.",
|
||||||
|
"DS4.WarningMacrosCanOnlyBeCreatedForOwnedItems": "Makros können nur für besessene Items angelegt werden.",
|
||||||
"DS4.InfoManuallyEnterSpellBonus": "Der korrekte Wert für den Zauberbonus '{spellBonus}' des Zaubers '{name}' musss manuell angegeben werden.",
|
"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.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.InfoSystemUpdateCompleted": "Aktualisierung des DS4 Systems von Migrationsversion {currentVersion} auf {targetVersion} erfolgreich!",
|
||||||
|
|
|
@ -192,8 +192,13 @@
|
||||||
"DS4.ErrorRollingForItemTypeNotPossible": "Rolling is not possible for items of type '{type}'.",
|
"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.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.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.ErrorCanvasIsNotInitialized": "Canvas is not initialized yet.",
|
||||||
"DS4.InfoManuallyEnterSpellBonus": "The correct value of the spell bons '{spellBonus}' of the spell '{name}' needs to be entered by manually.",
|
"DS4.WarningItemMustBeEquippedToBeRolled": "To roll for item '{name}' ({id}) of type '{type}', it needs to be equipped.",
|
||||||
|
"DS4.WarningMustControlActorToRollItemMacro": "You must control an actor to be able to use an item macro.",
|
||||||
|
"DS4.WarningControlledActorDoesNotHaveItem": "Your controlled actor '{actorName}' ({actorId}) does not have any item with the id '{itemId}'.",
|
||||||
|
"DS4.WarningItemIsNotRollable": "Item '{name}' ({id}) of type '{type}' is not rollable.",
|
||||||
|
"DS4.WarningMacrosCanOnlyBeCreatedForOwnedItems": "Macros can only be created for owned items.",
|
||||||
|
"DS4.InfoManuallyEnterSpellBonus": "The correct value of the spell bonus '{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.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.InfoSystemUpdateCompleted": "Migration of DS4 system from migration version {currentVersion} to {targetVersion} successful!",
|
||||||
"DS4.UnitRounds": "Rounds",
|
"DS4.UnitRounds": "Rounds",
|
||||||
|
|
|
@ -10,6 +10,8 @@ import { registerSystemSettings } from "./settings";
|
||||||
import { migration } from "./migrations";
|
import { migration } from "./migrations";
|
||||||
import registerHandlebarsHelpers from "./handlebars/handlebars-helpers";
|
import registerHandlebarsHelpers from "./handlebars/handlebars-helpers";
|
||||||
import registerHandlebarsPartials from "./handlebars/handlebars-partials";
|
import registerHandlebarsPartials from "./handlebars/handlebars-partials";
|
||||||
|
import { macros } from "./macros/macros";
|
||||||
|
import registerHooks from "./hooks/hooks";
|
||||||
|
|
||||||
Hooks.once("init", async () => {
|
Hooks.once("init", async () => {
|
||||||
console.log(`DS4 | Initializing the DS4 Game System\n${DS4.ASCII}`);
|
console.log(`DS4 | Initializing the DS4 Game System\n${DS4.ASCII}`);
|
||||||
|
@ -20,6 +22,7 @@ Hooks.once("init", async () => {
|
||||||
DS4,
|
DS4,
|
||||||
createCheckRoll,
|
createCheckRoll,
|
||||||
migration,
|
migration,
|
||||||
|
macros,
|
||||||
};
|
};
|
||||||
|
|
||||||
CONFIG.DS4 = DS4;
|
CONFIG.DS4 = DS4;
|
||||||
|
@ -43,6 +46,8 @@ Hooks.once("init", async () => {
|
||||||
|
|
||||||
await registerHandlebarsPartials();
|
await registerHandlebarsPartials();
|
||||||
registerHandlebarsHelpers();
|
registerHandlebarsHelpers();
|
||||||
|
|
||||||
|
registerHooks();
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
6
src/module/helpers.ts
Normal file
6
src/module/helpers.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export function getCanvas(): Canvas {
|
||||||
|
if (!(canvas instanceof Canvas) || !canvas.ready) {
|
||||||
|
throw new Error(game.i18n.localize("DS4.ErrorCanvasIsNotInitialized"));
|
||||||
|
}
|
||||||
|
return canvas;
|
||||||
|
}
|
5
src/module/hooks/hooks.ts
Normal file
5
src/module/hooks/hooks.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import registerHotbarHook from "./hotbar-drop";
|
||||||
|
|
||||||
|
export default function registerHooks(): void {
|
||||||
|
registerHotbarHook();
|
||||||
|
}
|
28
src/module/hooks/hotbar-drop.ts
Normal file
28
src/module/hooks/hotbar-drop.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { DS4Item } from "../item/item";
|
||||||
|
import { DS4ItemData } from "../item/item-data";
|
||||||
|
import { createItemMacro } from "../macros/item-macro";
|
||||||
|
import notifications from "../ui/notifications";
|
||||||
|
|
||||||
|
export default function registerHotbarHook(): void {
|
||||||
|
Hooks.on("hotbarDrop", async (hotbar: Hotbar, data: { type: string } & Record<string, unknown>, slot: string) => {
|
||||||
|
switch (data.type) {
|
||||||
|
case "Item": {
|
||||||
|
if (!("data" in data)) {
|
||||||
|
return notifications.warn(game.i18n.localize("DS4.WarningMacrosCanOnlyBeCreatedForOwnedItems"));
|
||||||
|
}
|
||||||
|
const itemData = data.data as DS4ItemData;
|
||||||
|
|
||||||
|
if (!DS4Item.rollableItemTypes.includes(itemData.type)) {
|
||||||
|
return notifications.warn(
|
||||||
|
game.i18n.format("DS4.WarningItemIsNotRollable", {
|
||||||
|
name: itemData.name,
|
||||||
|
id: itemData._id,
|
||||||
|
type: itemData.type,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await createItemMacro(itemData, slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ import { DS4Actor } from "../actor/actor";
|
||||||
import { DS4 } from "../config";
|
import { DS4 } from "../config";
|
||||||
import { createCheckRoll } from "../rolls/check-factory";
|
import { createCheckRoll } from "../rolls/check-factory";
|
||||||
import notifications from "../ui/notifications";
|
import notifications from "../ui/notifications";
|
||||||
import { AttackType, DS4ItemData } from "./item-data";
|
import { AttackType, DS4ItemData, ItemType } from "./item-data";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Item class for DS4
|
* The Item class for DS4
|
||||||
|
@ -40,6 +40,13 @@ export class DS4Item extends Item<DS4ItemData> {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of item types that are rollable.
|
||||||
|
*/
|
||||||
|
static get rollableItemTypes(): ItemType[] {
|
||||||
|
return ["weapon", "spell"];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Roll a check for a action with this item.
|
* Roll a check for a action with this item.
|
||||||
*/
|
*/
|
||||||
|
@ -71,8 +78,8 @@ export class DS4Item extends Item<DS4ItemData> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.data.data.equipped) {
|
if (!this.data.data.equipped) {
|
||||||
throw new Error(
|
return notifications.warn(
|
||||||
game.i18n.format("DS4.ErrorItemMustBeEquippedToBeRolled", {
|
game.i18n.format("DS4.WarningItemMustBeEquippedToBeRolled", {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
id: this.id,
|
id: this.id,
|
||||||
type: this.data.type,
|
type: this.data.type,
|
||||||
|
@ -104,8 +111,8 @@ export class DS4Item extends Item<DS4ItemData> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.data.data.equipped) {
|
if (!this.data.data.equipped) {
|
||||||
throw new Error(
|
return notifications.warn(
|
||||||
game.i18n.format("DS4.ErrorItemMustBeEquippedToBeRolled", {
|
game.i18n.format("DS4.WarningItemMustBeEquippedToBeRolled", {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
id: this.id,
|
id: this.id,
|
||||||
type: this.data.type,
|
type: this.data.type,
|
||||||
|
@ -158,7 +165,6 @@ export class DS4Item extends Item<DS4ItemData> {
|
||||||
}
|
}
|
||||||
return `${selectedAttackType}Attack` as const;
|
return `${selectedAttackType}Attack` as const;
|
||||||
},
|
},
|
||||||
render: () => undefined, // TODO(types): This is actually optional, remove when types are updated )
|
|
||||||
options: { jQuery: true },
|
options: { jQuery: true },
|
||||||
});
|
});
|
||||||
return answer;
|
return answer;
|
||||||
|
|
54
src/module/macros/item-macro.ts
Normal file
54
src/module/macros/item-macro.ts
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import { DS4Actor } from "../actor/actor";
|
||||||
|
import { getCanvas } from "../helpers";
|
||||||
|
import { DS4ItemData } from "../item/item-data";
|
||||||
|
import notifications from "../ui/notifications";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Macro from an item drop.
|
||||||
|
* Get an existing item macro if one exists, otherwise create a new one.
|
||||||
|
* @param itemData - The item data
|
||||||
|
* @param slot - The hotbar slot to use
|
||||||
|
*/
|
||||||
|
export async function createItemMacro(itemData: DS4ItemData, slot: string): Promise<void> {
|
||||||
|
const command = `game.ds4.macros.rollItemMacro("${itemData._id}");`;
|
||||||
|
const macro =
|
||||||
|
game.macros?.entities.find((m) => m.name === itemData.name && m.data.command === command) ??
|
||||||
|
(await Macro.create(
|
||||||
|
{
|
||||||
|
command,
|
||||||
|
name: itemData.name,
|
||||||
|
type: "script",
|
||||||
|
img: itemData.img,
|
||||||
|
flags: { "ds4.itemMacro": true },
|
||||||
|
},
|
||||||
|
{ displaySheet: false },
|
||||||
|
));
|
||||||
|
game.user?.assignHotbarMacro(macro, (slot as unknown) as number); // TODO(types): adjust so that cast is not needed, slot should be an optional string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the item macro for the given itemId.
|
||||||
|
* @param itemId
|
||||||
|
*/
|
||||||
|
export async function rollItemMacro(itemId: string): Promise<void> {
|
||||||
|
const speaker = ChatMessage.getSpeaker();
|
||||||
|
const actor = (getCanvas().tokens.get(speaker.token ?? "")?.actor ?? game.actors?.get(speaker.actor ?? "")) as
|
||||||
|
| DS4Actor
|
||||||
|
| null
|
||||||
|
| undefined;
|
||||||
|
if (!actor) {
|
||||||
|
return notifications.warn(game.i18n.localize("DS4.WarningMustControlActorToRollItemMacro"));
|
||||||
|
}
|
||||||
|
const item = actor.items?.get(itemId);
|
||||||
|
if (!item) {
|
||||||
|
return notifications.warn(
|
||||||
|
game.i18n.format("DS4.WarningControlledActorDoesNotHaveItem", {
|
||||||
|
actorName: actor.name,
|
||||||
|
actorId: actor.id,
|
||||||
|
itemId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return item.roll();
|
||||||
|
}
|
5
src/module/macros/macros.ts
Normal file
5
src/module/macros/macros.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { rollItemMacro } from "./item-macro";
|
||||||
|
|
||||||
|
export const macros = {
|
||||||
|
rollItemMacro,
|
||||||
|
};
|
Loading…
Reference in a new issue