diff --git a/MaterialDeck.js b/MaterialDeck.js index dda26c7..49259dd 100644 --- a/MaterialDeck.js +++ b/MaterialDeck.js @@ -30,7 +30,7 @@ let activeSounds = []; export let hotbarUses = false; export let calculateHotbarUses; - +let controlTokenTimer; //CONFIG.debug.hooks = true; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -116,7 +116,7 @@ async function analyzeWSmessage(msg){ if (action == 'token'){ tokenControl.active = true; - tokenControl.update(device,selectedTokenId,device); + tokenControl.pushData(selectedTokenId,settings,context,device); } else if (action == 'move') move.update(settings,context,device); @@ -353,17 +353,13 @@ Hooks.once('ready', async()=>{ } const hotbarUsesTemp = game.modules.get("illandril-hotbar-uses"); - if (hotbarUsesTemp != undefined) { - hotbarUses = true; - } - + if (hotbarUsesTemp != undefined) hotbarUses = true; }); Hooks.on('updateToken',(scene,token)=>{ if (enableModule == false || ready == false) return; let tokenId = token._id; - if (tokenId == selectedTokenId) - tokenControl.update(selectedTokenId); + if (tokenId == selectedTokenId) tokenControl.update(selectedTokenId); if (macroControl != undefined) macroControl.updateAll(); }); @@ -373,8 +369,10 @@ Hooks.on('updateActor',(scene,actor)=>{ for (let i=0; i{ if (enableModule == false || ready == false) return; if (controlled) { selectedTokenId = token.data._id; + tokenControl.update(selectedTokenId); + if (controlTokenTimer != undefined) { + clearTimeout(controlTokenTimer); + controlTokenTimer = undefined; + } } else { + controlTokenTimer = setTimeout(function(){tokenControl.update(selectedTokenId);},10) selectedTokenId = undefined; } - tokenControl.update(selectedTokenId); + if (macroControl != undefined) macroControl.updateAll(); }); diff --git a/changelog.md b/changelog.md index 4bb73d8..544b4ae 100644 --- a/changelog.md +++ b/changelog.md @@ -1,8 +1,38 @@ # Changelog Material Deck Module +### v1.4.2 - 23-04-2021 +Fixes: + + +Additions: + + +Other: + + +
+Compatible server app and SD plugin:
+Material Server v1.0.2 (unchanged): https://github.com/CDeenen/MaterialServer/releases
+SD plugin v1.4.2 (must be updated!): https://github.com/CDeenen/MaterialDeck_SD/releases
+ ### v1.4.1 - 21-04-2021 Fixes: ### v1.4.0 - 21-04-2021 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/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/module.json b/module.json index 3b4f159..2f6283f 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.4.1", - "minimumSDversion": "1.4.0", + "version": "1.4.2", + "minimumSDversion": "1.4.2", "minimumMSversion": "1.0.2", "author": "CDeenen", "esmodules": [ diff --git a/src/combattracker.js b/src/combattracker.js index 02a7193..102e9c1 100644 --- a/src/combattracker.js +++ b/src/combattracker.js @@ -28,6 +28,7 @@ export class CombatTracker{ let txt = ""; let background = "#000000"; settings.combat = true; + settings.icon = settings.displayIcon ? 'tokenIcon' : 'none'; if (mode == 'combatants'){ if (MODULE.getPermission('COMBAT','DISPLAY_COMBATANTS') == false) { diff --git a/src/macro.js b/src/macro.js index 6806f27..e67ca10 100644 --- a/src/macro.js +++ b/src/macro.js @@ -51,6 +51,7 @@ export class MacroControl{ ringColor = (macroOffset == parseInt(this.offset)) ? ringOnColor : ringOffColor; ring = 2; + src = "modules/MaterialDeck/img/transparant.png"; } else { //Execute macro macroNumber += this.offset - 1; diff --git a/src/playlist.js b/src/playlist.js index fd2d4b1..9e57370 100644 --- a/src/playlist.js +++ b/src/playlist.js @@ -52,6 +52,7 @@ export class PlaylistControl{ const ringOffColor = settings.offRing ? settings.offRing : '#FF0000'; const ringOnColor = settings.onRing ? settings.onRing : '#00FF00'; const playlistType = settings.playlistType ? settings.playlistType : 'playStop'; + let src = "modules/MaterialDeck/img/transparant.png"; //Play/Stop if (playlistType == 'playStop'){ @@ -74,7 +75,7 @@ export class PlaylistControl{ else if (playlistType == 'offset') { let playlistOffset = parseInt(settings.offset); if (isNaN(playlistOffset)) playlistOffset = 0; - if (playlistOffset == this.playlistOffset) ringColor = ringOnColor; + ringColor = (playlistOffset == this.playlistOffset) ? ringOnColor : ringOffColor; } //Relative Offset else if (playlistType == 'relativeOffset') { @@ -87,7 +88,7 @@ export class PlaylistControl{ const targetPlaylist = this.getPlaylist(number); if (targetPlaylist != undefined) name = targetPlaylist.name; } - streamDeck.setIcon(context,device,"",{background:background,ring:2,ringColor:ringColor}); + streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor}); streamDeck.setTitle(name,context); } @@ -98,6 +99,7 @@ export class PlaylistControl{ const ringOffColor = settings.offRing ? settings.offRing : '#FF0000'; const ringOnColor = settings.onRing ? settings.onRing : '#00FF00'; const playlistType = settings.playlistType ? settings.playlistType : 'playStop'; + let src = "modules/MaterialDeck/img/transparant.png"; //Play/Stop if (playlistType == 'playStop'){ @@ -130,12 +132,12 @@ export class PlaylistControl{ else if (playlistType == 'offset') { let trackOffset = parseInt(settings.offset); if (isNaN(trackOffset)) trackOffset = 0; - if (trackOffset == this.trackOffset) ringColor = ringOnColor; + ringColor = (trackOffset == this.trackOffset) ? ringOnColor : ringOffColor; } //Relative Offset else if (playlistType == 'relativeOffset') { } - streamDeck.setIcon(context,device,"",{background:background,ring:2,ringColor:ringColor}); + streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor}); streamDeck.setTitle(name,context); } diff --git a/src/scene.js b/src/scene.js index a2e3581..175d64d 100644 --- a/src/scene.js +++ b/src/scene.js @@ -114,8 +114,8 @@ export class SceneControl{ else if (func == 'offset'){ let offset = parseInt(settings.sceneOffset); if (isNaN(offset)) offset = 0; - if (offset == this.sceneOffset) ringColor = ringOnColor; - else ringColor = ringOffColor; + ringColor = (offset == this.sceneOffset) ? ringOnColor : ringOffColor; + src = "modules/MaterialDeck/img/transparant.png"; } streamDeck.setTitle(name,context); streamDeck.setIcon(context,device,src,{background:background,ring:ring,ringColor:ringColor}); diff --git a/src/token.js b/src/token.js index 719e155..a1ace93 100644 --- a/src/token.js +++ b/src/token.js @@ -21,7 +21,7 @@ export class TokenControl{ async pushData(tokenId,settings,context,device,ring=0,ringColor='#000000'){ const name = settings.displayName ? settings.displayName : false; - const icon = settings.displayIcon ? settings.displayIcon : false; + const icon = settings.icon ? settings.icon : 'none'; const background = settings.background ? settings.background : "#000000"; let stats = settings.stats ? settings.stats : 'none'; const selection = settings.selection ? settings.selection : 'selected'; @@ -30,7 +30,10 @@ export class TokenControl{ let validToken = false; let token; - if (tokenId != undefined && tokenId != null) token = canvas.tokens.children[0].children.find(p => p.id == tokenId); + if (settings.combatTrackerMode) { + const mode = settings.combatTrackerMode; + token = canvas.tokens.children[0].children.find(p => p.id == tokenId); + } else 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); @@ -76,7 +79,8 @@ export class TokenControl{ stats = 'none'; } - if (icon) iconSrc = token.data.img; + if (icon == 'tokenIcon') iconSrc = token.data.img; + else if (icon == 'actorIcon') iconSrc = token.actor.data.img; if (name && stats != 'none' && stats != 'HPbox') txt += "\n"; if (stats == 'custom'){ const custom = settings.custom ? settings.custom : ''; @@ -99,7 +103,7 @@ export class TokenControl{ else if (game.system.id == 'dnd5e'){ let attributes = token.actor.data.data.attributes; if (stats == 'HP') { - if (!icon) { + if (icon == 'stats') { uses = { available: attributes.hp.value, maximum: attributes.hp.max, @@ -119,7 +123,7 @@ export class TokenControl{ else if (stats == 'TempHP') { const val = (attributes.hp.temp == null) ? 0 : attributes.hp.temp; const max = (attributes.hp.tempmax == null) ? 0 : attributes.hp.tempmax - if (!icon) { + if (icon == 'stats') { uses = { available: (attributes.hp.temp == null) ? 0 : attributes.hp.temp, maximum: (max == 0) ? 1 : attributes.hp.tempmax, @@ -186,7 +190,7 @@ export class TokenControl{ } else if (stats == 'Skill') { const skill = settings.skill ? settings.skill : 'acr'; - const value = token.actor.data.data.skills?.[skill].mod; + const value = token.actor.data.data.skills?.[skill].total; if (value >= 0) txt += '+'; txt += value; } @@ -200,7 +204,7 @@ export class TokenControl{ else if (game.system.id == 'D35E' || game.system.id == 'pf1'){ let attributes = token.actor.data.data.attributes; if (stats == 'HP') { - if (!icon) { + if (icon == 'stats') { uses = { available: attributes.hp.value, maximum: attributes.hp.max, @@ -273,7 +277,7 @@ export class TokenControl{ else if (game.system.id == 'pf2e'){ let attributes = token.actor.data.data.attributes; if (stats == 'HP') { - if (!icon) { + if (icon == 'stats') { uses = { available: attributes.hp.value, maximum: attributes.hp.max, @@ -341,7 +345,7 @@ export class TokenControl{ else if (game.system.id == 'demonlord'){ let characteristics = token.actor.data.data.characteristics; if (stats == 'HP') { - if (!icon) { + if (icon == 'stats') { uses = { available: attributes.hp.value, maximum: attributes.hp.max, @@ -391,7 +395,7 @@ export class TokenControl{ ring = 2; ringColor = "#FF7B00"; } - if (icon == false) { + if (icon == 'stats') { iconSrc = window.CONFIG.controlIcons.visibility; overlay = true; } @@ -406,7 +410,7 @@ export class TokenControl{ ring = 2; ringColor = "#FF7B00"; } - if (icon == false) { + if (icon == 'stats') { iconSrc = window.CONFIG.controlIcons.combat; overlay = true; } @@ -417,7 +421,7 @@ export class TokenControl{ ring = 2; ringColor = "#FF7B00"; } - if (icon == false) { + if (icon == 'stats') { iconSrc = "fas fa-bullseye"; } } @@ -429,9 +433,9 @@ export class TokenControl{ ring = 1; if (game.system.id == 'dnd5e' || game.system.id == 'D35E' || game.system.id == 'pf1'){ const condition = settings.condition ? settings.condition : 'removeAll'; - if (condition == 'removeAll' && icon == false) + if (condition == 'removeAll' && icon == 'stats') iconSrc = window.CONFIG.controlIcons.effects; - else if (icon == false) { + else if (icon == 'stats') { let effect = CONFIG.statusEffects.find(e => e.id === condition); iconSrc = effect.icon; let effects = compatibleCore("0.8.1") ? token.actor.effects.contents : token.actor.effects.entries; @@ -444,9 +448,9 @@ export class TokenControl{ } else if (game.system.id == 'pf2e') { const condition = settings.condition ? settings.condition : 'removeAll'; - if (condition == 'removeAll' && icon == false) + if (condition == 'removeAll' && icon == 'stats') iconSrc = window.CONFIG.controlIcons.effects; - else if (icon == false) { + else if (icon == 'stats') { let effects = token.data.effects; for (let i=0; i e.id === condition); iconSrc = effect.icon; let effects = token.actor.effects.entries; @@ -485,7 +489,7 @@ export class TokenControl{ overlay = true; const condition = settings.cubConditionName; if (condition == undefined || condition == '') return; - if (icon == false) { + if (icon == 'stats') { let effect = CONFIG.statusEffects.find(e => e.label === condition); iconSrc = effect.icon; let effects = compatibleCore("0.8.1") ? token.actor.effects.contents : token.actor.effects.entries; @@ -501,7 +505,7 @@ export class TokenControl{ streamDeck.noPermission(context,device); return; } - if (icon == false) return; + if (icon != 'stats') return; const method = settings.wildcardMethod ? settings.wildcardMethod : 'iterate'; let value = parseInt(settings.wildcardValue); if (isNaN(value)) value = 1; @@ -541,7 +545,7 @@ export class TokenControl{ streamDeck.noPermission(context,device); return; } - if (icon == false) { + if (icon == 'stats') { iconSrc = window.CONFIG.controlIcons.visibility; ring = 2; overlay = true; @@ -552,14 +556,14 @@ export class TokenControl{ streamDeck.noPermission(context,device); return; } - if (icon == false) { + if (icon == 'stats') { iconSrc = window.CONFIG.controlIcons.combat; ring = 2; overlay = true; } } else if (settings.onClick == 'target') { //target token - if (icon == false) { + if (icon == 'stats') { iconSrc = "fas fa-bullseye"; ring = 2; overlay = true; @@ -574,21 +578,21 @@ export class TokenControl{ const condition = settings.condition ? settings.condition : 'removeAll'; if (condition == 'removeAll' && icon == false) iconSrc = window.CONFIG.controlIcons.effects; - else if (icon == false) + else if (icon == 'stats') iconSrc = CONFIG.statusEffects.find(e => e.id === condition).icon; } else if (game.system.id == 'pf2e') { const condition = settings.condition ? settings.condition : 'removeAll'; - if (condition == 'removeAll' && icon == false) + if (condition == 'removeAll' && icon == 'stats') iconSrc = window.CONFIG.controlIcons.effects; - else if (icon == false) + else if (icon == 'stats') iconSrc = this.pf2eCondition(condition); } else if (game.system.id == 'demonlord'){ const condition = settings.condition ? settings.condition : 'removeAll'; - if (condition == 'removeAll' && icon == false) + if (condition == 'removeAll' && icon == 'stats') iconSrc = window.CONFIG.controlIcons.effects; - else if (icon == false) + else if (icon == 'stats') iconSrc = CONFIG.statusEffects.find(e => e.id === condition).icon; } ring = 1; @@ -601,7 +605,7 @@ export class TokenControl{ } const condition = settings.cubConditionName; if (condition == undefined || condition == '') return; - if (icon == false) { + if (icon == 'stats') { iconSrc = CONFIG.statusEffects.find(e => e.label === condition).icon; } ring = 1; @@ -609,7 +613,7 @@ export class TokenControl{ } } - if (icon == false){ + if (icon == 'stats'){ if (MODULE.getPermission('TOKEN','STATS') == false) stats = statsOld; if (stats == 'HP') //HP iconSrc = "modules/MaterialDeck/img/token/hp_empty.png"; @@ -851,12 +855,17 @@ export class TokenControl{ 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') - } + const rollMode = settings.rollMode ? settings.rollMode : 'default'; + let options; + if (rollMode == 'default') + options = { + fastForward: (otherControls.rollOption != 'dialog'), + advantage: (otherControls.rollOption == 'advantage'), + disadvantage: (otherControls.rollOption == 'disadvantage') + } + else if (rollMode == 'normal') options = {fastForward:true} + else if (rollMode == 'advantage') options = {fastForward:true,advantage:true} + else if (rollMode == 'disadvantage') options = {fastForward:true,disadvantage:true} if (game.system.id == 'pf2e') { if (roll == 'ability') token.actor.data.data.saves?.[ability].roll(options);