diff --git a/MaterialDeck.js b/MaterialDeck.js
index 85e07ff..dda26c7 100644
--- a/MaterialDeck.js
+++ b/MaterialDeck.js
@@ -72,14 +72,28 @@ async function analyzeWSmessage(msg){
}
if (data.type == "version" && data.source == "SD") {
- /*
- console.log(data);
const minimumSDversion = game.modules.get("MaterialDeck").data.minimumSDversion.replace('v','');
const minimumMSversion = game.modules.get("MaterialDeck").data.minimumMSversion;
- console.log('SD',minimumSDversion,data.version)
- if (data.version < minimumSDversion) console.log('SD: nope')
- else console.log('SD: yes');
- */
+
+ if (data.version < minimumSDversion) {
+ let d = new Dialog({
+ title: "Material Deck: Update Needed",
+ content: "
The Stream Deck plugin version you're using is v" + data.version + ", which is outdated.
Update to v" + minimumSDversion + " or newer.
",
+ buttons: {
+ download: {
+ icon: '',
+ label: "Update",
+ callback: () => window.open("https://github.com/CDeenen/MaterialDeck_SD/releases")
+ },
+ ignore: {
+ icon: '',
+ label: "Ignore"
+ }
+ },
+ default: "download"
+ });
+ d.render(true);
+ }
}
if (data == undefined || data.payload == undefined) return;
@@ -89,6 +103,8 @@ async function analyzeWSmessage(msg){
const context = data.context;
const coordinates = data.payload.coordinates;
const settings = data.payload.settings;
+ const device = data.device;
+
if (data.data == 'init'){
@@ -96,33 +112,33 @@ async function analyzeWSmessage(msg){
if (event == 'willAppear' || event == 'didReceiveSettings'){
if (coordinates == undefined) return;
streamDeck.setScreen(action);
- streamDeck.setContext(action,context,coordinates,settings);
+ await streamDeck.setContext(device,data.size,data.deviceIteration,action,context,coordinates,settings);
if (action == 'token'){
tokenControl.active = true;
- tokenControl.update(selectedTokenId);
+ tokenControl.update(device,selectedTokenId,device);
}
else if (action == 'move')
- move.update(settings,context);
+ move.update(settings,context,device);
else if (action == 'macro')
- macroControl.update(settings,context);
+ macroControl.update(settings,context,device);
else if (action == 'combattracker')
- combatTracker.update(settings,context);
+ combatTracker.update(settings,context,device);
else if (action == 'playlist')
- playlistControl.update(settings,context);
+ playlistControl.update(settings,context,device);
else if (action == 'soundboard')
- soundboard.update(settings,context);
+ soundboard.update(settings,context,device);
else if (action == 'other')
- otherControls.update(settings,context);
+ otherControls.update(settings,context,device);
else if (action == 'external')
- externalModules.update(settings,context);
+ externalModules.update(settings,context,device);
else if (action == 'scene')
- sceneControl.update(settings,context);
+ sceneControl.update(settings,context,device);
}
else if (event == 'willDisappear'){
if (coordinates == undefined) return;
- streamDeck.clearContext(action,coordinates,context);
+ streamDeck.clearContext(device,action,coordinates,context);
}
else if (event == 'keyDown'){
@@ -133,15 +149,15 @@ async function analyzeWSmessage(msg){
else if (action == 'macro')
macroControl.keyPress(settings);
else if (action == 'combattracker')
- combatTracker.keyPress(settings,context);
+ combatTracker.keyPress(settings,context,device);
else if (action == 'playlist')
- playlistControl.keyPress(settings,context);
+ playlistControl.keyPress(settings,context,device);
else if (action == 'soundboard')
soundboard.keyPressDown(settings);
else if (action == 'other')
- otherControls.keyPress(settings,context);
+ otherControls.keyPress(settings,context,device);
else if (action == 'external')
- externalModules.keyPress(settings,context);
+ externalModules.keyPress(settings,context,device);
else if (action == 'scene')
sceneControl.keyPress(settings);
}
diff --git a/changelog.md b/changelog.md
index d88103a..b4fb7f7 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,29 @@
# Changelog Material Deck Module
-## v1.3.3
+### v1.4.0
+Additions:
+
+- Support for connecting multiple Stream Decks at the same time. Please note that performance decreases with each extra Stream Deck
+- Other Actions: Added 'Token Roll Options'. This can toggle token rolls between showing a dialog and skipping the dialog and rolling normally or with advantage or disadvantage
+- If the SD plugin version you're using is outdated, you now get a pop-up to notify you of this and direct you to the download page
+- Added a module setting to set how dark the default white images should be. Can be lowered for improved readability of the text
+- Token Action => Stats: Added option to prepend text to the title, so you can set the stat to, for example, strength, and put 'STR: ' in the prepend textbox to display, for example, 'STR: +2'
+
+
+Fixes:
+
+- Token Action => Skill Roll: Setting wasn't saved in SD app
+- Token Action => Roll Ability: Rolling ability checks was broken for some systems
+- Token Action => Stats => Display HP: Read overlay indicating HP in the heart icon was also drawn when 'Display Token Icon' was enabled
+- Token Action => Stats: Added default images for all dnd5e abilities, saves and skills
+
+
+
+Compatible server app and SD plugin:
+Material Server v1.0.2 (unchanged): https://github.com/CDeenen/MaterialServer/releases
+SD plugin v1.4.0 (must be updated!): https://github.com/CDeenen/MaterialDeck_SD/releases
+
+
+### v1.3.3
Additions:
- Other Actions => Open Sidebar Tab: Action now indicates which sidebar tab is open (only works on Foundry 0.8.x)
@@ -30,7 +54,7 @@ Other:
Material Server v1.0.2 (unchanged): https://github.com/CDeenen/MaterialServer/releases
SD plugin v1.3.4 (must be updated!): https://github.com/CDeenen/MaterialDeck_SD/releases
-## v1.3.2 - 11-03-2021
+### v1.3.2 - 11-03-2021
Additions:
- Added support for the Multi Action provided by the SD app
@@ -50,7 +74,6 @@ Other:
- Macro Action: Improved the way Hotbar Uses are displayed, it is now displayed in a box similar to how the module looks in Foundry
- Made the way images are generated more flexible to make future additions easier
-
@@ -90,7 +113,7 @@ Additions:
- External Modules => Added support for the 'Shared Vision' module
- External Modules => Added support for the 'Lock View' module
- External Modules => Added support for the 'Not Your Turn' module
-
Fixes:
- Token Action => OnClick: Fixed conditions for pf1e and dnd3.5e
@@ -323,4 +346,4 @@ SD plugin v0.7.0
Compatible server app and SD plugin:
Server v0.2.4
-SD plugin v0.7.1
\ No newline at end of file
+SD plugin v0.7.1
diff --git a/img/.thumb/MaterialFoundry512x512.png.jpg b/img/.thumb/MaterialFoundry512x512.png.jpg
new file mode 100644
index 0000000..56f4c07
Binary files /dev/null and b/img/.thumb/MaterialFoundry512x512.png.jpg differ
diff --git a/img/MaterialFoundry512x512.png b/img/MaterialFoundry512x512.png
new file mode 100644
index 0000000..f362917
Binary files /dev/null and b/img/MaterialFoundry512x512.png differ
diff --git a/img/other/.thumb/d20.png.jpg b/img/other/.thumb/d20.png.jpg
new file mode 100644
index 0000000..8a07cfb
Binary files /dev/null and b/img/other/.thumb/d20.png.jpg differ
diff --git a/img/other/SOURCES.txt b/img/other/SOURCES.txt
index 4437a7b..f9c909d 100644
--- a/img/other/SOURCES.txt
+++ b/img/other/SOURCES.txt
@@ -1,2 +1,3 @@
other.png: Made using https://www.elgato.com/en/gaming/keycreator
-cogs.png: Edited from https://fontawesome.com/icons/cogs?style=solid
\ No newline at end of file
+cogs.png: Edited from https://fontawesome.com/icons/cogs?style=solid
+d20.png: Edited from https://game-icons.net/1x1/delapouite/dice-twenty-faces-twenty.html
\ No newline at end of file
diff --git a/img/other/d20.png b/img/other/d20.png
new file mode 100644
index 0000000..4fbe195
Binary files /dev/null and b/img/other/d20.png differ
diff --git a/img/token/.thumb/temp_hp_empty.png.jpg b/img/token/.thumb/temp_hp_empty.png.jpg
new file mode 100644
index 0000000..94323a3
Binary files /dev/null and b/img/token/.thumb/temp_hp_empty.png.jpg differ
diff --git a/img/token/SOURCES.txt b/img/token/SOURCES.txt
index 2a7ae56..e19ef4f 100644
--- a/img/token/SOURCES.txt
+++ b/img/token/SOURCES.txt
@@ -1,5 +1,5 @@
ac.webp: Foundry's icon folder, original name: heater-steel-worn.webp
-hp.png: made using Elgato's key creator: https://www.elgato.com/en/gaming/keycreator
+hp.png, hp_empty.png and temp_hp_empty.png: made using/modified from Elgato's key creator: https://www.elgato.com/en/gaming/keycreator
init.png: freepngimg.com, color inverted, from: https://freepngimg.com/png/81025-art-dice-dungeons-system-dragons-d20-triangle/icon
speed.webp: Foundry's icon folder, original name: shoes-collared-leather-blue.webp
mystery-man.png: Foundry's icon folder, converted from .svg
\ No newline at end of file
diff --git a/img/token/abilities/.thumb/cha.png.jpg b/img/token/abilities/.thumb/cha.png.jpg
new file mode 100644
index 0000000..0fe0835
Binary files /dev/null and b/img/token/abilities/.thumb/cha.png.jpg differ
diff --git a/img/token/abilities/.thumb/cons.png.jpg b/img/token/abilities/.thumb/cons.png.jpg
new file mode 100644
index 0000000..aec6541
Binary files /dev/null and b/img/token/abilities/.thumb/cons.png.jpg differ
diff --git a/img/token/abilities/.thumb/dex.png.jpg b/img/token/abilities/.thumb/dex.png.jpg
new file mode 100644
index 0000000..716d8f7
Binary files /dev/null and b/img/token/abilities/.thumb/dex.png.jpg differ
diff --git a/img/token/abilities/.thumb/int.png.jpg b/img/token/abilities/.thumb/int.png.jpg
new file mode 100644
index 0000000..4b1787c
Binary files /dev/null and b/img/token/abilities/.thumb/int.png.jpg differ
diff --git a/img/token/abilities/.thumb/str.png.jpg b/img/token/abilities/.thumb/str.png.jpg
new file mode 100644
index 0000000..b3bb184
Binary files /dev/null and b/img/token/abilities/.thumb/str.png.jpg differ
diff --git a/img/token/abilities/.thumb/wis.png.jpg b/img/token/abilities/.thumb/wis.png.jpg
new file mode 100644
index 0000000..7ce2396
Binary files /dev/null and b/img/token/abilities/.thumb/wis.png.jpg differ
diff --git a/img/token/abilities/SOURCES.txt b/img/token/abilities/SOURCES.txt
new file mode 100644
index 0000000..583383b
--- /dev/null
+++ b/img/token/abilities/SOURCES.txt
@@ -0,0 +1,7 @@
+All images licenced under CC BY 3.0. Grabbed from game-icons.net
+str.png: https://game-icons.net/1x1/delapouite/weight-lifting-up.html
+dex.png: https://game-icons.net/1x1/darkzaitzev/acrobatic.html
+cons.png: https://game-icons.net/1x1/zeromancer/heart-plus.html
+int.png: https://game-icons.net/1x1/lorc/bookmarklet.html
+wis.png: https://game-icons.net/1x1/delapouite/wisdom.html
+cha.png: https://game-icons.net/1x1/lorc/icicles-aura.html
\ No newline at end of file
diff --git a/img/token/abilities/cha.png b/img/token/abilities/cha.png
new file mode 100644
index 0000000..cd678db
Binary files /dev/null and b/img/token/abilities/cha.png differ
diff --git a/img/token/abilities/cons.png b/img/token/abilities/cons.png
new file mode 100644
index 0000000..bab1df8
Binary files /dev/null and b/img/token/abilities/cons.png differ
diff --git a/img/token/abilities/dex.png b/img/token/abilities/dex.png
new file mode 100644
index 0000000..523b713
Binary files /dev/null and b/img/token/abilities/dex.png differ
diff --git a/img/token/abilities/int.png b/img/token/abilities/int.png
new file mode 100644
index 0000000..bb9ecb1
Binary files /dev/null and b/img/token/abilities/int.png differ
diff --git a/img/token/abilities/str.png b/img/token/abilities/str.png
new file mode 100644
index 0000000..1beae3c
Binary files /dev/null and b/img/token/abilities/str.png differ
diff --git a/img/token/abilities/wis.png b/img/token/abilities/wis.png
new file mode 100644
index 0000000..ee4a5ce
Binary files /dev/null and b/img/token/abilities/wis.png differ
diff --git a/img/token/skills/.thumb/acr.png.jpg b/img/token/skills/.thumb/acr.png.jpg
new file mode 100644
index 0000000..2322149
Binary files /dev/null and b/img/token/skills/.thumb/acr.png.jpg differ
diff --git a/img/token/skills/.thumb/ani.png.jpg b/img/token/skills/.thumb/ani.png.jpg
new file mode 100644
index 0000000..8eac9af
Binary files /dev/null and b/img/token/skills/.thumb/ani.png.jpg differ
diff --git a/img/token/skills/.thumb/arc.png.jpg b/img/token/skills/.thumb/arc.png.jpg
new file mode 100644
index 0000000..fd06c23
Binary files /dev/null and b/img/token/skills/.thumb/arc.png.jpg differ
diff --git a/img/token/skills/.thumb/ath.png.jpg b/img/token/skills/.thumb/ath.png.jpg
new file mode 100644
index 0000000..695e260
Binary files /dev/null and b/img/token/skills/.thumb/ath.png.jpg differ
diff --git a/img/token/skills/.thumb/dec.png.jpg b/img/token/skills/.thumb/dec.png.jpg
new file mode 100644
index 0000000..bf18c75
Binary files /dev/null and b/img/token/skills/.thumb/dec.png.jpg differ
diff --git a/img/token/skills/.thumb/his.png.jpg b/img/token/skills/.thumb/his.png.jpg
new file mode 100644
index 0000000..1bde4d1
Binary files /dev/null and b/img/token/skills/.thumb/his.png.jpg differ
diff --git a/img/token/skills/.thumb/ins.png.jpg b/img/token/skills/.thumb/ins.png.jpg
new file mode 100644
index 0000000..40c8965
Binary files /dev/null and b/img/token/skills/.thumb/ins.png.jpg differ
diff --git a/img/token/skills/.thumb/inv.png.jpg b/img/token/skills/.thumb/inv.png.jpg
new file mode 100644
index 0000000..2009316
Binary files /dev/null and b/img/token/skills/.thumb/inv.png.jpg differ
diff --git a/img/token/skills/.thumb/itm.png.jpg b/img/token/skills/.thumb/itm.png.jpg
new file mode 100644
index 0000000..444585c
Binary files /dev/null and b/img/token/skills/.thumb/itm.png.jpg differ
diff --git a/img/token/skills/.thumb/med.png.jpg b/img/token/skills/.thumb/med.png.jpg
new file mode 100644
index 0000000..a9277b8
Binary files /dev/null and b/img/token/skills/.thumb/med.png.jpg differ
diff --git a/img/token/skills/.thumb/nat.png.jpg b/img/token/skills/.thumb/nat.png.jpg
new file mode 100644
index 0000000..c2f6fe6
Binary files /dev/null and b/img/token/skills/.thumb/nat.png.jpg differ
diff --git a/img/token/skills/.thumb/per.png.jpg b/img/token/skills/.thumb/per.png.jpg
new file mode 100644
index 0000000..18816fa
Binary files /dev/null and b/img/token/skills/.thumb/per.png.jpg differ
diff --git a/img/token/skills/.thumb/prc.png.jpg b/img/token/skills/.thumb/prc.png.jpg
new file mode 100644
index 0000000..41f5756
Binary files /dev/null and b/img/token/skills/.thumb/prc.png.jpg differ
diff --git a/img/token/skills/.thumb/prf.png.jpg b/img/token/skills/.thumb/prf.png.jpg
new file mode 100644
index 0000000..4913f95
Binary files /dev/null and b/img/token/skills/.thumb/prf.png.jpg differ
diff --git a/img/token/skills/.thumb/rel.png.jpg b/img/token/skills/.thumb/rel.png.jpg
new file mode 100644
index 0000000..b9b450a
Binary files /dev/null and b/img/token/skills/.thumb/rel.png.jpg differ
diff --git a/img/token/skills/.thumb/slt.png.jpg b/img/token/skills/.thumb/slt.png.jpg
new file mode 100644
index 0000000..8fc6eaa
Binary files /dev/null and b/img/token/skills/.thumb/slt.png.jpg differ
diff --git a/img/token/skills/.thumb/ste.png.jpg b/img/token/skills/.thumb/ste.png.jpg
new file mode 100644
index 0000000..8773530
Binary files /dev/null and b/img/token/skills/.thumb/ste.png.jpg differ
diff --git a/img/token/skills/.thumb/sur.png.jpg b/img/token/skills/.thumb/sur.png.jpg
new file mode 100644
index 0000000..af23858
Binary files /dev/null and b/img/token/skills/.thumb/sur.png.jpg differ
diff --git a/img/token/skills/SOURCES.txt b/img/token/skills/SOURCES.txt
new file mode 100644
index 0000000..0d2fb22
--- /dev/null
+++ b/img/token/skills/SOURCES.txt
@@ -0,0 +1,19 @@
+All images licenced under CC BY 3.0. Grabbed from game-icons.net
+acr.png: https://game-icons.net/1x1/delapouite/contortionist.html
+ani.png: https://game-icons.net/1x1/delapouite/cavalry.html
+arc.png: https://game-icons.net/1x1/delapouite/spell-book.html
+ath.png: https://game-icons.net/1x1/lorc/muscle-up.html
+dec.png: https://game-icons.net/1x1/delapouite/convince.html
+his.png: https://game-icons.net/1x1/delapouite/backward-time.html
+ins.png: https://game-icons.net/1x1/lorc/light-bulb.html
+itm.png: https://game-icons.net/1x1/lorc/one-eyed.html
+inv.png: https://game-icons.net/1x1/lorc/magnifying-glass.html
+med.png: https://game-icons.net/1x1/delapouite/first-aid-kit.html
+nat.png: https://game-icons.net/1x1/delapouite/forest.html
+prc.png: https://game-icons.net/1x1/lorc/semi-closed-eye.html
+prf.png: https://game-icons.net/1x1/lorc/sing.html
+per.png: https://game-icons.net/1x1/delapouite/public-speaker.html
+rel.png: https://game-icons.net/1x1/lorc/holy-grail.html
+slt.png: https://game-icons.net/1x1/lorc/snatch.html
+ste.png: https://game-icons.net/1x1/lorc/cloak-dagger.html
+sur.png: https://game-icons.net/1x1/delapouite/pyre.html
\ No newline at end of file
diff --git a/img/token/skills/acr.png b/img/token/skills/acr.png
new file mode 100644
index 0000000..1e34bb8
Binary files /dev/null and b/img/token/skills/acr.png differ
diff --git a/img/token/skills/ani.png b/img/token/skills/ani.png
new file mode 100644
index 0000000..666bd13
Binary files /dev/null and b/img/token/skills/ani.png differ
diff --git a/img/token/skills/arc.png b/img/token/skills/arc.png
new file mode 100644
index 0000000..d7e3f1d
Binary files /dev/null and b/img/token/skills/arc.png differ
diff --git a/img/token/skills/ath.png b/img/token/skills/ath.png
new file mode 100644
index 0000000..07de39b
Binary files /dev/null and b/img/token/skills/ath.png differ
diff --git a/img/token/skills/dec.png b/img/token/skills/dec.png
new file mode 100644
index 0000000..5e3868e
Binary files /dev/null and b/img/token/skills/dec.png differ
diff --git a/img/token/skills/his.png b/img/token/skills/his.png
new file mode 100644
index 0000000..b294333
Binary files /dev/null and b/img/token/skills/his.png differ
diff --git a/img/token/skills/ins.png b/img/token/skills/ins.png
new file mode 100644
index 0000000..d5f4a53
Binary files /dev/null and b/img/token/skills/ins.png differ
diff --git a/img/token/skills/inv.png b/img/token/skills/inv.png
new file mode 100644
index 0000000..c93b63d
Binary files /dev/null and b/img/token/skills/inv.png differ
diff --git a/img/token/skills/itm.png b/img/token/skills/itm.png
new file mode 100644
index 0000000..51cad98
Binary files /dev/null and b/img/token/skills/itm.png differ
diff --git a/img/token/skills/med.png b/img/token/skills/med.png
new file mode 100644
index 0000000..c0dc115
Binary files /dev/null and b/img/token/skills/med.png differ
diff --git a/img/token/skills/nat.png b/img/token/skills/nat.png
new file mode 100644
index 0000000..aeac202
Binary files /dev/null and b/img/token/skills/nat.png differ
diff --git a/img/token/skills/per.png b/img/token/skills/per.png
new file mode 100644
index 0000000..3b247f6
Binary files /dev/null and b/img/token/skills/per.png differ
diff --git a/img/token/skills/prc.png b/img/token/skills/prc.png
new file mode 100644
index 0000000..8bc7c37
Binary files /dev/null and b/img/token/skills/prc.png differ
diff --git a/img/token/skills/prf.png b/img/token/skills/prf.png
new file mode 100644
index 0000000..78bfc53
Binary files /dev/null and b/img/token/skills/prf.png differ
diff --git a/img/token/skills/rel.png b/img/token/skills/rel.png
new file mode 100644
index 0000000..b6bbe8a
Binary files /dev/null and b/img/token/skills/rel.png differ
diff --git a/img/token/skills/slt.png b/img/token/skills/slt.png
new file mode 100644
index 0000000..932d847
Binary files /dev/null and b/img/token/skills/slt.png differ
diff --git a/img/token/skills/ste.png b/img/token/skills/ste.png
new file mode 100644
index 0000000..7b12381
Binary files /dev/null and b/img/token/skills/ste.png differ
diff --git a/img/token/skills/sur.png b/img/token/skills/sur.png
new file mode 100644
index 0000000..2cfc6c6
Binary files /dev/null and b/img/token/skills/sur.png differ
diff --git a/img/token/temp_hp_empty.png b/img/token/temp_hp_empty.png
new file mode 100644
index 0000000..4dc7321
Binary files /dev/null and b/img/token/temp_hp_empty.png differ
diff --git a/lang/en.json b/lang/en.json
index c8a24a7..896c025 100644
--- a/lang/en.json
+++ b/lang/en.json
@@ -21,6 +21,8 @@
"MaterialDeck.Sett.ServerAddrHint": "The IP address and port of Material Server. The default value will work for 99% of people, only change this if you know what you're doing. Must follow the format [ip_address]:[port], for example: 'localhost:3001' or '192.168.1.1:4000'.",
"MaterialDeck.Sett.ImageBuffer": "Image Cache Size",
"MaterialDeck.Sett.ImageBufferHint": "Sets the amount of images to store in the image cache. The image cache will locally store all images sent to the Stream Deck. This improves the update speed, but increases memory usage.",
+ "MaterialDeck.Sett.ImageBrightness": "Image Brightness",
+ "MaterialDeck.Sett.ImageBrightnessHint": "Sets the brightness of the default white images. If the Image Cache Size is bigger than 0, perform a refresh for instant results.",
"MaterialDeck.PL.Unrestricted": "Unrestricted",
"MaterialDeck.PL.OneTrackPlaylist": "One track per playlist",
diff --git a/module.json b/module.json
index db570d6..233b252 100644
--- a/module.json
+++ b/module.json
@@ -2,8 +2,8 @@
"name": "MaterialDeck",
"title": "Material Deck",
"description": "Material Deck allows you to control Foundry using an Elgato Stream Deck",
- "version": "1.3.3",
- "minimumSDversion": "1.3.4",
+ "version": "1.4.0",
+ "minimumSDversion": "1.4.0",
"minimumMSversion": "1.0.2",
"author": "CDeenen",
"esmodules": [
diff --git a/src/combattracker.js b/src/combattracker.js
index 798aa2d..02a7193 100644
--- a/src/combattracker.js
+++ b/src/combattracker.js
@@ -10,14 +10,16 @@ export class CombatTracker{
async updateAll(){
if (this.active == false) return;
- for (let i=0; i<32; i++){
- const data = streamDeck.buttonContext[i];
- if (data == undefined || data.action != 'combattracker') continue;
- await this.update(data.settings,data.context);
+ for (let device of streamDeck.buttonContext) {
+ for (let i=0; i c.name == control);
if (selectedControl != undefined){
if (selectedControl.visible == false) {
- streamDeck.noPermission(context,false);
+ streamDeck.noPermission(context,device,false);
return;
}
if (tool == 'open'){ //open category
@@ -189,7 +202,7 @@ export class OtherControls{
const selectedTool = selectedControl.tools.find(t => t.name == tool);
if (selectedTool != undefined){
if (selectedTool.visible == false) {
- streamDeck.noPermission(context,false);
+ streamDeck.noPermission(context,device,false);
return;
}
txt = game.i18n.localize(selectedTool.title);
@@ -204,7 +217,7 @@ export class OtherControls{
}
}
}
- streamDeck.setIcon(context,src,{background:background,ring:2,ringColor:ringColor});
+ streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor});
streamDeck.setTitle(txt,context);
}
@@ -213,18 +226,19 @@ export class OtherControls{
if (canvas.scene == null) return;
const control = settings.control ? settings.control : 'dispControls';
const tool = settings.tool ? settings.tool : 'open';
-
+
if (control == 'dispControls'){ //displayed controls
let controlNr = parseInt(settings.controlNr);
if (isNaN(controlNr)) controlNr = 1;
controlNr--;
const selectedControl = ui.controls.controls[controlNr];
+
if (selectedControl != undefined){
if (selectedControl.visible == false) {
- streamDeck.noPermission(context,false);
+ streamDeck.noPermission(context,device,false);
return;
}
- ui.controls.activeControl = 'token';
+ ui.controls.activeControl = selectedControl.name;
selectedControl.activeTool = selectedControl.activeTool;
canvas.getLayer(selectedControl.layer).activate();
}
@@ -236,13 +250,13 @@ export class OtherControls{
const selectedControl = ui.controls.controls.find(c => c.name == ui.controls.activeControl);
if (selectedControl != undefined){
if (selectedControl.visible == false) {
- streamDeck.noPermission(context,false);
+ streamDeck.noPermission(context,device,false);
return;
}
const selectedTool = selectedControl.tools[controlNr];
if (selectedTool != undefined){
if (selectedTool.visible == false) {
- streamDeck.noPermission(context,false);
+ streamDeck.noPermission(context,device,false);
return;
}
if (selectedTool.toggle) {
@@ -261,11 +275,11 @@ export class OtherControls{
const selectedControl = ui.controls.controls.find(c => c.name == control);
if (selectedControl != undefined){
if (selectedControl.visible == false) {
- streamDeck.noPermission(context,false);
+ streamDeck.noPermission(context,device,false);
return;
}
if (tool == 'open'){ //open category
- ui.controls.activeControl = 'token';
+ ui.controls.activeControl = control;
selectedControl.activeTool = selectedControl.activeTool;
canvas.getLayer(selectedControl.layer).activate();
}
@@ -273,7 +287,7 @@ export class OtherControls{
const selectedTool = selectedControl.tools.find(t => t.name == tool);
if (selectedTool != undefined){
if (selectedTool.visible == false) {
- streamDeck.noPermission(context,false);
+ streamDeck.noPermission(context,device,false);
return;
}
ui.controls.activeControl = control;
@@ -296,9 +310,9 @@ export class OtherControls{
//////////////////////////////////////////////////////////////////////////////////////////
- updateDarkness(settings,context,options={}){
+ updateDarkness(settings,context,device,options={}){
if (MODULE.getPermission('OTHER','DARKNESS') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
const func = settings.darknessFunction ? settings.darknessFunction : 'value';
@@ -321,7 +335,7 @@ export class OtherControls{
txt += darkness;
}
streamDeck.setTitle(txt,context);
- streamDeck.setIcon(context,src,{background:background});
+ streamDeck.setIcon(context,device,src,{background:background,overlay:true});
}
keyPressDarkness(settings) {
@@ -342,9 +356,9 @@ export class OtherControls{
//////////////////////////////////////////////////////////////////////////////////////////
- updateRollDice(settings,context,options={}){
+ updateRollDice(settings,context,device,options={}){
if (MODULE.getPermission('OTHER','DICE') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
const background = settings.background ? settings.background : '#000000';
@@ -353,10 +367,10 @@ export class OtherControls{
if (settings.displayDiceName) txt = 'Roll: ' + settings.rollDiceFormula;
streamDeck.setTitle(txt,context);
- streamDeck.setIcon(context,'',{background:background});
+ streamDeck.setIcon(context,device,'',{background:background});
}
- keyPressRollDice(settings,context){
+ keyPressRollDice(settings,context,device){
if (MODULE.getPermission('OTHER','DICE') == false ) return;
if (settings.rollDiceFormula == undefined || settings.rollDiceFormula == '') return;
const rollFunction = settings.rollDiceFunction ? settings.rollDiceFunction : 'public';
@@ -394,11 +408,11 @@ export class OtherControls{
//////////////////////////////////////////////////////////////////////////////////////////
- updateRollTable(settings,context,options={}){
+ updateRollTable(settings,context,device,options={}){
const name = settings.rollTableName;
if (name == undefined) return;
if (MODULE.getPermission('OTHER','TABLES') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
@@ -414,13 +428,13 @@ export class OtherControls{
}
else {
if (table.permission < 2 && MODULE.getPermission('OTHER','TABLES_ALL') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
}
streamDeck.setTitle(txt,context);
- streamDeck.setIcon(context,src,{background:background});
+ streamDeck.setIcon(context,device,src,{background:background});
}
keyPressRollTable(settings){
@@ -479,9 +493,9 @@ export class OtherControls{
return icon;
}
- updateSidebar(settings,context,options={}){
+ updateSidebar(settings,context,device,options={}){
if (MODULE.getPermission('OTHER','SIDEBAR') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
const popOut = settings.sidebarPopOut ? settings.sidebarPopOut : false;
@@ -500,7 +514,7 @@ export class OtherControls{
const icon = settings.displaySidebarIcon ? this.getSidebarIcon(sidebarTab) : '';
streamDeck.setTitle(name,context);
- streamDeck.setIcon(context,icon,{background:background,ring:2,ringColor:ringColor});
+ streamDeck.setIcon(context,device,icon,{background:background,ring:2,ringColor:ringColor});
}
keyPressSidebar(settings){
@@ -523,7 +537,7 @@ export class OtherControls{
//////////////////////////////////////////////////////////////////////////////////////////
- updateCompendiumBrowser(settings,context,options={}){
+ updateCompendiumBrowser(settings,context,device,options={}){
let rendered = options.renderCompendiumBrowser;
if (rendered == undefined && game.system.id == "pf2e") rendered = (document.getElementById("app-1") != null);
else if (rendered == undefined) rendered = (document.getElementById("compendium-popout") != null);
@@ -534,7 +548,7 @@ export class OtherControls{
const txt = settings.displayCompendiumName ? name : '';
streamDeck.setTitle(txt,context);
- streamDeck.setIcon(context,"",{background:background,ring:2,ringColor:ringColor});
+ streamDeck.setIcon(context,device,"",{background:background,ring:2,ringColor:ringColor});
}
keyPressCompendiumBrowser(settings){
@@ -553,11 +567,11 @@ export class OtherControls{
//////////////////////////////////////////////////////////////////////////////////////////
- updateCompendium(settings,context,options={}){
+ updateCompendium(settings,context,device,options={}){
const name = settings.compendiumName;
if (name == undefined) return;
if (MODULE.getPermission('OTHER','COMPENDIUM') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
let compendium;
@@ -565,7 +579,7 @@ export class OtherControls{
else compendium = game.packs.entries.find(p=>p.metadata.label == name);
if (compendium == undefined) return;
if (compendium.private && MODULE.getPermission('OTHER','COMPENDIUM_ALL') == false) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
const background = settings.background ? settings.background : '#000000';
@@ -575,7 +589,7 @@ export class OtherControls{
const txt = settings.displayCompendiumName ? name : '';
streamDeck.setTitle(txt,context);
- streamDeck.setIcon(context,"",{background:background,ring:2,ringColor:ringColor});
+ streamDeck.setIcon(context,device,"",{background:background,ring:2,ringColor:ringColor});
}
keyPressCompendium(settings){
@@ -594,7 +608,7 @@ export class OtherControls{
//////////////////////////////////////////////////////////////////////////////////////////
- updateJournal(settings,context,options={}){
+ updateJournal(settings,context,device,options={}){
const name = settings.compendiumName;
if (name == undefined) return;
@@ -602,11 +616,11 @@ export class OtherControls{
if (journal == undefined) return;
if (MODULE.getPermission('OTHER','JOURNAL') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
if (journal.permission < 2 && MODULE.getPermission('OTHER','JOURNAL_ALL') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
let rendered = false;
@@ -625,7 +639,7 @@ export class OtherControls{
const txt = settings.displayCompendiumName ? name : '';
streamDeck.setTitle(txt,context);
- streamDeck.setIcon(context,"",{background:background,ring:2,ringColor:ringColor});
+ streamDeck.setIcon(context,device,"",{background:background,ring:2,ringColor:ringColor});
}
keyPressJournal(settings){
@@ -644,14 +658,14 @@ export class OtherControls{
//////////////////////////////////////////////////////////////////////////////////////////
- updateChatMessage(settings,context,options={}){
+ updateChatMessage(settings,context,device,options={}){
if (MODULE.getPermission('OTHER','CHAT') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
const background = settings.background ? settings.background : '#000000';
streamDeck.setTitle("",context);
- streamDeck.setIcon(context,"",{background:background});
+ streamDeck.setIcon(context,device,"",{background:background});
}
keyPressChatMessage(settings){
@@ -665,4 +679,25 @@ export class OtherControls{
};
ChatMessage.create(chatData, {});
}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+ updateRollOptions(settings,context,device,options={}){
+ const background = settings.background ? settings.background : '#000000';
+ const ringOffColor = settings.offRing ? settings.offRing : '#000000';
+ const ringOnColor = settings.onRing ? settings.onRing : '#00FF00';
+ const iconSrc = "modules/MaterialDeck/img/other/d20.png";
+ const rollOption = settings.rollOptionFunction ? settings.rollOptionFunction : 'normal';
+ const ringColor = (rollOption == this.rollOption) ? ringOnColor : ringOffColor;
+ streamDeck.setTitle("",context);
+ streamDeck.setIcon(context,device,iconSrc,{background:background,ring:2,ringColor:ringColor,overlay:true});
+ }
+
+ keyPressRollOptions(settings){
+ const rollOption = settings.rollOptionFunction ? settings.rollOptionFunction : 'normal';
+ if (this.rollOption != rollOption) {
+ this.rollOption = rollOption;
+ this.updateAll();
+ }
+ }
}
\ No newline at end of file
diff --git a/src/playlist.js b/src/playlist.js
index 336456a..fd2d4b1 100644
--- a/src/playlist.js
+++ b/src/playlist.js
@@ -11,26 +11,28 @@ export class PlaylistControl{
async updateAll(){
if (this.active == false) return;
- for (let i=0; i<32; i++){
- const data = streamDeck.buttonContext[i];
- if (data == undefined || data.action != 'playlist') continue;
- await this.update(data.settings,data.context);
+ for (let device of streamDeck.buttonContext) {
+ for (let i=0; i 0) ? '#00FF00' : '#000000';
const ring = (game.playlists.playing.length > 0) ? 2 : 1;
const txt = settings.displayPlaylistName ? this.getPlaylist(this.playlistOffset).name : '';
- streamDeck.setIcon(context,src,{background:background,ring:ring,ringColor:ringColor,overlay:true});
+ streamDeck.setIcon(context,device,src,{background:background,ring:ring,ringColor:ringColor,overlay:true});
streamDeck.setTitle(txt,context);
}
}
- updatePlaylist(settings,context){
+ updatePlaylist(settings,context,device){
let name = "";
let ringColor = "#000000"
const background = settings.background ? settings.background : '#000000';
@@ -85,11 +87,11 @@ export class PlaylistControl{
const targetPlaylist = this.getPlaylist(number);
if (targetPlaylist != undefined) name = targetPlaylist.name;
}
- streamDeck.setIcon(context,"",{background:background,ring:2,ringColor:ringColor});
+ streamDeck.setIcon(context,device,"",{background:background,ring:2,ringColor:ringColor});
streamDeck.setTitle(name,context);
}
- updateTrack(settings,context){
+ updateTrack(settings,context,device){
let name = "";
let ringColor = "#000000"
const background = settings.background ? settings.background : '#000000';
@@ -133,7 +135,7 @@ export class PlaylistControl{
//Relative Offset
else if (playlistType == 'relativeOffset') {
}
- streamDeck.setIcon(context,"",{background:background,ring:2,ringColor:ringColor});
+ streamDeck.setIcon(context,device,"",{background:background,ring:2,ringColor:ringColor});
streamDeck.setTitle(name,context);
}
@@ -171,7 +173,7 @@ export class PlaylistControl{
else return undefined;
}
- keyPress(settings,context){
+ keyPress(settings,context,device){
if (MODULE.getPermission('PLAYLIST','PLAY') == false ) return;
let playlistNr = settings.playlistNr;
if (playlistNr == undefined || playlistNr < 1) playlistNr = 1;
diff --git a/src/scene.js b/src/scene.js
index c331bdf..a2e3581 100644
--- a/src/scene.js
+++ b/src/scene.js
@@ -11,14 +11,16 @@ export class SceneControl{
async updateAll(){
if (this.active == false) return;
- for (let i=0; i<32; i++){
- const data = streamDeck.buttonContext[i];
- if (data == undefined || data.action != 'scene') continue;
- await this.update(data.settings,data.context);
+ for (let device of streamDeck.buttonContext) {
+ for (let i=0; i 0)
txtNew += "\n";
@@ -177,11 +197,12 @@ export class StreamDeck{
MODULE.sendWS(JSON.stringify(msg));
}
- setImage(image,context,nr,id){
+ setImage(image,context,device,nr,id){
var json = {
target: "SD",
event: "setImage",
context: context,
+ device: device,
payload: {
nr: nr,
id: id,
@@ -192,11 +213,12 @@ export class StreamDeck{
MODULE.sendWS(JSON.stringify(json));
}
- setBufferImage(context,nr,id){
+ setBufferImage(context,device,nr,id){
var json = {
target: "SD",
event: "setBufferImage",
context: context,
+ device: device,
payload: {
nr: nr,
id: id,
@@ -206,7 +228,7 @@ export class StreamDeck{
MODULE.sendWS(JSON.stringify(json));
}
- setIcon(context,src='',options = {}){
+ setIcon(context,device,src='',options = {}){
if (src == null || src == undefined) src = '';
if (src == '') src = 'modules/MaterialDeck/img/black.png';
let background = options.background ? options.background : '#000000';
@@ -215,19 +237,27 @@ export class StreamDeck{
let overlay = options.overlay ? options.overlay : false;
let uses = options.uses ? options.uses : undefined;
let clock = options.clock ? options.clock : false;
- for (let i=0; i<32; i++){
- if (clock != false) break;
- if (this.buttonContext[i] == undefined) continue;
- if (this.buttonContext[i].context == context) {
- if (this.buttonContext[i].icon == src && this.buttonContext[i].ring == ring && this.buttonContext[i].ringColor == ringColor && this.buttonContext[i].background == background && this.buttonContext[i].uses == uses)
- return;
- this.buttonContext[i].icon = src;
- this.buttonContext[i].ring = ring;
- this.buttonContext[i].ringColor = ringColor;
- this.buttonContext[i].background = background;
- this.buttonContext[i].uses = uses;
+
+ //if (src != 'modules/MaterialDeck/img/black.png')
+ for (let d of this.buttonContext) {
+ if (d.device == device) {
+ for (let i=0; i 0 || uses.maximum != undefined)) {
+ if (uses != undefined && uses.heart != false && (uses.available > 0 || uses.maximum != undefined)) {
const percentage = 102*uses.available/uses.maximum;
- ctx.fillStyle = "#FF0000";
+ ctx.fillStyle = uses.heart;
ctx.fillRect(0, 121,144,-percentage);
}
if (format == 'icon' && url != ""){
ctx.font = '600 90px "Font Awesome 5 Free"';
- ctx.fillStyle = "gray";
+ ctx.fillStyle = "#545454";
var elm = document.createElement('i');
elm.className = url;
elm.style.display = 'none';
@@ -384,7 +417,8 @@ export class StreamDeck{
img.setAttribute('crossorigin', 'anonymous');
img.onload = () => {
if (format == 'color') ctx.filter = "opacity(0)";
- if (data.overlay) ctx.filter = "brightness(60%)";
+
+ if (data.overlay == true) ctx.filter = "brightness(" + game.settings.get(MODULE.moduleName,'imageBrightness') + "%)";
//ctx.filter = "brightness(0) saturate(100%) invert(38%) sepia(62%) saturate(2063%) hue-rotate(209deg) brightness(90%) contrast(95%)";
var imageAspectRatio = img.width / img.height;
var canvasAspectRatio = canvas.width / canvas.height;
@@ -489,7 +523,7 @@ export class StreamDeck{
var dataURL = canvas.toDataURL();
canvas.remove();
const nr = this.addToImageBuffer(dataURL,data);
- this.setImage(dataURL,data.context,nr,this.getImageBufferId(data));
+ this.setImage(dataURL,data.context,device,nr,this.getImageBufferId(data));
};
img.src = resImageURL;
}
@@ -531,12 +565,12 @@ export class StreamDeck{
this.imageBuffer = [];
}
- noPermission(context,showTxt=true, origin = ""){
+ noPermission(context,device,showTxt=true, origin = ""){
console.warn("Material Deck: User lacks permission for function "+origin);
const url = 'modules/MaterialDeck/img/black.png';
const background = '#000000';
const txt = showTxt ? 'no\npermission' : '';
- this.setIcon(context,url,{background:background});
+ this.setIcon(context,device,url,{background:background});
this.setTitle(txt,context);
}
}
\ No newline at end of file
diff --git a/src/token.js b/src/token.js
index 49ee4f5..c8f4881 100644
--- a/src/token.js
+++ b/src/token.js
@@ -1,5 +1,5 @@
import * as MODULE from "../MaterialDeck.js";
-import {streamDeck, macroControl} from "../MaterialDeck.js";
+import {streamDeck, macroControl, otherControls} from "../MaterialDeck.js";
import {compatibleCore} from "./misc.js";
export class TokenControl{
@@ -10,24 +10,27 @@ export class TokenControl{
async update(tokenId=null){
if (this.active == false) return;
- for (let i=0; i<32; i++){
- const data = streamDeck.buttonContext[i];
- if (data == undefined || data.action != 'token') continue;
- await this.pushData(tokenId,data.settings,data.context);
+ for (let device of streamDeck.buttonContext) {
+ for (let i=0; i p.id == tokenId);
+ if (selection == 'selected') token = canvas.tokens.controlled[0];
else if (selection != 'selected' && tokenIdentifier == '') {}
else if (selection == 'tokenName') token = canvas.tokens.children[0].children.find(p => p.name == tokenIdentifier);
else if (selection == 'actorName') token = canvas.tokens.children[0].children.find(p => p.actor.name == tokenIdentifier);
@@ -35,7 +38,6 @@ export class TokenControl{
else if (selection == 'actorId') token = canvas.tokens.children[0].children.find(p => p.actor.id == tokenIdentifier);
if (token != undefined) validToken = true;
-
let tokenName = "";
let txt = "";
let iconSrc = "";
@@ -45,16 +47,17 @@ export class TokenControl{
let hp = undefined;
if (validToken) {
if (token.owner == false && token.observer == true && MODULE.getPermission('TOKEN','OBSERVER') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
if (token.owner == false && token.observer == false && MODULE.getPermission('TOKEN','NON_OWNED') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
tokenName = token.data.name;
if (name) txt += tokenName;
+ else txt += prependTitle;
const permission = token.actor?.permission;
if (settings.combat){
@@ -95,11 +98,14 @@ export class TokenControl{
else if (game.system.id == 'dnd5e'){
let attributes = token.actor.data.data.attributes;
if (stats == 'HP') {
- uses = {
- available: attributes.hp.value,
- maximum: attributes.hp.max,
- heart: true
- };
+ if (!icon) {
+ uses = {
+ available: attributes.hp.value,
+ maximum: attributes.hp.max,
+ heart: "#FF0000"
+ };
+ }
+
txt += attributes.hp.value + "/" + attributes.hp.max;
}
else if (stats == 'HPbox') {
@@ -110,9 +116,17 @@ export class TokenControl{
}
}
else if (stats == 'TempHP') {
- txt += attributes.hp.temp;
- if (attributes.hp.tempmax != null)
- txt += "/" + attributes.hp.tempmax;
+ const val = (attributes.hp.temp == null) ? 0 : attributes.hp.temp;
+ const max = (attributes.hp.tempmax == null) ? 0 : attributes.hp.tempmax
+ if (!icon) {
+ uses = {
+ available: (attributes.hp.temp == null) ? 0 : attributes.hp.temp,
+ maximum: (max == 0) ? 1 : attributes.hp.tempmax,
+ heart: "#00FF00"
+ };
+ }
+ txt += val;
+ if (max != 0) txt += "/" + max;
}
else if (stats == 'AC') txt += attributes.ac.value;
else if (stats == 'Speed'){
@@ -175,12 +189,25 @@ export class TokenControl{
if (value >= 0) txt += '+';
txt += value;
}
- else if (stats == 'Prof') txt += token.actor.data.data.attributes.prof;
+ else if (stats == 'Prof') {
+ const value = token.actor.data.data.attributes.prof;
+ if (value >= 0) txt += '+';
+ txt += value;
+ }
}
else if (game.system.id == 'D35E' || game.system.id == 'pf1'){
let attributes = token.actor.data.data.attributes;
- if (stats == 'HP') txt += attributes.hp.value + "/" + attributes.hp.max;
+ if (stats == 'HP') {
+ if (!icon) {
+ uses = {
+ available: attributes.hp.value,
+ maximum: attributes.hp.max,
+ heart: true
+ };
+ }
+ txt += attributes.hp.value + "/" + attributes.hp.max;
+ }
else if (stats == 'HPbox') {
uses = {
available: attributes.hp.value,
@@ -244,7 +271,17 @@ export class TokenControl{
}
else if (game.system.id == 'pf2e'){
let attributes = token.actor.data.data.attributes;
- if (stats == 'HP') txt += attributes.hp.value + "/" + attributes.hp.max;
+ if (stats == 'HP') {
+ if (!icon) {
+ uses = {
+ available: attributes.hp.value,
+ maximum: attributes.hp.max,
+ heart: true
+ };
+ }
+
+ txt += attributes.hp.value + "/" + attributes.hp.max;
+ }
else if (stats == 'HPbox') {
uses = {
available: attributes.hp.value,
@@ -302,7 +339,17 @@ export class TokenControl{
}
else if (game.system.id == 'demonlord'){
let characteristics = token.actor.data.data.characteristics;
- if (stats == 'HP') txt += characteristics.health.value + "/" + characteristics.health.max;
+ if (stats == 'HP') {
+ if (!icon) {
+ uses = {
+ available: attributes.hp.value,
+ maximum: attributes.hp.max,
+ heart: true
+ };
+ }
+
+ characteristics.health.value + "/" + characteristics.health.max;
+ }
else if (stats == 'HPbox') {
uses = {
available: characteristics.health.value,
@@ -335,7 +382,7 @@ export class TokenControl{
if (settings.onClick == 'visibility') { //toggle visibility
if (MODULE.getPermission('TOKEN','VISIBILITY') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
ring = 1;
@@ -350,7 +397,7 @@ export class TokenControl{
}
else if (settings.onClick == 'combatState') { //toggle combat state
if (MODULE.getPermission('TOKEN','COMBAT') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
ring = 1;
@@ -375,7 +422,7 @@ export class TokenControl{
}
else if (settings.onClick == 'condition') { //toggle condition
if (MODULE.getPermission('TOKEN','CONDITIONS') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
ring = 1;
@@ -430,7 +477,7 @@ export class TokenControl{
}
else if (settings.onClick == 'cubCondition') { //Combat Utility Belt conditions
if (MODULE.getPermission('TOKEN','CONDITIONS') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
ring = 1;
@@ -450,7 +497,7 @@ export class TokenControl{
}
else if (settings.onClick == 'wildcard') { //wildcard images
if (MODULE.getPermission('TOKEN','WILDCARD') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
if (icon == false) return;
@@ -490,7 +537,7 @@ export class TokenControl{
iconSrc += "";
if (settings.onClick == 'visibility') { //toggle visibility
if (MODULE.getPermission('TOKEN','VISIBILITY') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
if (icon == false) {
@@ -501,7 +548,7 @@ export class TokenControl{
}
else if (settings.onClick == 'combatState') { //toggle combat state
if (MODULE.getPermission('TOKEN','COMBAT') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
if (icon == false) {
@@ -519,7 +566,7 @@ export class TokenControl{
}
else if (settings.onClick == 'condition') { //toggle condition
if (MODULE.getPermission('TOKEN','CONDITIONS') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
if (game.system.id == 'dnd5e' || game.system.id == 'D35E' || game.system.id == 'pf1'){
@@ -548,7 +595,7 @@ export class TokenControl{
}
else if (settings.onClick == 'cubCondition') { //Combat Utility Belt conditions
if (MODULE.getPermission('TOKEN','CONDITIONS') == false ) {
- streamDeck.noPermission(context);
+ streamDeck.noPermission(context,device);
return;
}
const condition = settings.cubConditionName;
@@ -560,22 +607,47 @@ export class TokenControl{
overlay = true;
}
}
+
if (icon == false){
if (MODULE.getPermission('TOKEN','STATS') == false) stats = statsOld;
- if (stats == 'HP' || stats == 'TempHP') //HP
+ if (stats == 'HP') //HP
iconSrc = "modules/MaterialDeck/img/token/hp_empty.png";
+ if (stats == 'TempHP') //Temp HP
+ iconSrc = "modules/MaterialDeck/img/token/temp_hp_empty.png";
else if (stats == 'AC' || stats == 'ShieldHP') //AC
iconSrc = "modules/MaterialDeck/img/token/ac.webp";
else if (stats == 'Speed') //Speed
iconSrc = "modules/MaterialDeck/img/token/speed.webp";
else if (stats == 'Init') //Initiative
iconSrc = "modules/MaterialDeck/img/token/init.png";
- else if (stats == 'PassivePerception')
- iconSrc = "modules/MaterialDeck/img/black.png";
- else if (stats == 'PassiveInvestigation')
- iconSrc = "modules/MaterialDeck/img/black.png";
+ else if (stats == 'PassivePerception') {
+ iconSrc = "modules/MaterialDeck/img/token/skills/prc.png";
+ overlay = true;
+ ring = 1;
+ }
+ else if (stats == 'PassiveInvestigation') {
+ iconSrc = "modules/MaterialDeck/img/token/skills/inv.png";
+ overlay = true;
+ ring = 1;
+ }
+ else if (stats == 'Ability' || stats == 'AbilityMod' || stats == 'Save') {
+ overlay = true;
+ ring = 1;
+ let ability = (stats == 'Save') ? settings.save : settings.ability;
+ if (ability == undefined) ability = 'str';
+ if (ability == 'con') iconSrc = "modules/MaterialDeck/img/token/abilities/cons.png";
+ else iconSrc = "modules/MaterialDeck/img/token/abilities/" + ability + ".png";
+ }
+ else if (stats == 'Skill') {
+ overlay = true;
+ ring = 1;
+ let skill = settings.skill;
+ if (skill == undefined) skill = 'acr';
+ else iconSrc = "modules/MaterialDeck/img/token/skills/" + skill + ".png";
+ }
+
}
- streamDeck.setIcon(context,iconSrc,{background:background,ring:ring,ringColor:ringColor,overlay:overlay,uses:uses,hp:hp});
+ streamDeck.setIcon(context,device,iconSrc,{background:background,ring:ring,ringColor:ringColor,overlay:overlay,uses:uses,hp:hp});
streamDeck.setTitle(txt,context);
}
@@ -774,37 +846,45 @@ export class TokenControl{
macroControl.keyPress(settingsNew);
}
else if (onClick == 'roll') { //roll skill/save/ability
- const roll = settings.roll ? settings.roll : 'abilityCheck';
+ const roll = settings.roll ? settings.roll : 'ability';
const ability = settings.rollAbility ? settings.rollAbility : 'str';
const skill = settings.rollSkill ? settings.rollSkill : 'acr';
const save = settings.rollSave ? settings.rollSave : 'str';
+ const rollOptions = otherControls.rollOption ? otherControls.rollOption : 'dialog';
+ const options = {
+ fastForward: (otherControls.rollOption != 'dialog'),
+ advantage: (otherControls.rollOption == 'advantage'),
+ disadvantage: (otherControls.rollOption == 'disadvantage')
+ }
if (game.system.id == 'pf2e') {
- if (roll == 'abilityCheck') token.actor.data.data.saves?.[ability].roll();
+ if (roll == 'ability') token.actor.data.data.saves?.[ability].roll(options);
else if (roll == 'save') {
let ability = save;
if (ability == 'fort') ability = 'fortitude';
else if (ability == 'ref') ability = 'reflex';
else if (ability == 'will') ability = 'will';
- token.actor.data.data.saves?.[ability].roll();
+ token.actor.data.data.saves?.[ability].roll(options);
}
- else if (roll == 'skill') token.actor.data.data.skills?.[skill].roll();
+ else if (roll == 'skill') token.actor.data.data.skills?.[skill].roll(options);
}
- if (roll == 'abilityCheck') token.actor.rollAbilityTest(ability);
+ if (roll == 'ability') token.actor.rollAbilityTest(ability,options);
else if (roll == 'save') {
- if (game.system.id == 'dnd5e') token.actor.rollAbilitySave(save);
- else token.actor.rollSavingThrow(save);
+ if (game.system.id == 'dnd5e') token.actor.rollAbilitySave(save,options);
+ else token.actor.rollSavingThrow(save,options);
}
- else if (roll == 'skill') token.actor.rollSkill(skill);
- else if (roll == 'initiative') token.actor.rollInitiative();
- else if (roll == 'deathSave') token.actor.rollDeathSave();
- else if (roll == 'grapple') token.actor.rollGrapple();
- else if (roll == 'bab') token.actor.rollBAB();
- else if (roll == 'melee') token.actor.rollMelee();
- else if (roll == 'ranged') token.actor.rollRanged();
- else if (roll == 'cmb') token.actor.rollCMB();
- else if (roll == 'attack') token.actor.rollAttack();
- else if (roll == 'defenses') token.actor.rollDefenses();
+ else if (roll == 'skill') token.actor.rollSkill(skill,options);
+ else if (roll == 'initiative') token.actor.rollInitiative(options);
+ else if (roll == 'deathSave') token.actor.rollDeathSave(options);
+ else if (roll == 'grapple') token.actor.rollGrapple(options);
+ else if (roll == 'bab') token.actor.rollBAB(options);
+ else if (roll == 'melee') token.actor.rollMelee(options);
+ else if (roll == 'ranged') token.actor.rollRanged(options);
+ else if (roll == 'cmb') token.actor.rollCMB(options);
+ else if (roll == 'attack') token.actor.rollAttack(options);
+ else if (roll == 'defenses') token.actor.rollDefenses(options);
+
+ if (otherControls.rollOption != 'dialog') otherControls.setRollOption('normal');
}
else if (onClick == 'custom') {//custom onClick function
if (MODULE.getPermission('TOKEN','CUSTOM') == false ) return;
diff --git a/templates/helpMenu.html b/templates/helpMenu.html
index b2b82b5..1c51f5d 100644
--- a/templates/helpMenu.html
+++ b/templates/helpMenu.html
@@ -1,6 +1,7 @@