Skip to content
This repository was archived by the owner on Aug 10, 2025. It is now read-only.

Commit 96be7bf

Browse files
committed
add addToActor and removeFromActor triggers
1 parent cb7752c commit 96be7bf

5 files changed

Lines changed: 73 additions & 12 deletions

File tree

README.md

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,37 @@ Clicking this button opens an overview where you can edit that item's scripts.
1111

1212
A script receives the following arguments (very similar to a normal Foundry macro!) when run:
1313

14-
- `this` is a copy of the Script itself
15-
- `item` the item containing the script
16-
- `speaker` speaker data of the item's actor or the currently selected token or user's character
17-
- `actor` actor from the speaker data, usually the item's owner
18-
- `token` token from the speaker data
19-
- `character` the current user's character or null
20-
- `trigger` the trigger of the script, such as a button press or on item use.
14+
- `this` - is a copy of the Script itself
15+
- `item` - the item containing the script
16+
- `speaker` - speaker data of the item's Actor or the currently selected token or user's character
17+
- `actor` - actor from the speaker data, usually the item's owner
18+
- `token` - token from the speaker data
19+
- `character` - the current user's character or null
20+
- `trigger` - the trigger of the script, such as a button press or on item use.
2121
Is equal to `debug` when ran from the script's config sheet.
22-
- `message` the chat message which triggered the script (only `trigger === "button"`)
22+
- `optional` - an object containing additional, optional arguments
23+
- `optional.message` - The chat message containing the clicked button (if `trigger === "button"` is true)
2324

2425
Available triggers are currently:
2526

26-
- When using the item (`dnd5e.preUseItem`)
27+
- `preUseItem` - When using the item (Hook is `dnd5e.preUseItem`)
2728
- If you want to also have normal item usage, you can return `true` from the script
2829
- If you want to use `item.use()` inside the script, you can use `item.use({}, {skipScripts: true})`
29-
- A button in the item's chat card
30+
- `button` A button in the item's chat card that triggers the script when clicked
31+
- `addToActor` When the item is added to an actor
32+
- `removeFromActor` When the item is removed from an actor
3033

3134
## Changelog
3235

36+
### 0.2.0
37+
38+
- Improved README
39+
- Improved localization
40+
- Refactored optional script arguments into an object
41+
- Added script triggers `addToActor` and `removeFromActor` which will execute the given script when the item is added
42+
or removed from an actor
43+
- Added a module setting to toggle the visibility of the header button label
44+
3345
### 0.1.2
3446

3547
- Added a module setting to show the header button only to users with the specified minimum role

lang/en.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
"SCRIPTABLE-ITEMS": {
33
"Trigger": {
44
"button": "On Button Click",
5-
"preUseItem": "On Pre Use Item"
5+
"preUseItem": "On Pre Use Item",
6+
"addToActor": "When Added to Actor",
7+
"removeFromActor": "When Removed from Actor"
68
},
79
"Script": {
810
"Label": "Script",
@@ -12,7 +14,11 @@
1214
"Setting": {
1315
"headerButtonPermission": {
1416
"Name": "Button Permission Level",
15-
"Hint": "The 'Scriptable Items' button in item sheets will be hidden for any user with a role less than the chosen role."
17+
"Hint": "The minimum role required to see the 'Scriptable Items' button in the header of item sheets."
18+
},
19+
"showHeaderButtonLabel": {
20+
"Name": "Display Button Label",
21+
"Hint": "If checked, the button's label is displayed."
1622
}
1723
},
1824
"Dialog": {

scripts/constants.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ const FLAG = {
77
const TRIGGER = {
88
BUTTON: "button",
99
PRE_USE: "preUseItem",
10+
ADD_TO_ACTOR: "addToActor",
11+
REMOVE_FROM_ACTOR: "removeFromActor",
1012
};
1113
const SETTING = {
1214
HEADER_BUTTON_PERMISSION: "headerButtonPermission",

scripts/data/script-model.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ export class ScriptModel extends foundry.abstract.DataModel {
131131
"token",
132132
"character",
133133
"trigger",
134+
"optional",
134135
...argNames,
135136
`{${this.command}\n}`,
136137
);
@@ -145,12 +146,14 @@ export class ScriptModel extends foundry.abstract.DataModel {
145146
token,
146147
character,
147148
trigger,
149+
{ ...scope },
148150
...argValues,
149151
);
150152
} catch (err) {
151153
ui.notifications.error(
152154
"There was an error in your script syntax. See the console (F12) for details.",
153155
);
156+
console.error(err);
154157
}
155158
}
156159

scripts/scriptable-items.mjs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,41 @@ Hooks.on("dnd5e.renderChatMessage", (message, html) => {
9494
});
9595
});
9696
});
97+
98+
Hooks.on("createItem", async (item, options, userId) => {
99+
if (game.user.id !== userId) return;
100+
if (item.actor == null) return;
101+
102+
const scripts = ScriptModel.getAll(item).filter((x) =>
103+
x.triggers.has(TRIGGER.ADD_TO_ACTOR),
104+
);
105+
if (!scripts.length) return;
106+
107+
let script = scripts[0];
108+
if (script.length > 1) {
109+
const chosenScriptId = await ScriptChoiceDialog.create(scripts);
110+
if (chosenScriptId == null) return;
111+
script = scripts.find((x) => x.id === chosenScriptId);
112+
}
113+
114+
await script.executeScript({ trigger: TRIGGER.ADD_TO_ACTOR });
115+
});
116+
117+
Hooks.on("deleteItem", async (item, options, userId) => {
118+
if (game.user.id !== userId) return;
119+
if (item.actor == null) return;
120+
121+
const scripts = ScriptModel.getAll(item).filter((x) =>
122+
x.triggers.has(TRIGGER.REMOVE_FROM_ACTOR),
123+
);
124+
if (!scripts.length) return;
125+
126+
let script = scripts[0];
127+
if (script.length > 1) {
128+
const chosenScriptId = await ScriptChoiceDialog.create(scripts);
129+
if (chosenScriptId == null) return;
130+
script = scripts.find((x) => x.id === chosenScriptId);
131+
}
132+
133+
await script.executeScript({ trigger: TRIGGER.REMOVE_FROM_ACTOR });
134+
});

0 commit comments

Comments
 (0)