Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd4c9e129e | ||
|
|
fb26eacc8d | ||
|
|
d809217d23 | ||
|
|
e4cdf1c355 |
@@ -265,6 +265,18 @@ Hooks.on('updateToken',(scene,token)=>{
|
|||||||
tokenControl.update(selectedTokenId);
|
tokenControl.update(selectedTokenId);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Hooks.on('updateActor',(scene,actor)=>{
|
||||||
|
if (enableModule == false || ready == false) return;
|
||||||
|
let children = canvas.tokens.children[0].children;
|
||||||
|
for (let i=0; i<children.length; i++){
|
||||||
|
if (children[i].actor.id == actor._id){
|
||||||
|
let tokenId = children[i].id;
|
||||||
|
if (tokenId == selectedTokenId)
|
||||||
|
tokenControl.update(selectedTokenId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Hooks.on('controlToken',(token,controlled)=>{
|
Hooks.on('controlToken',(token,controlled)=>{
|
||||||
if (enableModule == false || ready == false) return;
|
if (enableModule == false || ready == false) return;
|
||||||
if (controlled) {
|
if (controlled) {
|
||||||
|
|||||||
86
README.md
86
README.md
@@ -1,8 +1,61 @@
|
|||||||
# Stream Deck
|
<b>Note:</b> At the moment only Windows support has been confirmed. Right now it doesn't appear to work on MacOS. Linux support is unknown, there is no official Linux support for the Stream Deck, but there exist a 3rd party <a href="https://timothycrosley.com/project-7-streamdeck_ui">Stream Deck UI</a> that might be compatible.<br>
|
||||||
Material Deck is a Foundry VTT module that allows you to control certain Foundry functions using an Elgato Stream Deck.
|
<b>In any case: Proceed at your own risk, I will not take any responsibility if you spent money and the module doesn't work!</b>
|
||||||
|
|
||||||
## Instructions
|
I created a <a href="https://discord.gg/3hd4G6TkmA">Discord server</a> to discuss this and other hardware-based Foundry modules. Feel free to join if you'd like to join the discussion and be updated on this module.
|
||||||
Instructions are on the <a href="https://github.com/CDeenen/MaterialDeck/wiki">wiki</a>.
|
|
||||||
|
# Material Deck
|
||||||
|
Material Deck is a Foundry VTT module that allows you to control certain Foundry functions using an Elgato Stream Deck. A Stream Deck is a device that has physical buttons with displays behind them. Material Deck uses this to, for example, control playlists, execute macros, display and control the combat tracker.<br><br>
|
||||||
|
The module allows a high degree of customization, where each button on the Stream Deck can be assigned any desired function. Furthermore, it supports folder structures, allowing easy switching between various button configurations so you can easily switch between the combat tracker, soundboard, or any other (custom) configuration.<br><br>
|
||||||
|
The functions are categorized into actions. Here is a list of the available actions and their most important functions:
|
||||||
|
<ul>
|
||||||
|
<li>Playlist Action: Control Foundry's playlists</li>
|
||||||
|
<ul>
|
||||||
|
<li>Play/Stop playlists</li>
|
||||||
|
<li>Play/Stop tracks</li>
|
||||||
|
<li>Stop all tracks & playlists</li>
|
||||||
|
</ul>
|
||||||
|
<li>Soundboard Action: Play sounds</li>
|
||||||
|
<ul>
|
||||||
|
<li>Play/Stop sound</li>
|
||||||
|
<li>Stop all sounds</li>
|
||||||
|
</ul>
|
||||||
|
<li>Token Action: Display token info</li>
|
||||||
|
<ul>
|
||||||
|
<li>Display selected token's name, icon or stats (HP/AC/Movement/Initiative)</li>
|
||||||
|
<li>Open selected token's character sheet or token config</li>
|
||||||
|
</ul>
|
||||||
|
<li>Move Action: Move selected token or the canvas</li>
|
||||||
|
<ul>
|
||||||
|
<li>Move token (in a specified direction)</li>
|
||||||
|
<li>Move canvas (in a specified direction)</li>
|
||||||
|
<li>Zoom canvas in/out</li>
|
||||||
|
</ul>
|
||||||
|
<li>Macro Actions: Execute macros</li>
|
||||||
|
<ul>
|
||||||
|
<li>Execute macro from hotbar</li>
|
||||||
|
<li>Execute macro from macro board</li>
|
||||||
|
</ul>
|
||||||
|
<li>Combat Tracker Actions: Control and display the combat tracker</li>
|
||||||
|
<ul>
|
||||||
|
<li>Display combatants</li>
|
||||||
|
<li>Start/Stop combat</li>
|
||||||
|
<li>Next/Previous turn/round</li>
|
||||||
|
</ul>
|
||||||
|
<li>Other Actions: Misc other actions</li>
|
||||||
|
<ul>
|
||||||
|
<li>Pause/Resume game</li>
|
||||||
|
<li>Scene selection/activation</li>
|
||||||
|
<li>Toggle control buttons</li>
|
||||||
|
<li>Control darkness level</li>
|
||||||
|
<li>Open/Roll from a roll table</li>
|
||||||
|
<li>Open sidebar tab</li>
|
||||||
|
<li>Open compendium pack</li>
|
||||||
|
<li>Open journal entry</li>
|
||||||
|
</ul>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
## Instructions and More Info
|
||||||
|
Instructions and more info can be found in the <a href="https://github.com/CDeenen/MaterialDeck/wiki">wiki</a>.
|
||||||
|
|
||||||
## Latest releases
|
## Latest releases
|
||||||
<a href="https://github.com/CDeenen/MaterialDeck/releases">Module</a><br>
|
<a href="https://github.com/CDeenen/MaterialDeck/releases">Module</a><br>
|
||||||
@@ -10,3 +63,28 @@ Instructions are on the <a href="https://github.com/CDeenen/MaterialDeck/wiki">w
|
|||||||
<a href="https://github.com/CDeenen/MaterialServer/releases">Server</a><br>
|
<a href="https://github.com/CDeenen/MaterialServer/releases">Server</a><br>
|
||||||
<br>
|
<br>
|
||||||
Module manifest: https://raw.githubusercontent.com/CDeenen/MaterialDeck/Master/module.json
|
Module manifest: https://raw.githubusercontent.com/CDeenen/MaterialDeck/Master/module.json
|
||||||
|
|
||||||
|
## Software Versions & Module Incompatibilities
|
||||||
|
<b>Foundry VTT:</b> Tested on 0.7.7<br>
|
||||||
|
<b>Module Incompatibilities:</b> None known.<br>
|
||||||
|
|
||||||
|
## Feedback
|
||||||
|
If you have any suggestions or bugs to report, feel free to create an issue, contact me on Discord (Cris#6864), or send me an email: cdeenen@outlook.com.
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
<b>Author:</b> Cristian Deenen (Cris#6864 on Discord)<br>
|
||||||
|
<br>
|
||||||
|
Special thanks to Asmodeus#7588 who made this module possible by generously donating a Stream Deck XL
|
||||||
|
|
||||||
|
## Abandonment
|
||||||
|
Abandoned modules are a (potential) problem for Foundry, because users and/or other modules might rely on abandoned modules, which might break in future Foundry updates.<br>
|
||||||
|
I consider this module abandoned if all of the below cases apply:
|
||||||
|
<ul>
|
||||||
|
<li>This module/github page has not received any updates in at least 3 months</li>
|
||||||
|
<li>I have not posted anything on "the Foundry", "the League of Extraordinary Foundry VTT Developers" or the "Material Foundry" Discord servers in at least 3 months</li>
|
||||||
|
<li>I have not responded to emails or PMs on Discord in at least 1 month</li>
|
||||||
|
<li>I have not announced a temporary break from development, unless the announced end date of this break has been passed by at least 3 months</li>
|
||||||
|
</ul>
|
||||||
|
If the above cases apply (as judged by the "League of Extraordinary Foundry VTT Developers" admins), I give permission to the "League of Extraordinary Foundry VTT Developers" admins to assign one or more developers to take over this module, including requesting the Foundry team to reassign the module to the new developer(s).<br>
|
||||||
|
I require the "League of Extraordinary Foundry VTT Developers" admins to send me an email 2 weeks before the reassignment takes place, to give me one last chance to prevent the reassignment.<br>
|
||||||
|
I require to be credited for my work in all future releases.
|
||||||
|
|||||||
17
changelog.md
17
changelog.md
@@ -1,5 +1,20 @@
|
|||||||
# Changelog Material Deck Module
|
# Changelog Material Deck Module
|
||||||
### v0.8.7 - 19-11-2020
|
### v0.9.1 - 23-11-2020
|
||||||
|
<ul>
|
||||||
|
<li>Fixed 'Playlist' action issue where 'TrackNr' wouldn't show</li>
|
||||||
|
<li>Fixed 'Soundboard Configuration' issue where changing the playlist would reset everything you've changed since last save</li>
|
||||||
|
<li>'Soundboard Configuration', 'Macro Configuration' and 'Playlist Configuration' now save after each change, and update the SD instantly</li>
|
||||||
|
<li>Save button has been removed from configuration screens, since it is now redundant</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<b>Note1:</b> In 'Macro Configuration', previously saved Furnace arguments have to be filled in again.<br>
|
||||||
|
<b>Note2:</b> Any settings set in 'Playlist Configuration' have to be set again<br>
|
||||||
|
<br>
|
||||||
|
<b>Compatible server app and SD plugin:</b><br>
|
||||||
|
Material Server v1.0.1: https://github.com/CDeenen/MaterialServer/releases <br>
|
||||||
|
SD plugin v0.9.1 (unchanged): https://github.com/CDeenen/MaterialDeck_SD/releases<br>
|
||||||
|
|
||||||
|
### v0.9.0 - 19-11-2020
|
||||||
<ul>
|
<ul>
|
||||||
<li>Added support for more playlists</li>
|
<li>Added support for more playlists</li>
|
||||||
<li>Added playmode setting for each playlist, which overrides the default playmode</li>
|
<li>Added playmode setting for each playlist, which overrides the default playmode</li>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
"MaterialDeck.PL.OneTrackTotal": "One track in total",
|
"MaterialDeck.PL.OneTrackTotal": "One track in total",
|
||||||
"MaterialDeck.PL.OneTrack": "One track",
|
"MaterialDeck.PL.OneTrack": "One track",
|
||||||
"MaterialDeck.PL.Settings": "Settings",
|
"MaterialDeck.PL.Settings": "Settings",
|
||||||
"MaterialDeck.PL.Mode": "Default Playmode",
|
"MaterialDeck.PL.Mode": "Default Play Mode",
|
||||||
"MaterialDeck.PL.Nr": "Number of playlists",
|
"MaterialDeck.PL.Nr": "Number of playlists",
|
||||||
|
|
||||||
"MaterialDeck.Playlists": "Playlists",
|
"MaterialDeck.Playlists": "Playlists",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "MaterialDeck",
|
"name": "MaterialDeck",
|
||||||
"title": "Material Deck",
|
"title": "Material Deck",
|
||||||
"description": "",
|
"description": "",
|
||||||
"version": "0.9.0",
|
"version": "0.9.1",
|
||||||
"author": "CDeenen",
|
"author": "CDeenen",
|
||||||
"esmodules": [
|
"esmodules": [
|
||||||
"./MaterialDeck.js"
|
"./MaterialDeck.js"
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ export class MacroControl{
|
|||||||
if (macroId != undefined){
|
if (macroId != undefined){
|
||||||
let macro = game.macros.get(macroId);
|
let macro = game.macros.get(macroId);
|
||||||
if (macro != undefined && macro != null) {
|
if (macro != undefined && macro != null) {
|
||||||
const args = game.settings.get(MODULE.moduleName,'macroArgs')[macroNumber];
|
const args = game.settings.get(MODULE.moduleName,'macroSettings').args[macroNumber];
|
||||||
let furnaceEnabled = false;
|
let furnaceEnabled = false;
|
||||||
let furnace = game.modules.get("furnace");
|
let furnace = game.modules.get("furnace");
|
||||||
if (furnace != undefined && furnace.active) furnaceEnabled = true;
|
if (furnace != undefined && furnace.active) furnaceEnabled = true;
|
||||||
|
|||||||
287
src/misc.js
287
src/misc.js
@@ -1,5 +1,5 @@
|
|||||||
import * as MODULE from "../MaterialDeck.js";
|
import * as MODULE from "../MaterialDeck.js";
|
||||||
import {macroControl} from "../MaterialDeck.js";
|
import {macroControl,soundboard,playlistControl} from "../MaterialDeck.js";
|
||||||
|
|
||||||
export class playlistConfigForm extends FormApplication {
|
export class playlistConfigForm extends FormApplication {
|
||||||
constructor(data, options) {
|
constructor(data, options) {
|
||||||
@@ -26,33 +26,43 @@ export class playlistConfigForm extends FormApplication {
|
|||||||
* Provide data to the template
|
* Provide data to the template
|
||||||
*/
|
*/
|
||||||
getData() {
|
getData() {
|
||||||
let selectedPlaylists = game.settings.get(MODULE.moduleName,'selectedPlaylists');
|
let settings = game.settings.get(MODULE.moduleName,'playlists');
|
||||||
|
let selectedPlaylists = settings.selectedPlaylist;
|
||||||
if (selectedPlaylists == undefined) selectedPlaylists = [];
|
if (selectedPlaylists == undefined) selectedPlaylists = [];
|
||||||
let selectedPlaylistMethod = game.settings.get(MODULE.moduleName, 'selectedPlaylistMethod');
|
let selectedPlaylistMode = settings.playlistMode;
|
||||||
if (selectedPlaylistMethod == undefined) selectedPlaylistMethod = [];
|
if (selectedPlaylistMode == undefined) selectedPlaylistMode = [];
|
||||||
let playlistData = [];
|
let numberOfPlaylists = settings.playlistNumber;
|
||||||
let numberOfPlaylists = game.settings.get(MODULE.moduleName,'numberOfPlaylists');
|
|
||||||
if (this.updatePlaylistNr) numberOfPlaylists = this.playlistNr;
|
if (this.updatePlaylistNr) numberOfPlaylists = this.playlistNr;
|
||||||
|
if (numberOfPlaylists == undefined) numberOfPlaylists = 9;
|
||||||
|
let playMode = settings.playMode;
|
||||||
|
if (playMode == undefined) playMode = 0;
|
||||||
|
let playlistData = [];
|
||||||
|
|
||||||
this.updatePlaylistNr = false;
|
this.updatePlaylistNr = false;
|
||||||
for (let i=0; i<numberOfPlaylists; i++){
|
for (let i=0; i<numberOfPlaylists; i++){
|
||||||
if (selectedPlaylists[i] == undefined) selectedPlaylists[i] = 'none';
|
if (selectedPlaylists[i] == undefined) selectedPlaylists[i] = 'none';
|
||||||
if (selectedPlaylistMethod[i] == undefined) selectedPlaylistMethod[i] = 0;
|
if (selectedPlaylistMode[i] == undefined) selectedPlaylistMode[i] = 0;
|
||||||
let dataThis = {
|
let dataThis = {
|
||||||
iteration: i+1,
|
iteration: i+1,
|
||||||
playlist: selectedPlaylists[i],
|
playlist: selectedPlaylists[i],
|
||||||
playlistMethod: selectedPlaylistMethod[i],
|
playlistMode: selectedPlaylistMode[i],
|
||||||
playlists: game.playlists.entities
|
playlists: game.playlists.entities
|
||||||
}
|
}
|
||||||
playlistData.push(dataThis);
|
playlistData.push(dataThis);
|
||||||
}
|
}
|
||||||
if (!this.data && selectedPlaylists) {
|
|
||||||
this.data = selectedPlaylists;
|
this.data = {
|
||||||
|
playMode: playMode,
|
||||||
|
playlistNumber: numberOfPlaylists,
|
||||||
|
selectedPlaylist: selectedPlaylists,
|
||||||
|
playlistMode: selectedPlaylistMode
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
playlists: game.playlists.entities,
|
playlists: game.playlists.entities,
|
||||||
numberOfPlaylists: numberOfPlaylists,
|
numberOfPlaylists: numberOfPlaylists,
|
||||||
playlistData: playlistData,
|
playlistData: playlistData,
|
||||||
playMethod: game.settings.get(MODULE.moduleName,'playlistMethod')
|
playMode: playMode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,21 +72,48 @@ export class playlistConfigForm extends FormApplication {
|
|||||||
* @param {*} formData
|
* @param {*} formData
|
||||||
*/
|
*/
|
||||||
async _updateObject(event, formData) {
|
async _updateObject(event, formData) {
|
||||||
await game.settings.set(MODULE.moduleName,'selectedPlaylists', formData["selectedPlaylist"]);
|
// await game.settings.set(MODULE.moduleName,'selectedPlaylists', formData["selectedPlaylist"]);
|
||||||
await game.settings.set(MODULE.moduleName,'playlistMethod',formData["playMethod"]);
|
// await game.settings.set(MODULE.moduleName,'playlistMethod',formData["playMethod"]);
|
||||||
await game.settings.set(MODULE.moduleName,'numberOfPlaylists',formData["plNum"]);
|
// await game.settings.set(MODULE.moduleName,'numberOfPlaylists',formData["plNum"]);
|
||||||
await game.settings.set(MODULE.moduleName,'selectedPlaylistMethod',formData["playlistMethod"]);
|
// await game.settings.set(MODULE.moduleName,'selectedPlaylistMode',formData["playlistMethod"]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
const playMode = html.find("select[name='playMode']");
|
||||||
const numberOfPlaylists = html.find("input[name='plNum']");
|
const numberOfPlaylists = html.find("input[name='plNum']");
|
||||||
|
const selectedPlaylist = html.find("select[name='selectedPlaylist']");
|
||||||
|
const playlistMode = html.find("select[name='playlistMode']");
|
||||||
|
|
||||||
|
playMode.on("change", event => {
|
||||||
|
this.data.playMode=event.target.value;
|
||||||
|
this.updateSettings(this.data);
|
||||||
|
});
|
||||||
|
|
||||||
numberOfPlaylists.on("change", event => {
|
numberOfPlaylists.on("change", event => {
|
||||||
this.playlistNr = event.target.value;
|
this.playlistNr = event.target.value;
|
||||||
this.updatePlaylistNr = true;
|
this.updatePlaylistNr = true;
|
||||||
this.render();
|
this.data.playlistNumber=event.target.value;
|
||||||
|
this.updateSettings(this.data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
selectedPlaylist.on("change", event => {
|
||||||
|
let id = event.target.id.replace('playlist','');
|
||||||
|
this.data.selectedPlaylist[id-1]=event.target.value;
|
||||||
|
this.updateSettings(this.data);
|
||||||
|
});
|
||||||
|
|
||||||
|
playlistMode.on("change", event => {
|
||||||
|
let id = event.target.id.replace('playlistMode','');
|
||||||
|
this.data.playlistMode[id-1]=event.target.value;
|
||||||
|
this.updateSettings(this.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async updateSettings(settings){
|
||||||
|
await game.settings.set(MODULE.moduleName,'playlists', settings);
|
||||||
|
if (MODULE.enableModule) playlistControl.updateAll();
|
||||||
|
this.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +153,7 @@ export class macroConfigForm extends FormApplication {
|
|||||||
getData() {
|
getData() {
|
||||||
var selectedMacros = game.settings.get(MODULE.moduleName,'macroSettings').macros;
|
var selectedMacros = game.settings.get(MODULE.moduleName,'macroSettings').macros;
|
||||||
var color = game.settings.get(MODULE.moduleName,'macroSettings').color;
|
var color = game.settings.get(MODULE.moduleName,'macroSettings').color;
|
||||||
var args = game.settings.get(MODULE.moduleName,'macroArgs');
|
var args = game.settings.get(MODULE.moduleName,'macroSettings').args;
|
||||||
if (selectedMacros == undefined) selectedMacros = [];
|
if (selectedMacros == undefined) selectedMacros = [];
|
||||||
if (color == undefined) color = [];
|
if (color == undefined) color = [];
|
||||||
if (args == undefined) args = [];
|
if (args == undefined) args = [];
|
||||||
@@ -191,9 +228,11 @@ export class macroConfigForm extends FormApplication {
|
|||||||
* @param {*} formData
|
* @param {*} formData
|
||||||
*/
|
*/
|
||||||
async _updateObject(event, formData) {
|
async _updateObject(event, formData) {
|
||||||
|
/*
|
||||||
await game.settings.set(MODULE.moduleName,'macroSettings',{
|
await game.settings.set(MODULE.moduleName,'macroSettings',{
|
||||||
macros: formData["macros"],
|
macros: formData["macros"],
|
||||||
color: formData["colorPicker"]
|
color: formData["colorPicker"],
|
||||||
|
args: formData["args"]
|
||||||
});
|
});
|
||||||
|
|
||||||
let furnace = game.modules.get("furnace");
|
let furnace = game.modules.get("furnace");
|
||||||
@@ -201,10 +240,41 @@ export class macroConfigForm extends FormApplication {
|
|||||||
await game.settings.set(MODULE.moduleName,'macroArgs', formData["args"]);
|
await game.settings.set(MODULE.moduleName,'macroArgs', formData["args"]);
|
||||||
if (MODULE.enableModule)
|
if (MODULE.enableModule)
|
||||||
macroControl.updateAll();
|
macroControl.updateAll();
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
const macro = html.find("select[name='macros']");
|
||||||
|
const args = html.find("input[name='args']");
|
||||||
|
const color = html.find("input[name='colorPicker']");
|
||||||
|
|
||||||
|
macro.on("change", event => {
|
||||||
|
let id = event.target.id.replace('macros','');
|
||||||
|
let settings = game.settings.get(MODULE.moduleName,'macroSettings');
|
||||||
|
settings.macros[id-1]=event.target.value;
|
||||||
|
this.updateSettings(settings);
|
||||||
|
});
|
||||||
|
|
||||||
|
args.on("change", event => {
|
||||||
|
let id = event.target.id.replace('args','');
|
||||||
|
let settings = game.settings.get(MODULE.moduleName,'macroSettings');
|
||||||
|
settings.args[id-1]=event.target.value;
|
||||||
|
this.updateSettings(settings);
|
||||||
|
});
|
||||||
|
|
||||||
|
color.on("change", event => {
|
||||||
|
let id = event.target.id.replace('colorpicker','');
|
||||||
|
let settings = game.settings.get(MODULE.moduleName,'macroSettings');
|
||||||
|
settings.color[id-1]=event.target.value;
|
||||||
|
this.updateSettings(settings);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateSettings(settings){
|
||||||
|
await game.settings.set(MODULE.moduleName,'macroSettings',settings);
|
||||||
|
if (MODULE.enableModule) macroControl.updateAll();
|
||||||
|
this.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,6 +287,9 @@ export class soundboardConfigForm extends FormApplication {
|
|||||||
//this.soundData = {};
|
//this.soundData = {};
|
||||||
this.playlists = [];
|
this.playlists = [];
|
||||||
this.updatePlaylist = false;
|
this.updatePlaylist = false;
|
||||||
|
this.update = false;
|
||||||
|
this.iMax;
|
||||||
|
this.jMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -250,7 +323,11 @@ export class soundboardConfigForm extends FormApplication {
|
|||||||
/**
|
/**
|
||||||
* Provide data to the template
|
* Provide data to the template
|
||||||
*/
|
*/
|
||||||
getData() {
|
getData() {
|
||||||
|
if (this.update) {
|
||||||
|
this.update=false;
|
||||||
|
return {soundData: this.data};
|
||||||
|
}
|
||||||
let selectedSounds = game.settings.get(MODULE.moduleName,'soundboardSettings').sounds;
|
let selectedSounds = game.settings.get(MODULE.moduleName,'soundboardSettings').sounds;
|
||||||
let colorOn = game.settings.get(MODULE.moduleName,'soundboardSettings').colorOn;
|
let colorOn = game.settings.get(MODULE.moduleName,'soundboardSettings').colorOn;
|
||||||
let colorOff = game.settings.get(MODULE.moduleName,'soundboardSettings').colorOff;
|
let colorOff = game.settings.get(MODULE.moduleName,'soundboardSettings').colorOff;
|
||||||
@@ -279,29 +356,25 @@ export class soundboardConfigForm extends FormApplication {
|
|||||||
let soundData = [];
|
let soundData = [];
|
||||||
|
|
||||||
let streamDeckModel = game.settings.get(MODULE.moduleName,'streamDeckModel');
|
let streamDeckModel = game.settings.get(MODULE.moduleName,'streamDeckModel');
|
||||||
let iMax,jMax;
|
|
||||||
if (streamDeckModel == 0){
|
if (streamDeckModel == 0){
|
||||||
jMax = 6;
|
this.jMax = 6;
|
||||||
iMax = 3;
|
this.iMax = 3;
|
||||||
}
|
}
|
||||||
else if (streamDeckModel == 1){
|
else if (streamDeckModel == 1){
|
||||||
jMax = 6;
|
this.jMax = 6;
|
||||||
iMax = 5;
|
this.iMax = 5;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jMax = 8;
|
this.jMax = 8;
|
||||||
iMax = 8;
|
this.iMax = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.updatePlaylist) selectedPlaylists = this.playlists;
|
|
||||||
else this.playlists = selectedPlaylists;
|
|
||||||
this.updatePlaylist = false;
|
|
||||||
|
|
||||||
let iteration = 0;
|
let iteration = 0;
|
||||||
|
|
||||||
for (let j=0; j<jMax; j++){
|
for (let j=0; j<this.jMax; j++){
|
||||||
let soundsThis = [];
|
let soundsThis = [];
|
||||||
for (let i=0; i<iMax; i++){
|
for (let i=0; i<this.iMax; i++){
|
||||||
let selectedPlaylist;
|
let selectedPlaylist;
|
||||||
let sounds = [];
|
let sounds = [];
|
||||||
if (volume == undefined) volume = 50;
|
if (volume == undefined) volume = 50;
|
||||||
@@ -343,8 +416,10 @@ export class soundboardConfigForm extends FormApplication {
|
|||||||
};
|
};
|
||||||
soundData.push(data);
|
soundData.push(data);
|
||||||
}
|
}
|
||||||
|
this.data = soundData;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
soundData: soundData
|
soundData: this.data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,6 +429,7 @@ export class soundboardConfigForm extends FormApplication {
|
|||||||
* @param {*} formData
|
* @param {*} formData
|
||||||
*/
|
*/
|
||||||
async _updateObject(event, formData) {
|
async _updateObject(event, formData) {
|
||||||
|
/*
|
||||||
let length = formData["sounds"].length;
|
let length = formData["sounds"].length;
|
||||||
let img = [];
|
let img = [];
|
||||||
let soundSrc = []
|
let soundSrc = []
|
||||||
@@ -375,23 +451,160 @@ export class soundboardConfigForm extends FormApplication {
|
|||||||
mode: formData["mode"],
|
mode: formData["mode"],
|
||||||
img: img,
|
img: img,
|
||||||
volume: formData["volume"],
|
volume: formData["volume"],
|
||||||
name: formData["name"],
|
name: formData["namebox"],
|
||||||
src: soundSrc
|
src: soundSrc
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
async activateListeners(html) {
|
async activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
const nameField = html.find("input[name='namebox']");
|
||||||
const playlistSelect = html.find("select[name='playlist']");
|
const playlistSelect = html.find("select[name='playlist']");
|
||||||
|
const soundSelect = html.find("select[name='sounds']");
|
||||||
|
const soundFP = html.find("input[name2='soundSrc']");
|
||||||
|
const imgFP = html.find("input[name2='imgSrc']");
|
||||||
|
const onCP = html.find("input[name='colorOn']");
|
||||||
|
const offCP = html.find("input[name='colorOff']");
|
||||||
|
const playMode = html.find("select[name='mode']");
|
||||||
|
const volume = html.find("input[name='volume']");
|
||||||
|
|
||||||
|
nameField.on("change",event => {
|
||||||
|
let id = event.target.id.replace('name','');
|
||||||
|
let j = Math.floor(id/this.jMax);
|
||||||
|
let i = id % this.jMax-1;
|
||||||
|
this.data[j].dataThis[i].name=event.target.value;
|
||||||
|
this.update = true;
|
||||||
|
|
||||||
|
let settings = game.settings.get(MODULE.moduleName,'soundboardSettings');
|
||||||
|
settings.name[id-1]=event.target.value;
|
||||||
|
this.updateSettings(settings);
|
||||||
|
});
|
||||||
|
|
||||||
if (playlistSelect.length > 0) {
|
if (playlistSelect.length > 0) {
|
||||||
playlistSelect.on("change", event => {
|
playlistSelect.on("change", event => {
|
||||||
let id = event.target.id.replace('playlists','');
|
let id = event.target.id.replace('playlists','');
|
||||||
this.playlists[id-1] = event.target.value;
|
let j = Math.floor(id/this.jMax);
|
||||||
this.updatePlaylist = true;
|
let i = id % this.jMax-1;
|
||||||
this.render();
|
this.data[j].dataThis[i].selectedPlaylist=event.target.value;
|
||||||
|
|
||||||
|
let selectedPlaylist;
|
||||||
|
let sounds = [];
|
||||||
|
if (event.target.value==undefined) selectedPlaylist = 'none';
|
||||||
|
else if (event.target.value == 'none') selectedPlaylist = 'none';
|
||||||
|
else if (event.target.value == 'FP') selectedPlaylist = 'FP';
|
||||||
|
else {
|
||||||
|
const pl = game.playlists.entities.find(p => p._id == event.target.value);
|
||||||
|
selectedPlaylist = pl._id;
|
||||||
|
sounds = pl.sounds;
|
||||||
|
}
|
||||||
|
this.data[j].dataThis[i].sounds=sounds;
|
||||||
|
|
||||||
|
let styleSS = "";
|
||||||
|
let styleFP ="display:none";
|
||||||
|
if (selectedPlaylist == 'FP') {
|
||||||
|
styleSS = 'display:none';
|
||||||
|
styleFP = ''
|
||||||
|
}
|
||||||
|
this.data[j].dataThis[i].styleSS=styleSS;
|
||||||
|
this.data[j].dataThis[i].styleFP=styleFP;
|
||||||
|
this.update = true;
|
||||||
|
|
||||||
|
let settings = game.settings.get(MODULE.moduleName,'soundboardSettings');
|
||||||
|
settings.selectedPlaylists[id-1]=event.target.value;
|
||||||
|
this.updateSettings(settings);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
soundSelect.on("change", event => {
|
||||||
|
let id = event.target.id.replace('soundSelect','');
|
||||||
|
let j = Math.floor(id/this.jMax);
|
||||||
|
let i = id % this.jMax-1;
|
||||||
|
this.data[j].dataThis[i].sound=event.target.value;
|
||||||
|
this.update = true;
|
||||||
|
|
||||||
|
let settings = game.settings.get(MODULE.moduleName,'soundboardSettings');
|
||||||
|
settings.sounds[id-1]=event.target.value;
|
||||||
|
this.updateSettings(settings);
|
||||||
|
});
|
||||||
|
|
||||||
|
soundFP.on("change",event => {
|
||||||
|
let id = event.target.id.replace('srcPath','');
|
||||||
|
let j = Math.floor(id/this.jMax);
|
||||||
|
let i = id % this.jMax-1;
|
||||||
|
this.data[j].dataThis[i].srcPath=event.target.value;
|
||||||
|
this.update = true;
|
||||||
|
|
||||||
|
let settings = game.settings.get(MODULE.moduleName,'soundboardSettings');
|
||||||
|
settings.src[id-1]=event.target.value;
|
||||||
|
this.updateSettings(settings);
|
||||||
|
});
|
||||||
|
|
||||||
|
imgFP.on("change",event => {
|
||||||
|
let id = event.target.id.replace('imgPath','');
|
||||||
|
let j = Math.floor(id/this.jMax);
|
||||||
|
let i = id % this.jMax-1;
|
||||||
|
this.data[j].dataThis[i].imgPath=event.target.value;
|
||||||
|
this.update = true;
|
||||||
|
|
||||||
|
let settings = game.settings.get(MODULE.moduleName,'soundboardSettings');
|
||||||
|
settings.img[id-1]=event.target.value;
|
||||||
|
this.updateSettings(settings);
|
||||||
|
});
|
||||||
|
|
||||||
|
onCP.on("change",event => {
|
||||||
|
let id = event.target.id.replace('colorOn','');
|
||||||
|
let j = Math.floor(id/this.jMax);
|
||||||
|
let i = id % this.jMax-1;
|
||||||
|
this.data[j].dataThis[i].colorOn=event.target.value;
|
||||||
|
this.update = true;
|
||||||
|
|
||||||
|
let settings = game.settings.get(MODULE.moduleName,'soundboardSettings');
|
||||||
|
settings.colorOn[id-1]=event.target.value;
|
||||||
|
this.updateSettings(settings);
|
||||||
|
});
|
||||||
|
|
||||||
|
offCP.on("change",event => {
|
||||||
|
let id = event.target.id.replace('colorOff','');
|
||||||
|
let j = Math.floor(id/this.jMax);
|
||||||
|
let i = id % this.jMax-1;
|
||||||
|
this.data[j].dataThis[i].colorOff=event.target.value;
|
||||||
|
this.update = true;
|
||||||
|
|
||||||
|
let settings = game.settings.get(MODULE.moduleName,'soundboardSettings');
|
||||||
|
settings.colorOff[id-1]=event.target.value;
|
||||||
|
this.updateSettings(settings);
|
||||||
|
});
|
||||||
|
|
||||||
|
playMode.on("change",event => {
|
||||||
|
let id = event.target.id.replace('playmode','');
|
||||||
|
let j = Math.floor(id/this.jMax);
|
||||||
|
let i = id % this.jMax-1;
|
||||||
|
this.data[j].dataThis[i].mode=event.target.value;
|
||||||
|
this.update = true;
|
||||||
|
|
||||||
|
let settings = game.settings.get(MODULE.moduleName,'soundboardSettings');
|
||||||
|
settings.mode[id-1]=event.target.value;
|
||||||
|
this.updateSettings(settings);
|
||||||
|
});
|
||||||
|
|
||||||
|
volume.on("change",event => {
|
||||||
|
let id = event.target.id.replace('volume','');
|
||||||
|
let j = Math.floor(id/this.jMax);
|
||||||
|
let i = id % this.jMax-1;
|
||||||
|
this.data[j].dataThis[i].volume=event.target.value;
|
||||||
|
this.update = true;
|
||||||
|
|
||||||
|
let settings = game.settings.get(MODULE.moduleName,'soundboardSettings');
|
||||||
|
settings.volume[id-1]=event.target.value;
|
||||||
|
this.updateSettings(settings);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateSettings(settings){
|
||||||
|
await game.settings.set(MODULE.moduleName,'soundboardSettings',settings);
|
||||||
|
if (MODULE.enableModule) soundboard.updateAll();
|
||||||
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -136,21 +136,19 @@ export class PlaylistControl{
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let playing = game.playlists.playing;
|
let playing = game.playlists.playing;
|
||||||
console.log(playing);
|
let settings = game.settings.get(MODULE.moduleName,'playlists');
|
||||||
let selectedPlaylists = game.settings.get(MODULE.moduleName,'selectedPlaylists');
|
let selectedPlaylists = settings.selectedPlaylist;
|
||||||
console.log(selectedPlaylists);
|
|
||||||
for (let i=0; i<playing.length; i++){
|
for (let i=0; i<playing.length; i++){
|
||||||
const playlistNr = selectedPlaylists.findIndex(p => p == playing[i]._id);
|
const playlistNr = selectedPlaylists.findIndex(p => p == playing[i]._id);
|
||||||
const mode = game.settings.get(MODULE.moduleName,'selectedPlaylistMethod')[playlistNr];
|
const mode = settings.playlistMode[playlistNr];
|
||||||
if (mode == 0) playing[i].stopAll();
|
if (mode == 0) playing[i].stopAll();
|
||||||
console.log(playlistNr,mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlaylist(num){
|
getPlaylist(num){
|
||||||
let playlistId = game.settings.get(MODULE.moduleName,'selectedPlaylists')[num];
|
let playlistId = game.settings.get(MODULE.moduleName,'playlists').selectedPlaylist[num];
|
||||||
return game.playlists.entities.find(p => p._id == playlistId);
|
return game.playlists.entities.find(p => p._id == playlistId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,9 +200,9 @@ export class PlaylistControl{
|
|||||||
playlist.stopAll();
|
playlist.stopAll();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mode = game.settings.get(MODULE.moduleName,'selectedPlaylistMethod')[playlistNr];
|
let mode = game.settings.get(MODULE.moduleName,'playlists').playlistMode[playlistNr];
|
||||||
if (mode == 0) {
|
if (mode == 0) {
|
||||||
mode = game.settings.get(MODULE.moduleName,'playlistMethod');
|
mode = game.settings.get(MODULE.moduleName,'playlists').playMode;
|
||||||
if (mode == 2) await this.stopAll();
|
if (mode == 2) await this.stopAll();
|
||||||
}
|
}
|
||||||
playlist.playAll();
|
playlist.playAll();
|
||||||
@@ -216,10 +214,9 @@ export class PlaylistControl{
|
|||||||
play = false;
|
play = false;
|
||||||
else {
|
else {
|
||||||
play = true;
|
play = true;
|
||||||
let mode = game.settings.get(MODULE.moduleName,'selectedPlaylistMethod')[playlistNr];
|
let mode = game.settings.get(MODULE.moduleName,'playlists').playlistMode[playlistNr];
|
||||||
console.log('mode',mode);
|
|
||||||
if (mode == 0) {
|
if (mode == 0) {
|
||||||
mode = game.settings.get(MODULE.moduleName,'playlistMethod');
|
mode = game.settings.get(MODULE.moduleName,'playlists').playMode;
|
||||||
if (mode == 1) await playlist.stopAll();
|
if (mode == 1) await playlist.stopAll();
|
||||||
else if (mode == 2) await this.stopAll();
|
else if (mode == 2) await this.stopAll();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,15 +42,6 @@ export const registerSettings = function() {
|
|||||||
/**
|
/**
|
||||||
* Playlist soundboard
|
* Playlist soundboard
|
||||||
*/
|
*/
|
||||||
game.settings.register(MODULE.moduleName,'playlistMethod', {
|
|
||||||
name: "Playlist play method",
|
|
||||||
scope: "world",
|
|
||||||
config: false,
|
|
||||||
type:Number,
|
|
||||||
default:0,
|
|
||||||
choices:["MaterialDeck.Playlist.Playmethod.Unrestricted","MaterialDeck.Playlist.Playmethod.OneTrackPlaylist","MaterialDeck.Playlist.Playmethod.OneTrackTotal"],
|
|
||||||
});
|
|
||||||
|
|
||||||
game.settings.registerMenu(MODULE.moduleName, 'playlistConfigMenu',{
|
game.settings.registerMenu(MODULE.moduleName, 'playlistConfigMenu',{
|
||||||
name: "MaterialDeck.Sett.PlaylistConfig",
|
name: "MaterialDeck.Sett.PlaylistConfig",
|
||||||
label: "MaterialDeck.Sett.PlaylistConfig",
|
label: "MaterialDeck.Sett.PlaylistConfig",
|
||||||
@@ -58,7 +49,7 @@ export const registerSettings = function() {
|
|||||||
restricted: true
|
restricted: true
|
||||||
});
|
});
|
||||||
|
|
||||||
game.settings.register(MODULE.moduleName, 'selectedPlaylists', {
|
game.settings.register(MODULE.moduleName, 'playlists', {
|
||||||
name: "selectedPlaylists",
|
name: "selectedPlaylists",
|
||||||
scope: "world",
|
scope: "world",
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -66,22 +57,6 @@ export const registerSettings = function() {
|
|||||||
config: false
|
config: false
|
||||||
});
|
});
|
||||||
|
|
||||||
game.settings.register(MODULE.moduleName, 'selectedPlaylistMethod', {
|
|
||||||
name: "selectedPlaylistMethod",
|
|
||||||
scope: "world",
|
|
||||||
type: Object,
|
|
||||||
default: {},
|
|
||||||
config: false
|
|
||||||
});
|
|
||||||
|
|
||||||
game.settings.register(MODULE.moduleName, 'numberOfPlaylists', {
|
|
||||||
name: "numberOfPlaylists",
|
|
||||||
scope: "world",
|
|
||||||
type: Number,
|
|
||||||
default: 9,
|
|
||||||
config: false
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Macro Board
|
* Macro Board
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -75,7 +75,10 @@ export class StreamDeck{
|
|||||||
let txtArray = [];
|
let txtArray = [];
|
||||||
let counter = 0;
|
let counter = 0;
|
||||||
for (let i=0; i<txtArrayOriginal.length; i++){
|
for (let i=0; i<txtArrayOriginal.length; i++){
|
||||||
|
if (i>0){
|
||||||
|
txtArray[counter] = '';
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
let txtArrayTemp = txtArrayOriginal[i].split(" ");
|
let txtArrayTemp = txtArrayOriginal[i].split(" ");
|
||||||
for (let j=0; j<txtArrayTemp.length; j++){
|
for (let j=0; j<txtArrayTemp.length; j++){
|
||||||
txtArray[counter] = txtArrayTemp[j];
|
txtArray[counter] = txtArrayTemp[j];
|
||||||
|
|||||||
198
src/token.js
198
src/token.js
@@ -16,64 +16,128 @@ export class TokenControl{
|
|||||||
}
|
}
|
||||||
|
|
||||||
pushData(tokenId,settings,context,ring=0,ringColor='#000000'){
|
pushData(tokenId,settings,context,ring=0,ringColor='#000000'){
|
||||||
|
console.log('token',settings);
|
||||||
let name = false;
|
let name = false;
|
||||||
let icon = false;
|
let icon = false;
|
||||||
let type = 0;
|
let stats = settings.stats;
|
||||||
let background = "#000000";
|
let background = "#000000";
|
||||||
|
|
||||||
if (settings.displayIcon) icon = true;
|
if (settings.displayIcon) icon = true;
|
||||||
if (settings.displayName) name = true;
|
if (settings.displayName) name = true;
|
||||||
if (settings.stats != undefined) type = settings.stats;
|
if (stats == undefined) stats = 0;
|
||||||
if (settings.background) background = settings.background;
|
if (settings.background) background = settings.background;
|
||||||
|
|
||||||
|
let system = settings.system;
|
||||||
|
if (system == undefined) system = 'dnd5e';
|
||||||
|
|
||||||
let tokenName = "";
|
let tokenName = "";
|
||||||
let hp = "";
|
|
||||||
let AC = "";
|
|
||||||
let speed = "";
|
|
||||||
let initiative = "";
|
|
||||||
let txt = "";
|
let txt = "";
|
||||||
let iconSrc = "";
|
let iconSrc = "";
|
||||||
if (tokenId != undefined) {
|
if (tokenId != undefined) {
|
||||||
let token = canvas.tokens.children[0].children.find(p => p.id == tokenId);
|
let token = canvas.tokens.children[0].children.find(p => p.id == tokenId);
|
||||||
tokenName = token.data.name;
|
tokenName = token.data.name;
|
||||||
|
if (name) txt += tokenName;
|
||||||
|
if (name && stats != 0) txt += "\n";
|
||||||
iconSrc += token.data.img;
|
iconSrc += token.data.img;
|
||||||
let actor = canvas.tokens.children[0].children.find(p => p.id == tokenId).actor;
|
let actor = canvas.tokens.children[0].children.find(p => p.id == tokenId).actor;
|
||||||
let system = game.system.id;
|
if (system == 'dnd5e' && game.system.id == 'dnd5e'){
|
||||||
if (system == 'dnd5e'){
|
|
||||||
let attributes = actor.data.data.attributes;
|
let attributes = actor.data.data.attributes;
|
||||||
let hpCurrent = attributes.hp.value;
|
if (stats == 'HP') txt += attributes.hp.value + "/" + attributes.hp.max;
|
||||||
let hpMax = attributes.hp.max;
|
else if (stats == 'TempHP') {
|
||||||
hp = hpCurrent + "/" + hpMax;
|
txt += attributes.hp.temp;
|
||||||
AC = attributes.ac.value;
|
if (attributes.hp.tempmax != null)
|
||||||
|
txt += "/" + attributes.hp.tempmax;
|
||||||
if (attributes.speed._deprecated){
|
|
||||||
if (attributes.movement.burrow > 0) speed += attributes.movement.burrow + attributes.movement.units + " burrow";
|
|
||||||
if (attributes.movement.climb > 0) {
|
|
||||||
if (speed.length > 0) speed += '\n';
|
|
||||||
speed += attributes.movement.climb + attributes.movement.units + " climb";
|
|
||||||
}
|
|
||||||
if (attributes.movement.fly > 0) {
|
|
||||||
if (speed.length > 0) speed += '\n';
|
|
||||||
speed += attributes.movement.fly + attributes.movement.units + " fly";
|
|
||||||
}
|
|
||||||
if (attributes.movement.hover > 0) {
|
|
||||||
if (speed.length > 0) speed += '\n';
|
|
||||||
speed += attributes.movement.hover + attributes.movement.units + " hover";
|
|
||||||
}
|
|
||||||
if (attributes.movement.swim > 0) {
|
|
||||||
if (speed.length > 0) speed += '\n';
|
|
||||||
speed += attributes.movement.swim + attributes.movement.units + " swim";
|
|
||||||
}
|
|
||||||
if (attributes.movement.walk > 0) {
|
|
||||||
if (speed.length > 0) speed += '\n';
|
|
||||||
speed += attributes.movement.walk + attributes.movement.units + " walk";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else if (stats == 'AC') txt += attributes.ac.value;
|
||||||
speed = attributes.speed.value;
|
else if (stats == 'Speed'){
|
||||||
if (attributes.speed.special.length > 0) speed + "\n" + attributes.speed.special;
|
let speed = "";
|
||||||
|
if (attributes.speed._deprecated){
|
||||||
|
if (attributes.movement.burrow > 0) speed += game.i18n.localize("DND5E.MovementBurrow") + ': ' + attributes.movement.burrow + attributes.movement.units;
|
||||||
|
if (attributes.movement.climb > 0) {
|
||||||
|
if (speed.length > 0) speed += '\n';
|
||||||
|
speed += game.i18n.localize("DND5E.MovementClimb") + ': ' + attributes.movement.climb + attributes.movement.units;
|
||||||
|
}
|
||||||
|
if (attributes.movement.fly > 0) {
|
||||||
|
if (speed.length > 0) speed += '\n';
|
||||||
|
speed += game.i18n.localize("DND5E.MovementFly") + ': ' + attributes.movement.fly + attributes.movement.units;
|
||||||
|
}
|
||||||
|
if (attributes.movement.hover > 0) {
|
||||||
|
if (speed.length > 0) speed += '\n';
|
||||||
|
speed += game.i18n.localize("DND5E.MovementHover") + ': ' + attributes.movement.hover + attributes.movement.units;
|
||||||
|
}
|
||||||
|
if (attributes.movement.swim > 0) {
|
||||||
|
if (speed.length > 0) speed += '\n';
|
||||||
|
speed += game.i18n.localize("DND5E.MovementSwim") + ': ' + attributes.movement.swim + attributes.movement.units;
|
||||||
|
}
|
||||||
|
if (attributes.movement.walk > 0) {
|
||||||
|
if (speed.length > 0) speed += '\n';
|
||||||
|
speed += game.i18n.localize("DND5E.MovementWalk") + ': ' + attributes.movement.walk + attributes.movement.units;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
speed = attributes.speed.value;
|
||||||
|
if (attributes.speed.special.length > 0) speed + "\n" + attributes.speed.special;
|
||||||
|
}
|
||||||
|
txt += speed;
|
||||||
|
}
|
||||||
|
else if (stats == 'Init') txt += attributes.init.total;
|
||||||
|
else if (stats == 'PassivePerception') txt += actor.data.data.skills.prc.passive;
|
||||||
|
else if (stats == 'PassiveInvestigation') txt += actor.data.data.skills.inv.passive;
|
||||||
|
}
|
||||||
|
else if (system == 'dnd3.5e' && game.system.id == 'D35E'){
|
||||||
|
let attributes = actor.data.data.attributes;
|
||||||
|
if (stats == 'HP') txt += attributes.hp.value + "/" + attributes.hp.max;
|
||||||
|
else if (stats == 'TempHP') {
|
||||||
|
if (attributes.hp.temp == null) txt += '0';
|
||||||
|
else txt += attributes.hp.temp;
|
||||||
|
}
|
||||||
|
else if (stats == 'AC') txt += attributes.ac.normal.total;
|
||||||
|
else if (stats == 'Speed'){
|
||||||
|
let speed = "";
|
||||||
|
if (attributes.speed.burrow.total > 0) speed += 'Burrow: ' + attributes.speed.burrow.total + 'Ft';
|
||||||
|
if (attributes.speed.climb.total > 0) {
|
||||||
|
if (speed.length > 0) speed += '\n';
|
||||||
|
speed += 'Climb: ' + attributes.speed.climb.total + 'Ft';
|
||||||
|
}
|
||||||
|
if (attributes.speed.fly.total > 0) {
|
||||||
|
if (speed.length > 0) speed += '\n';
|
||||||
|
speed += 'Fly: ' + attributes.speed.fly.total + 'Ft';
|
||||||
|
}
|
||||||
|
if (attributes.speed.land.total > 0) {
|
||||||
|
if (speed.length > 0) speed += '\n';
|
||||||
|
speed += 'Land: ' + attributes.speed.land.total + 'Ft';
|
||||||
|
}
|
||||||
|
if (attributes.speed.swim.total > 0) {
|
||||||
|
if (speed.length > 0) speed += '\n';
|
||||||
|
speed += 'Swim: ' + attributes.speed.swim.total + 'Ft';
|
||||||
|
}
|
||||||
|
txt += speed;
|
||||||
|
}
|
||||||
|
else if (stats == 'Init') txt += attributes.init.total;
|
||||||
|
}
|
||||||
|
else if (system == 'pf2e' && game.system.id == 'pf2e'){
|
||||||
|
let attributes = actor.data.data.attributes;
|
||||||
|
if (stats == 'HP') txt += attributes.hp.value + "/" + attributes.hp.max;
|
||||||
|
else if (stats == 'TempHP') {
|
||||||
|
if (attributes.hp.temp == null) txt += '0';
|
||||||
|
else {
|
||||||
|
txt += attributes.hp.temp;
|
||||||
|
if (attributes.hp.tempmax > 0) txt += '/' + attributes.hp.tempmax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (stats == 'AC') txt += attributes.ac.value;
|
||||||
|
else if (stats == 'Speed'){
|
||||||
|
let speed = "Land: " + attributes.speed.value.replace('feet','') + ' feet';
|
||||||
|
const otherSpeeds = attributes.speed.otherSpeeds;
|
||||||
|
if (otherSpeeds.length > 0)
|
||||||
|
for (let i=0; i<otherSpeeds.length; i++)
|
||||||
|
speed += '\n' + otherSpeeds[i].type + ": " + otherSpeeds[i].value;
|
||||||
|
txt += speed;
|
||||||
|
}
|
||||||
|
else if (stats == 'Init') {
|
||||||
|
let init = attributes.initiative.totalModifier;
|
||||||
|
if (init != undefined) txt += init;
|
||||||
}
|
}
|
||||||
initiative = attributes.init.total;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//Other systems
|
//Other systems
|
||||||
@@ -82,6 +146,7 @@ export class TokenControl{
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.onClick == 4) { //toggle visibility
|
if (settings.onClick == 4) { //toggle visibility
|
||||||
ring = 1;
|
ring = 1;
|
||||||
if (token.data.hidden){
|
if (token.data.hidden){
|
||||||
@@ -119,18 +184,29 @@ export class TokenControl{
|
|||||||
ring = 1;
|
ring = 1;
|
||||||
let condition = settings.condition;
|
let condition = settings.condition;
|
||||||
if (condition == undefined) condition = 0;
|
if (condition == undefined) condition = 0;
|
||||||
|
|
||||||
if (condition == 0 && icon == false){
|
if (condition == 0 && icon == false){
|
||||||
iconSrc = window.CONFIG.controlIcons.effects;
|
iconSrc = window.CONFIG.controlIcons.effects;
|
||||||
}
|
}
|
||||||
else if (icon == false) {
|
else if (icon == false) {
|
||||||
let effect = CONFIG.statusEffects.find(e => e.id === this.getStatusId(condition));
|
if ((system == 'dnd5e' && game.system.id == 'dnd5e') || (system == 'dnd3.5e' && game.system.id == 'D35E')){
|
||||||
iconSrc = effect.icon;
|
let effect = CONFIG.statusEffects.find(e => e.id === this.getStatusId(condition));
|
||||||
let effects = token.actor.effects.entries;
|
iconSrc = effect.icon;
|
||||||
let active = effects.find(e => e.isTemporary === this.getStatusId(condition));
|
let effects = token.actor.effects.entries;
|
||||||
if (active != undefined){
|
let active = effects.find(e => e.isTemporary === this.getStatusId(condition));
|
||||||
ring = 2;
|
if (active != undefined){
|
||||||
ringColor = "#FF7B00";
|
ring = 2;
|
||||||
|
ringColor = "#FF7B00";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (system == 'pf2e' && game.system.id == 'pf2e') {
|
||||||
|
let effects = token.data.effects;
|
||||||
|
for (let i=0; i<effects.length; i++){
|
||||||
|
if (CONFIG.statusEffects[condition-1] == effects[i]){
|
||||||
|
ring = 2;
|
||||||
|
ringColor = "#FF7B00";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iconSrc = CONFIG.statusEffects[condition-1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
streamDeck.setIcon(1,context,iconSrc,background,ring,ringColor,true);
|
streamDeck.setIcon(1,context,iconSrc,background,ring,ringColor,true);
|
||||||
@@ -164,19 +240,16 @@ export class TokenControl{
|
|||||||
iconSrc = window.CONFIG.controlIcons.effects;
|
iconSrc = window.CONFIG.controlIcons.effects;
|
||||||
}
|
}
|
||||||
else if (icon == false) {
|
else if (icon == false) {
|
||||||
iconSrc = CONFIG.statusEffects.find(e => e.id === this.getStatusId(condition)).icon;
|
if ((system == 'dnd5e' && game.system.id == 'dnd5e') || (system == 'dnd3.5e' && game.system.id == 'D35E'))
|
||||||
|
iconSrc = CONFIG.statusEffects.find(e => e.id === this.getStatusId(condition)).icon;
|
||||||
|
else if (system == 'pf2e' && game.system.id == 'pf2e')
|
||||||
|
iconSrc = CONFIG.statusEffects[condition-1];
|
||||||
}
|
}
|
||||||
streamDeck.setIcon(1,context,iconSrc,background,1,'#000000',true);
|
streamDeck.setIcon(1,context,iconSrc,background,1,'#000000',true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (icon) streamDeck.setIcon(1,context,iconSrc,background,ring,ringColor);
|
if (icon) streamDeck.setIcon(1,context,iconSrc,background,ring,ringColor);
|
||||||
|
|
||||||
if (name) txt += tokenName;
|
|
||||||
if (name && type > 0) txt += "\n";
|
|
||||||
if (type == 1) txt += hp;
|
|
||||||
else if (type == 2) txt += AC;
|
|
||||||
else if (type == 3) txt += speed;
|
|
||||||
else if (type == 4) txt += initiative;
|
|
||||||
streamDeck.setTitle(txt,context);
|
streamDeck.setTitle(txt,context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,6 +263,9 @@ export class TokenControl{
|
|||||||
const token = canvas.tokens.children[0].children.find(p => p.id == tokenId);
|
const token = canvas.tokens.children[0].children.find(p => p.id == tokenId);
|
||||||
if (token == undefined) return;
|
if (token == undefined) return;
|
||||||
|
|
||||||
|
let system = settings.system;
|
||||||
|
if (system == undefined) system = 'dnd5e';
|
||||||
|
|
||||||
if (onClick == 0) //Do nothing
|
if (onClick == 0) //Do nothing
|
||||||
return;
|
return;
|
||||||
else if (onClick == 1){ //center on token
|
else if (onClick == 1){ //center on token
|
||||||
@@ -218,12 +294,20 @@ export class TokenControl{
|
|||||||
if (condition == 0){
|
if (condition == 0){
|
||||||
const effects = token.actor.effects.entries;
|
const effects = token.actor.effects.entries;
|
||||||
for (let i=0; i<effects.length; i++){
|
for (let i=0; i<effects.length; i++){
|
||||||
const effect = CONFIG.statusEffects.find(e => e.icon === effects[i].data.icon);
|
let effect;
|
||||||
|
if ((system == 'dnd5e' && game.system.id == 'dnd5e') || (system == 'dnd3.5e' && game.system.id == 'D35E'))
|
||||||
|
effect = CONFIG.statusEffects.find(e => e.icon === effects[i].data.icon);
|
||||||
|
else if (system == 'pf2e' && game.system.id == 'pf2e')
|
||||||
|
effect = CONFIG.statusEffects[condition-1];
|
||||||
await token.toggleEffect(effect)
|
await token.toggleEffect(effect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const effect = CONFIG.statusEffects.find(e => e.id === this.getStatusId(condition));
|
let effect;
|
||||||
|
if ((system == 'dnd5e' && game.system.id == 'dnd5e') || (system == 'dnd3.5e' && game.system.id == 'D35E'))
|
||||||
|
effect = CONFIG.statusEffects.find(e => e.id === this.getStatusId(condition));
|
||||||
|
else if (system == 'pf2e' && game.system.id == 'pf2e')
|
||||||
|
effect = CONFIG.statusEffects[condition-1];
|
||||||
token.toggleEffect(effect);
|
token.toggleEffect(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
{{localize "MaterialDeck.Macro"}} {{this.iteration}}
|
{{localize "MaterialDeck.Macro"}} {{this.iteration}}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<select name="macros" class="macros-select" default="" style="max-width:140px;">
|
<select name="macros" class="macros-select" id="macros{{this.iteration}}" default="" style="max-width:140px;">
|
||||||
{{#select this.macro}}
|
{{#select this.macro}}
|
||||||
<option value="">{{localize "MaterialDeck.None"}}</option>
|
<option value="">{{localize "MaterialDeck.None"}}</option>
|
||||||
{{#each macros}}
|
{{#each macros}}
|
||||||
@@ -27,19 +27,15 @@
|
|||||||
</div>
|
</div>
|
||||||
{{#if this.furnace}}
|
{{#if this.furnace}}
|
||||||
<label>{{localize "MaterialDeck.FurnaceArgs"}}</label>
|
<label>{{localize "MaterialDeck.FurnaceArgs"}}</label>
|
||||||
<input type="text" name="args" value="{{this.args}}">
|
<input type="text" name="args" id="args{{this.iteration}}" value="{{this.args}}">
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<div class="flex-container" style="display:flex;flex-direction:row;padding-top:10px">
|
<div class="flex-container" style="display:flex;flex-direction:row;padding-top:10px">
|
||||||
<label style="flex:1">{{localize "MaterialDeck.Background"}}</label>
|
<label style="flex:1">{{localize "MaterialDeck.Background"}}</label>
|
||||||
<input style="flex:1" type="color" name="colorPicker" data-dtype="String" value="{{this.color}}">
|
<input style="flex:1" type="color" name="colorPicker" id="colorpicker{{this.iteration}}" data-dtype="String" value="{{this.color}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
<button type="submit" name="submit">
|
|
||||||
<i class="far fa-save"></i> {{localize "MaterialDeck.Save"}}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
@@ -4,8 +4,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>{{localize "MaterialDeck.PL.Mode"}}</label>
|
<label>{{localize "MaterialDeck.PL.Mode"}}</label>
|
||||||
<select name="playMethod" class="playMethod" default="">
|
<select name="playMode" class="playMode" default="">
|
||||||
{{#select playMethod}}
|
{{#select playMode}}
|
||||||
<option value="0">{{localize "MaterialDeck.PL.Unrestricted"}}</option>
|
<option value="0">{{localize "MaterialDeck.PL.Unrestricted"}}</option>
|
||||||
<option value="1">{{localize "MaterialDeck.PL.OneTrackPlaylist"}}</option>
|
<option value="1">{{localize "MaterialDeck.PL.OneTrackPlaylist"}}</option>
|
||||||
<option value="2">{{localize "MaterialDeck.PL.OneTrackTotal"}}</option>
|
<option value="2">{{localize "MaterialDeck.PL.OneTrackTotal"}}</option>
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
{{#each playlistData}}
|
{{#each playlistData}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>{{localize "MaterialDeck.Playlist"}} {{this.iteration}}</label>
|
<label>{{localize "MaterialDeck.Playlist"}} {{this.iteration}}</label>
|
||||||
<select name="selectedPlaylist" class="playlist-select" default="">
|
<select name="selectedPlaylist" class="playlist-select" id="playlist{{this.iteration}}" default="">
|
||||||
{{#select this.playlist}}
|
{{#select this.playlist}}
|
||||||
<option value="">{{localize "MaterialDeck.None"}}</option>
|
<option value="">{{localize "MaterialDeck.None"}}</option>
|
||||||
{{#each this.playlists}}
|
{{#each this.playlists}}
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
{{/select}}
|
{{/select}}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select name="playlistMethod" class="playlistMethod" default="">
|
<select name="playlistMode" class="playlistMode" id="playlistMode{{this.iteration}}" default="">
|
||||||
{{#select this.playlistMethod}}
|
{{#select this.playlistMode}}
|
||||||
<option value="0">{{localize "MaterialDeck.PL.Mode"}}</option>
|
<option value="0">{{localize "MaterialDeck.PL.Mode"}}</option>
|
||||||
<option value="1">{{localize "MaterialDeck.PL.Unrestricted"}}</option>
|
<option value="1">{{localize "MaterialDeck.PL.Unrestricted"}}</option>
|
||||||
<option value="2">{{localize "MaterialDeck.PL.OneTrack"}}</option>
|
<option value="2">{{localize "MaterialDeck.PL.OneTrack"}}</option>
|
||||||
@@ -40,9 +40,4 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
<button type="submit" name="submit">
|
|
||||||
<i class="far fa-save"></i> {{localize "MaterialDeck.Save"}}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
<div style="text-align:center;">
|
<div style="text-align:center;">
|
||||||
{{localize "MaterialDeck.Name"}}
|
{{localize "MaterialDeck.Name"}}
|
||||||
</div>
|
</div>
|
||||||
<input type="text" name="name" value="{{this.name}}">
|
<input type="text" name="namebox" value="{{this.name}}" id="name{{this.iteration}}">
|
||||||
|
|
||||||
<div style="text-align:center;">
|
<div style="text-align:center;">
|
||||||
{{localize "MaterialDeck.Playlist"}}
|
{{localize "MaterialDeck.Playlist"}}
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
<button type="button" class="file-picker" data-type="audio" data-target="src{{this.iteration}}" title="Browse Files" tabindex="-1">
|
<button type="button" class="file-picker" data-type="audio" data-target="src{{this.iteration}}" title="Browse Files" tabindex="-1">
|
||||||
<i class="fas fa-file-import fa-fw"></i>
|
<i class="fas fa-file-import fa-fw"></i>
|
||||||
</button>
|
</button>
|
||||||
<input class="image" type="text" name="src{{this.iteration}}" id="srcPath{{this.iteration}}" placeholder="path/audio.mp3" value={{this.srcPath}}>
|
<input class="image" type="text" name="src{{this.iteration}}" name2="soundSrc" id="srcPath{{this.iteration}}" placeholder="path/audio.mp3" value={{this.srcPath}}>
|
||||||
</div>
|
</div>
|
||||||
<div style="text-align:center;">
|
<div style="text-align:center;">
|
||||||
{{localize "MaterialDeck.Icon"}}
|
{{localize "MaterialDeck.Icon"}}
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
<button type="button" class="file-picker" data-type="image" data-target="img{{this.iteration}}" title="Browse Files" tabindex="-1">
|
<button type="button" class="file-picker" data-type="image" data-target="img{{this.iteration}}" title="Browse Files" tabindex="-1">
|
||||||
<i class="fas fa-file-import fa-fw"></i>
|
<i class="fas fa-file-import fa-fw"></i>
|
||||||
</button>
|
</button>
|
||||||
<input class="image" type="text" name="img{{this.iteration}}" id="imgPath{{this.iteration}}" placeholder="path/image.png" value={{this.imgPath}}>
|
<input class="image" type="text" name="img{{this.iteration}}" name2="imgSrc" id="imgPath{{this.iteration}}" placeholder="path/image.png" value={{this.imgPath}}>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-container" style="display:flex;flex-direction:row;padding-top:5px">
|
<div class="flex-container" style="display:flex;flex-direction:row;padding-top:5px">
|
||||||
<label style="flex:1">{{localize "MaterialDeck.On"}} </label>
|
<label style="flex:1">{{localize "MaterialDeck.On"}} </label>
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
|
|
||||||
<div class="form-group options">
|
<div class="form-group options">
|
||||||
<label>{{localize "MaterialDeck.Playback"}}</label>
|
<label>{{localize "MaterialDeck.Playback"}}</label>
|
||||||
<select name="mode" style="flex:1">
|
<select name="mode" id="playmode{{this.iteration}}" style="flex:1">
|
||||||
{{#select this.mode}}
|
{{#select this.mode}}
|
||||||
<option value="0">{{localize "MaterialDeck.Once"}}</option>
|
<option value="0">{{localize "MaterialDeck.Once"}}</option>
|
||||||
<option value="1">{{localize "MaterialDeck.Repeat"}}</option>
|
<option value="1">{{localize "MaterialDeck.Repeat"}}</option>
|
||||||
@@ -87,8 +87,4 @@
|
|||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
<button type="submit" name="submit">
|
|
||||||
<i class="far fa-save"></i> {{localize "MaterialDeck.Save"}}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
Reference in New Issue
Block a user