Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
631fdbcccb | ||
|
|
9a7088a310 | ||
|
|
033a7351e4 | ||
|
|
be7f837f7d | ||
|
|
79cfc5769a | ||
|
|
fc7dcff3b0 | ||
|
|
abb883c8b8 |
45
.github/workflows/main.yml
vendored
Normal file
45
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
name: Release Creation
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
# get part of the tag after the `v`
|
||||
- name: Extract tag version number
|
||||
id: get_version
|
||||
uses: battila7/get-version-action@v2
|
||||
|
||||
# Substitute the Manifest and Download URLs in the module.json
|
||||
- name: Substitute Manifest and Download Links For Versioned Ones
|
||||
id: sub_manifest_link_version
|
||||
uses: microsoft/variable-substitution@v1
|
||||
with:
|
||||
files: 'module.json'
|
||||
env:
|
||||
version: ${{steps.get_version.outputs.version-without-v}}
|
||||
url: https://github.com/${{github.repository}}
|
||||
manifest: https://github.com/${{github.repository}}/releases/latest/download/module.json
|
||||
download: https://github.com/${{github.repository}}/releases/download/${{github.event.release.tag_name}}/module.zip
|
||||
|
||||
# Create a zip file with all files required by the module to add to the release
|
||||
- run: zip -r ./module.zip MaterialDeck.js module.json README.md DEVGUIDE.md changelog.md css/ wiki/ img/ lang/ src/ templates/
|
||||
|
||||
# Create a release for this specific version
|
||||
- name: Update Release with Files
|
||||
id: create_version_release
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
allowUpdates: true # Set this to false if you want to prevent updating existing releases
|
||||
name: ${{ github.event.release.name }}
|
||||
draft: ${{ github.event.release.unpublished }}
|
||||
prerelease: ${{ github.event.release.prerelease }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
artifacts: './module.json, ./module.zip'
|
||||
tag: ${{ github.event.release.tag_name }}
|
||||
body: ${{ github.event.release.body }}
|
||||
@@ -7,7 +7,7 @@ In addition to this repo, you will also need to check out the [MaterialDeck_SD g
|
||||
|
||||
### Make a new system.js file
|
||||
|
||||
In the [src/systems](src/systems) directory, create a new system file by copying and pasting a similar system to it; for example, `cp demonlord.js wfrp4.js`
|
||||
In the [src/systems](src/systems) directory, create a new system file by copying and pasting a similar system to it, or use template.js; for example, `cp demonlord.js wfrp4.js`
|
||||
You then need to go through all the functions in there and make sure that the correct data is set.
|
||||
|
||||
### Update TokenHelper
|
||||
|
||||
112
MaterialDeck.js
112
MaterialDeck.js
@@ -1,15 +1,19 @@
|
||||
import { registerSettings } from "./src/settings.js";
|
||||
import { StreamDeck } from "./src/streamDeck.js";
|
||||
import {TokenControl} from "./src/token.js";
|
||||
import {MacroControl} from "./src/macro.js";
|
||||
import {CombatTracker} from "./src/combattracker.js";
|
||||
import {PlaylistControl} from "./src/playlist.js";
|
||||
import {SoundboardControl} from "./src/soundboard.js";
|
||||
import {OtherControls} from "./src/othercontrols.js";
|
||||
import {ExternalModules} from "./src/external.js";
|
||||
import {SceneControl} from "./src/scene.js";
|
||||
import {downloadUtility, compatibleCore} from "./src/misc.js";
|
||||
import { TokenControl } from "./src/actions/token.js";
|
||||
import { MacroControl } from "./src/actions/macro.js";
|
||||
import { CombatTracker } from "./src/actions/combattracker.js";
|
||||
import { PlaylistControl } from "./src/actions/playlist.js";
|
||||
import { SoundboardControl } from "./src/actions/soundboard.js";
|
||||
import { OtherControls } from "./src/actions/othercontrols.js";
|
||||
import { ExternalModules } from "./src/actions/external.js";
|
||||
import { SceneControl } from "./src/actions/scene.js";
|
||||
import { downloadUtility, compareVersions, compatibleCore } from "./src/misc.js";
|
||||
import { TokenHelper } from "./src/systems/tokenHelper.js";
|
||||
|
||||
export const minimumSDversion = "1.4.11";
|
||||
export const minimumMSversion = "1.0.2";
|
||||
|
||||
export var streamDeck;
|
||||
export var tokenControl;
|
||||
export var macroControl;
|
||||
@@ -20,21 +24,15 @@ export var otherControls;
|
||||
export var externalModules;
|
||||
export var sceneControl;
|
||||
export var tokenHelper;
|
||||
|
||||
export const moduleName = "MaterialDeck";
|
||||
|
||||
export let gamingSystem = "dnd5e";
|
||||
|
||||
let ready = false;
|
||||
|
||||
export let hotbarUses = false;
|
||||
export let calculateHotbarUses;
|
||||
|
||||
let controlTokenTimer;
|
||||
|
||||
export let sdVersion;
|
||||
export let msVersion;
|
||||
|
||||
let ready = false;
|
||||
let controlTokenTimer;
|
||||
let updateDialog;
|
||||
|
||||
//CONFIG.debug.hooks = true;
|
||||
@@ -67,33 +65,58 @@ async function analyzeWSmessage(msg){
|
||||
const msg = {
|
||||
target: "SD",
|
||||
type: "init",
|
||||
system: gamingSystem
|
||||
system: getGamingSystem(),
|
||||
coreVersion: game.version.split('.')[0]
|
||||
}
|
||||
ws.send(JSON.stringify(msg));
|
||||
if (data.MSversion) msVersion = data.MSversion;
|
||||
if (data.SDversion) sdVersion = data.SDversion;
|
||||
|
||||
|
||||
console.log("streamdeck connected to server");
|
||||
console.log("streamdeck connected to server", msVersion);
|
||||
streamDeck.resetImageBuffer();
|
||||
}
|
||||
|
||||
if (data.type == "version" && data.source == "SD") {
|
||||
let minimumSDversion;
|
||||
let minimumMSversion;
|
||||
if (compatibleCore("0.8.5")) {
|
||||
minimumSDversion = game.modules.get("MaterialDeck").data.flags.minimumSDversion.replace('v','');
|
||||
minimumMSversion = game.modules.get("MaterialDeck").data.flags.minimumMSversion;
|
||||
}
|
||||
else {
|
||||
minimumSDversion = game.modules.get("MaterialDeck").data.minimumSDversion.replace('v','');
|
||||
minimumMSversion = game.modules.get("MaterialDeck").data.minimumMSversion;
|
||||
}
|
||||
|
||||
sdVersion = data.version;
|
||||
|
||||
if (data.version < minimumSDversion && updateDialog == undefined) {
|
||||
const sdCompatible = compareVersions(minimumSDversion,sdVersion);
|
||||
const msCompatible = compareVersions(minimumMSversion,msVersion);
|
||||
|
||||
if ((!sdCompatible || !msCompatible) && updateDialog == undefined) {
|
||||
let content = "";
|
||||
|
||||
if (!sdCompatible && !msCompatible)
|
||||
content = game.i18n.localize("MaterialDeck.SdMsUpdateRequired")
|
||||
else if (!sdCompatible)
|
||||
content = game.i18n.localize("MaterialDeck.SdUpdateRequired")
|
||||
else
|
||||
content = game.i18n.localize("MaterialDeck.MsUpdateRequired")
|
||||
const sd = sdCompatible ? 'display:none' : ''
|
||||
const ms = msCompatible ? 'display:none' : ''
|
||||
content += `
|
||||
<table>
|
||||
<tr>
|
||||
<th style='width:40%'>
|
||||
<th style='width:30%'>${game.i18n.localize("MaterialDeck.DownloadUtility.Current")}</th>
|
||||
<th style='width:30%'>${game.i18n.localize("MaterialDeck.DownloadUtility.Minimum")}</th>
|
||||
</tr>
|
||||
<tr style="${sd}">
|
||||
<td>Stream Deck Plugin</td>
|
||||
<td><center>${sdVersion}</center></td>
|
||||
<td><center>${minimumSDversion}</center></td>
|
||||
</tr>
|
||||
<tr style="${ms}">
|
||||
<td>Material Server</th>
|
||||
<td><center>${msVersion}</center></td>
|
||||
<td><center>${minimumMSversion}</center></td>
|
||||
<tr>
|
||||
</table>
|
||||
`
|
||||
//else if (!sdCompatible) contents += `The Stream Deck plugin version you're using is v${data.version}, which is incompatible with this version of the module.<br>Update to v${minimumSDversion} or newer.`;
|
||||
|
||||
updateDialog = new Dialog({
|
||||
title: "Material Deck: Update Needed",
|
||||
content: "<p>The Stream Deck plugin version you're using is v" + data.version + ", which is incompatible with this verion of the module.<br>Update to v" + minimumSDversion + " or newer.</p>",
|
||||
content,
|
||||
buttons: {
|
||||
download: {
|
||||
icon: '<i class="fas fa-download"></i>',
|
||||
@@ -224,7 +247,8 @@ function startWebsocket() {
|
||||
const msg2 = {
|
||||
target: "SD",
|
||||
type: "init",
|
||||
system: gamingSystem
|
||||
system: getGamingSystem(),
|
||||
coreVersion: game.version.split('.')[0]
|
||||
}
|
||||
ws.send(JSON.stringify(msg2));
|
||||
clearInterval(wsInterval);
|
||||
@@ -278,6 +302,11 @@ export function getPermission(action,func) {
|
||||
else return settings.permissions?.[action]?.[func]?.[role];
|
||||
}
|
||||
|
||||
function getGamingSystem() {
|
||||
const systemOverride = game.settings.get(moduleName,'systemOverride');
|
||||
gamingSystem = (systemOverride == undefined || systemOverride == null || systemOverride == '') ? game.system.id : systemOverride;
|
||||
return gamingSystem;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -290,11 +319,10 @@ export function getPermission(action,func) {
|
||||
* Attempt to open the websocket
|
||||
*/
|
||||
Hooks.once('ready', async()=>{
|
||||
registerSettings();
|
||||
await registerSettings();
|
||||
enableModule = (game.settings.get(moduleName,'Enable')) ? true : false;
|
||||
|
||||
const systemOverride = game.settings.get(moduleName,'systemOverride');
|
||||
gamingSystem = systemOverride != '' ? systemOverride : game.system.id;
|
||||
getGamingSystem();
|
||||
|
||||
soundboard = new SoundboardControl();
|
||||
streamDeck = new StreamDeck();
|
||||
@@ -435,7 +463,7 @@ Hooks.on('onActorSetCondition',(data)=>{
|
||||
Hooks.on('controlToken',(token,controlled)=>{
|
||||
if (enableModule == false || ready == false) return;
|
||||
if (controlled) {
|
||||
tokenControl.update(token.data._id);
|
||||
tokenControl.update(compatibleCore('10.0') ? token.id : token.data._id);
|
||||
if (controlTokenTimer != undefined) {
|
||||
clearTimeout(controlTokenTimer);
|
||||
controlTokenTimer = undefined;
|
||||
@@ -459,9 +487,7 @@ Hooks.on('renderHotbar', (hotbar)=>{
|
||||
|
||||
Hooks.on('render', (app)=>{
|
||||
if (enableModule == false || ready == false) return;
|
||||
if (compatibleCore("0.8.1") == false) return;
|
||||
if (app.id == "hotbar" && macroControl != undefined) macroControl.hotbar(app.macros);
|
||||
|
||||
});
|
||||
|
||||
Hooks.on('renderCombatTracker',()=>{
|
||||
@@ -486,6 +512,11 @@ Hooks.on('closeplaylistConfigForm', (form)=>{
|
||||
playlistControl.updateAll();
|
||||
});
|
||||
|
||||
Hooks.on('lightingRefresh',()=>{
|
||||
if (enableModule == false || ready == false) return;
|
||||
if (tokenControl != undefined) tokenControl.update();
|
||||
});
|
||||
|
||||
Hooks.on('pauseGame',()=>{
|
||||
if (enableModule == false || ready == false) return;
|
||||
otherControls.updateAll();
|
||||
@@ -610,6 +641,7 @@ Hooks.on('updateTile',()=>{
|
||||
Hooks.once('init', ()=>{
|
||||
//CONFIG.debug.hooks = true;
|
||||
//registerSettings(); //in ./src/settings.js
|
||||
|
||||
});
|
||||
|
||||
Hooks.once('canvasReady',()=>{
|
||||
|
||||
62
changelog.md
62
changelog.md
@@ -1,4 +1,66 @@
|
||||
# Changelog Material Deck Module
|
||||
### v1.4.12 - 07-09-2022
|
||||
Fixes:
|
||||
<ul>
|
||||
<li>Some settings did not have a default value, which caused errors for new users in v10</li>
|
||||
</ul>
|
||||
|
||||
### v1.4.11 - 05-09-2022
|
||||
Fixes:
|
||||
<ul>
|
||||
<li>Fixed system autodetection bug, where it would not always correctly detect the system</li>
|
||||
<li>Token Action => Stats/On Click: Pf2e intimidation did not work</li>
|
||||
<li>Playlist Action => Fix unrestricted playback and 'play playlist'</li>
|
||||
<li>User Config: Fix settings saving issue</li>
|
||||
</ul>
|
||||
|
||||
Additions:
|
||||
<ul>
|
||||
<li>Token Action => Inventory: Added roll options to roll for to hit and damage (dnd5e only)</li>
|
||||
<li>Token Action => Inventory/Features/Spellbook: Select by name or id</li>
|
||||
<li>Token Action => Features: Added option to filter active and passive abilities (dnd5e only)</li>
|
||||
<li>Token Action => Items/Spells/Features: Add offset options</li>
|
||||
<li>Token Action => OnClick => SetVision: Added checkboxes to configure what settings should be changed</li>
|
||||
<li>Combat Tracker => Function: Added option to roll initiative for combatants</li>
|
||||
<li>Combat Tracker => OnClick: Added target and untarget token option</li>
|
||||
<li>Other Actions => Darkness Control: Added 'Transition to Day' and 'Transition to Night' options</li>
|
||||
<li>Other Actions => Darkness Control: Added animation time option for darkness changes</li>
|
||||
</ul>
|
||||
|
||||
Other:
|
||||
<ul>
|
||||
<li>Made compatible with Foundry v10 (see notes below), dropped compatibility with Foundry v8</li>
|
||||
<li>Token Action => On Click => Call Macro: Removed macro target, since I can't get it to work properly</li>
|
||||
<li>Token Action => On Click => Movement: Tokens now snap to the grid when moved</li>
|
||||
<li>Token Action => OnClick => SetVision: update configuration to v9/v10 standards</li>
|
||||
<li>Token Action => Handle Conditions: Removed the increase/decrease option for all systems but pf2e (it only works in pf2e)</li>
|
||||
<li>System Override: Changed to a dropdown menu with all supported systems, instead of a string field</li>
|
||||
<li>All ui elements and classes have been given unique identifiers to prevent module incompatibilities</li>
|
||||
</ul>
|
||||
|
||||
V10 Compatibility Notes:
|
||||
<ul>
|
||||
<li>The following systems have been tested in v10: dnd5e, pf1e, forbidden lands, wfrp4. Other systems have not been updated to v10 yet at the time of this update</li>
|
||||
<li>Changing the token vision mode through MD does not work properly, appears to be a bug in Foundry</li>
|
||||
<li>Wildcard images currently don't seem to work in v10, so they have not been tested</li>
|
||||
</ul>
|
||||
|
||||
<b>Compatible server app and SD plugin:</b><br>
|
||||
Material Server v1.0.2+ (unchanged): https://github.com/CDeenen/MaterialServer/releases <br>
|
||||
SD plugin v1.4.11 (<b>must be updated!</b>): https://github.com/CDeenen/MaterialDeck_SD/releases<br>
|
||||
|
||||
### v1.4.10 - 30-05-2022
|
||||
Fixes:
|
||||
<ul>
|
||||
<li>Stream Deck plugin v1.4.10 was not properly recognized as compatible</li>
|
||||
</ul>
|
||||
|
||||
Additions:
|
||||
<ul>
|
||||
<li>Material Server version is now displayed in the Download Utility (MS v1.1.0+)</li>
|
||||
</ul>
|
||||
|
||||
|
||||
### v1.4.9 - 16-04-2022
|
||||
Fixes:
|
||||
<ul>
|
||||
|
||||
175
css/style.css
Normal file
175
css/style.css
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Device Config
|
||||
*/
|
||||
.materialDeck_devConf_columnLabel {
|
||||
max-width:30%;
|
||||
min-width:30%;
|
||||
text-align: left;
|
||||
}
|
||||
.materialDeck_devConf_columnId {
|
||||
max-width:25%;
|
||||
min-width:25%;
|
||||
text-align: left;
|
||||
text-overflow: hidden;
|
||||
}
|
||||
.materialDeck_devConf_columnCB {
|
||||
width:10%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/*
|
||||
* Download Utility
|
||||
*/
|
||||
.materialDeck_dlUtil_columnLabel {
|
||||
width:25%;
|
||||
text-align: left;
|
||||
}
|
||||
.materialDeck_dlUtil_columnVersion {
|
||||
width:15%;
|
||||
text-align: left;
|
||||
}
|
||||
.materialDeck_dlUtil_columnOS {
|
||||
width:15%;
|
||||
}
|
||||
.materialDeck_dlUtil_columnButton {
|
||||
width:15%;
|
||||
}
|
||||
.materialDeck_dlUtil_button {
|
||||
width:100%;
|
||||
}
|
||||
|
||||
/*
|
||||
* Macro Config
|
||||
*/
|
||||
.materialDeck_macroConfig_boxed {
|
||||
border: 1px solid black ;
|
||||
border-radius: 5px ;
|
||||
max-width: 166px;
|
||||
padding: 5px;
|
||||
margin:2px;
|
||||
width:10%;
|
||||
}
|
||||
|
||||
.materialDeck_macroConfig_navigationDiv {
|
||||
width:100%;
|
||||
display:flex;
|
||||
flex-direction:row;
|
||||
}
|
||||
|
||||
.materialDeck_macroConfig_navigation {
|
||||
flex:1;
|
||||
max-width: 8%;
|
||||
}
|
||||
|
||||
.materialDeck_macroConfig_p {
|
||||
width:84%;
|
||||
text-align:center;
|
||||
padding: 0px 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.materialDeck_macroConfig_background {
|
||||
display:flex;
|
||||
flex-direction:row;
|
||||
padding-top:10px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Playlist Config
|
||||
*/
|
||||
.materialDeck_plConfig_select {
|
||||
width: 35%;
|
||||
max-width: 35%;
|
||||
}
|
||||
|
||||
/*
|
||||
* Soundboard Config
|
||||
*/
|
||||
.materialDeck_sbConfig_boxed {
|
||||
border: 1px solid black ;
|
||||
border-radius: 5px ;
|
||||
max-width: 166px;
|
||||
height: 300px;
|
||||
padding: 5px;
|
||||
margin:2px;
|
||||
width:10%
|
||||
}
|
||||
|
||||
.materialDeck_sbConfig_navigationDiv {
|
||||
flex:1;
|
||||
width:100%;
|
||||
display:flex;
|
||||
flex-direction:row;
|
||||
}
|
||||
|
||||
.materialDeck_sbConfig_navigation {
|
||||
flex:1;
|
||||
}
|
||||
|
||||
.materialDeck_sbConfig_p {
|
||||
flex:15;
|
||||
text-align:center;
|
||||
padding: 0px 0;
|
||||
font-size: 20px
|
||||
}
|
||||
|
||||
/*
|
||||
* User Permission Config
|
||||
*/
|
||||
header.materialDeck_uPerm_table-header {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
padding: 5px;
|
||||
border: 1px solid #191813;
|
||||
text-align: center;
|
||||
color: #f0f0e0;
|
||||
font-weight: bold;
|
||||
text-shadow: 1px 1px #000;
|
||||
}
|
||||
|
||||
ul.materialDeck_uPerm_permissions-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
overflow: hidden auto;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
li.materialDeck_uPerm_permission {
|
||||
padding: 5px;
|
||||
border-bottom: 1px solid #7a7971;
|
||||
}
|
||||
|
||||
li.materialDeck_uPerm_permission .form-fields {
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
li.materialDeck_uPerm_permission input[type="checkbox"] {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.materialDeck_uPerm_index {
|
||||
flex: 0 0 200px;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.materialDeck_uPerm_hint {
|
||||
flex: 0 0 100%;
|
||||
color: #4b4a44;
|
||||
font-size: 13px;
|
||||
margin: 5px 0 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Help Menu
|
||||
*/
|
||||
.materialDeck_helpMenu_expandable {
|
||||
cursor: pointer;
|
||||
}
|
||||
.materialDeck_helpMenu_collapsed {
|
||||
display:none;
|
||||
}
|
||||
.materialDeck_helpMenu_expandableIcon {
|
||||
border: none;
|
||||
}
|
||||
BIN
img/.thumb/down.png.jpg
Normal file
BIN
img/.thumb/down.png.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
BIN
img/.thumb/right.png.jpg
Normal file
BIN
img/.thumb/right.png.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
BIN
img/down.png
Normal file
BIN
img/down.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.0 KiB |
BIN
img/right.png
Normal file
BIN
img/right.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
11
lang/en.json
11
lang/en.json
@@ -22,7 +22,7 @@
|
||||
"MaterialDeck.Sett.NrOfConnMessages": "Number of Connection Warnings",
|
||||
"MaterialDeck.Sett.NrOfConnMessagesHint": "Sets the number of times a connection warning is displayed if Material Deck cannot connect to Material Server. If set to 0, it will give not be limited.",
|
||||
"MaterialDeck.Sett.SystemOverride": "System Override",
|
||||
"MaterialDeck.Sett.SystemOverrideHint": "Overrides the automatic gaming system detection. Unsupported systems default to dnd5e, but if an unsupported system is similar to a different system you can specify that system here. Leave empty for system autodetection.",
|
||||
"MaterialDeck.Sett.SystemOverrideHint": "Overrides the automatic gaming system detection. Unsupported systems default to dnd5e, but if an unsupported system is similar to a different system you can specify that system here.",
|
||||
|
||||
"MaterialDeck.PL.Unrestricted": "Unrestricted",
|
||||
"MaterialDeck.PL.OneTrackPlaylist": "One track per playlist",
|
||||
@@ -205,10 +205,15 @@
|
||||
"MaterialDeck.DownloadUtility.SDplugin": "SD Plugin",
|
||||
"MaterialDeck.DownloadUtility.MSserver": "Material Server",
|
||||
"MaterialDeck.DownloadUtility.Windows": "Windows",
|
||||
"MaterialDeck.DownloadUtility.Macos": "MacOS",
|
||||
"MaterialDeck.DownloadUtility.MacosM1": "MacOS (M1)",
|
||||
"MaterialDeck.DownloadUtility.MacosIntel": "MacOS (Intel)",
|
||||
"MaterialDeck.DownloadUtility.Linux": "Linux",
|
||||
"MaterialDeck.DownloadUtility.Source": "Source",
|
||||
"MaterialDeck.DownloadUtility.Profiles": "Profiles",
|
||||
"MaterialDeck.DownloadUtility.Name": "Name",
|
||||
"MaterialDeck.DownloadUtility.Refresh": "Refresh"
|
||||
"MaterialDeck.DownloadUtility.Refresh": "Refresh",
|
||||
|
||||
"MaterialDeck.SdMsUpdateRequired": "The Stream Deck plugin and Material Server version you are using are incompatible with this version of the module.<br>Please update them.",
|
||||
"MaterialDeck.SdUpdateRequired": "The Stream Deck plugin you are using is incompatible with this version of the module.<br>Please update it.",
|
||||
"MaterialDeck.MsUpdateRequired": "The Material Server version you are using is incompatible with this version of the module.<br>Please update it."
|
||||
}
|
||||
@@ -200,7 +200,8 @@
|
||||
"MaterialDeck.DownloadUtility.SDplugin": "SDプラグイン",
|
||||
"MaterialDeck.DownloadUtility.MSserver": "Material Server",
|
||||
"MaterialDeck.DownloadUtility.Windows": "Windows",
|
||||
"MaterialDeck.DownloadUtility.Macos": "MacOS",
|
||||
"MaterialDeck.DownloadUtility.MacosM1": "MacOS (M1)",
|
||||
"MaterialDeck.DownloadUtility.MacosIntel": "MacOS (Intel)",
|
||||
"MaterialDeck.DownloadUtility.Linux": "Linux",
|
||||
"MaterialDeck.DownloadUtility.Source": "ソース",
|
||||
"MaterialDeck.DownloadUtility.Profiles": "プロファイル",
|
||||
|
||||
22
module.json
22
module.json
@@ -1,8 +1,9 @@
|
||||
{
|
||||
"name": "MaterialDeck",
|
||||
"id": "MaterialDeck",
|
||||
"title": "Material Deck",
|
||||
"description": "Material Deck allows you to control Foundry using an Elgato Stream Deck",
|
||||
"version": "1.4.9",
|
||||
"version": "1.4.12",
|
||||
"author": "CDeenen",
|
||||
"authors": {
|
||||
"name": "CDeenen",
|
||||
@@ -11,18 +12,15 @@
|
||||
"patreon": "MaterialFoundry",
|
||||
"reddit": "CDeenen123"
|
||||
},
|
||||
"flags": {
|
||||
"minimumSDversion": "1.4.7",
|
||||
"minimumMSversion": "1.0.2"
|
||||
},
|
||||
"minimumSDversion": "1.4.7",
|
||||
"minimumMSversion": "1.0.2",
|
||||
"esmodules": [
|
||||
"./MaterialDeck.js"
|
||||
],
|
||||
"esmodules": ["./MaterialDeck.js"],
|
||||
"styles": ["./css/style.css"],
|
||||
"socket": true,
|
||||
"minimumCoreVersion": "0.7.5",
|
||||
"compatibleCoreVersion": "9",
|
||||
"minimumCoreVersion": "9",
|
||||
"compatibleCoreVersion": "10",
|
||||
"compatibility": {
|
||||
"minimum": "9",
|
||||
"verified": "10"
|
||||
},
|
||||
"languages": [
|
||||
{
|
||||
"lang": "en",
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import * as MODULE from "../MaterialDeck.js";
|
||||
import {streamDeck, tokenControl} from "../MaterialDeck.js";
|
||||
import {compatibleCore} from "./misc.js";
|
||||
import { streamDeck, tokenControl, getPermission } from "../../MaterialDeck.js";
|
||||
|
||||
export class CombatTracker{
|
||||
constructor(){
|
||||
@@ -32,7 +30,7 @@ export class CombatTracker{
|
||||
settings.icon = settings.displayIcon ? 'tokenIcon' : 'none';
|
||||
|
||||
if (mode == 'combatants'){
|
||||
if (MODULE.getPermission('COMBAT','DISPLAY_COMBATANTS') == false) {
|
||||
if (getPermission('COMBAT','DISPLAY_COMBATANTS') == false) {
|
||||
streamDeck.noPermission(context,device,device,false,"combat tracker");
|
||||
return;
|
||||
}
|
||||
@@ -44,7 +42,7 @@ export class CombatTracker{
|
||||
const combatant = initiativeOrder[nr]
|
||||
|
||||
if (combatant != undefined){
|
||||
const tokenId = compatibleCore("0.8.1") ? combatant.data.tokenId : combatant.tokenId;
|
||||
const tokenId = combatant.data.tokenId;
|
||||
tokenControl.pushData(tokenId,settings,context,device,combatantState,'#cccc00');
|
||||
return;
|
||||
}
|
||||
@@ -59,12 +57,12 @@ export class CombatTracker{
|
||||
}
|
||||
}
|
||||
else if (mode == 'currentCombatant'){
|
||||
if (MODULE.getPermission('COMBAT','DISPLAY_COMBATANTS') == false) {
|
||||
if (getPermission('COMBAT','DISPLAY_COMBATANTS') == false) {
|
||||
streamDeck.noPermission(context,device,device);
|
||||
return;
|
||||
}
|
||||
if (combat != null && combat != undefined && combat.started){
|
||||
const tokenId = compatibleCore("0.8.1") ? combat.combatant.data.tokenId : combat.combatant.tokenId;
|
||||
const tokenId = combat.combatant.data.tokenId;
|
||||
tokenControl.pushData(tokenId,settings,context,device);
|
||||
}
|
||||
else {
|
||||
@@ -74,15 +72,15 @@ export class CombatTracker{
|
||||
}
|
||||
else if (mode == 'function'){
|
||||
|
||||
if (ctFunction == 'turnDisplay' && MODULE.getPermission('COMBAT','TURN_DISPLAY') == false) {
|
||||
if (ctFunction == 'turnDisplay' && getPermission('COMBAT','TURN_DISPLAY') == false) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
else if (ctFunction == 'endTurn' && MODULE.getPermission('COMBAT','END_TURN') == false) {
|
||||
else if (ctFunction == 'endTurn' && getPermission('COMBAT','END_TURN') == false) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
else if (ctFunction != 'turnDisplay' && ctFunction != 'endTurn' && MODULE.getPermission('COMBAT','OTHER_FUNCTIONS') == false) {
|
||||
else if (ctFunction != 'turnDisplay' && ctFunction != 'endTurn' && getPermission('COMBAT','OTHER_FUNCTIONS') == false) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -130,6 +128,8 @@ export class CombatTracker{
|
||||
if (settings.displayRound && settings.displayTurn) txt += "\n";
|
||||
if (settings.displayTurn) txt += "Turn\n"+turn;
|
||||
}
|
||||
else if (ctFunction == 'rollInitiative' || ctFunction == 'rollInitiativeNPC')
|
||||
src = "modules/MaterialDeck/img/token/init.png";
|
||||
|
||||
streamDeck.setIcon(context,device,src,{background:background});
|
||||
streamDeck.setTitle(txt,context);
|
||||
@@ -145,20 +145,19 @@ export class CombatTracker{
|
||||
if (combat == null || combat == undefined) return;
|
||||
const ctFunction = settings.combatTrackerFunction ? settings.combatTrackerFunction : 'startStop';
|
||||
|
||||
if (ctFunction == 'turnDisplay' && MODULE.getPermission('COMBAT','TURN_DISPLAY') == false) {
|
||||
if (ctFunction == 'turnDisplay' && getPermission('COMBAT','TURN_DISPLAY') == false) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
else if (ctFunction == 'endTurn' && MODULE.getPermission('COMBAT','END_TURN') == false) {
|
||||
else if (ctFunction == 'endTurn' && getPermission('COMBAT','END_TURN') == false) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
else if (ctFunction != 'turnDisplay' && ctFunction != 'endTurn' && MODULE.getPermission('COMBAT','OTHER_FUNCTIONS') == false) {
|
||||
else if (ctFunction != 'turnDisplay' && ctFunction != 'endTurn' && getPermission('COMBAT','OTHER_FUNCTIONS') == false) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctFunction == 'startStop'){
|
||||
else if (ctFunction == 'startStop'){
|
||||
let src;
|
||||
let background;
|
||||
if (game.combat.started){
|
||||
@@ -169,8 +168,10 @@ export class CombatTracker{
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (game.combat.started == false) return;
|
||||
else if (ctFunction == 'rollInitiative' && getPermission('COMBAT','OTHER_FUNCTIONS')) game.combat.rollAll();
|
||||
else if (ctFunction == 'rollInitiativeNPC' && getPermission('COMBAT','OTHER_FUNCTIONS')) game.combat.rollNPC();
|
||||
|
||||
if (game.combat.started == false) return;
|
||||
if (ctFunction == 'nextTurn') await game.combat.nextTurn();
|
||||
else if (ctFunction == 'prevTurn') await game.combat.previousTurn();
|
||||
else if (ctFunction == 'nextRound') await game.combat.nextRound();
|
||||
@@ -181,7 +182,6 @@ export class CombatTracker{
|
||||
const token = canvas.tokens.placeables.filter(token => token.id == game.combat.combatant.token.id)[0];
|
||||
if (token.can(game.userId,"control")) token.control();
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
const onClick = settings.onClick ? settings.onClick : 'doNothing';
|
||||
@@ -193,12 +193,12 @@ export class CombatTracker{
|
||||
if (nr == undefined || nr < 1) nr = 0;
|
||||
const combatant = initiativeOrder[nr]
|
||||
if (combatant == undefined) return;
|
||||
tokenId = compatibleCore("0.8.1") ? combatant.data.tokenId : combatant.tokenId;
|
||||
tokenId = combatant.data.tokenId;
|
||||
}
|
||||
}
|
||||
else if (mode == 'currentCombatant')
|
||||
if (combat != null && combat != undefined && combat.started)
|
||||
tokenId = compatibleCore("0.8.1") ? combat.combatant.data.tokenId : combat.combatant.tokenId;
|
||||
tokenId = combat.combatant.data.tokenId;
|
||||
|
||||
let token = (canvas.tokens.children[0] != undefined) ? canvas.tokens.children[0].children.find(p => p.id == tokenId) : undefined;
|
||||
if (token == undefined) return;
|
||||
@@ -226,6 +226,12 @@ export class CombatTracker{
|
||||
if (element == null) token.sheet.render(true);
|
||||
else token.sheet.close();
|
||||
}
|
||||
else if (onClick == 'rollInitiative') {
|
||||
token.actor.rollInitiative({rerollInitiative:true});
|
||||
}
|
||||
else if (onClick == 'target') {
|
||||
token.setTarget(!token.isTargeted,{releaseOthers:false})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import {streamDeck} from "../MaterialDeck.js";
|
||||
import { streamDeck } from "../../MaterialDeck.js";
|
||||
import { compatibleCore } from "../misc.js";
|
||||
|
||||
export class ExternalModules{
|
||||
soundscapeSettings = {
|
||||
@@ -113,14 +114,14 @@ export class ExternalModules{
|
||||
let name = '';
|
||||
if (type == 'weatherControls') {
|
||||
const effect = (settings.weatherEffect == undefined) ? 'leaves' : settings.weatherEffect;
|
||||
name = CONFIG.fxmaster.weather[effect].label;
|
||||
icon = CONFIG.fxmaster.weather[effect].icon;
|
||||
name = compatibleCore('10.0') ? game.i18n.localize(CONFIG.fxmaster.particleEffects[effect].label) : CONFIG.fxmaster.weather[effect].label;
|
||||
icon = compatibleCore('10.0') ? CONFIG.fxmaster.particleEffects[effect].icon : CONFIG.fxmaster.weather[effect].icon;
|
||||
ring = canvas.scene.getFlag("fxmaster", "effects")?.[`core_${effect}`] ? 2 : 1;
|
||||
ringColor = ring < 2 ? '#000000' : "#00ff00";
|
||||
}
|
||||
else if (type == 'filters') {
|
||||
const filter = (settings.fxMasterFilter == undefined) ? 'underwater' : settings.fxMasterFilter;
|
||||
name = CONFIG.fxmaster.filters[filter].label;
|
||||
name = compatibleCore('10.0') ? game.i18n.localize(CONFIG.fxmaster.filterEffects[filter].label) : CONFIG.fxmaster.filters[filter].label;
|
||||
background = "#340057";
|
||||
if (displayIcon){
|
||||
if (filter == 'lightning') icon = "fas fa-bolt";
|
||||
@@ -174,7 +175,7 @@ export class ExternalModules{
|
||||
applyColor: (settings.fxWeatherEnColor == undefined) ? false : settings.fxWeatherEnColor
|
||||
}
|
||||
|
||||
Hooks.call("fxmaster.switchWeather", {
|
||||
Hooks.call(compatibleCore('10.0') ? "fxmaster.switchParticleEffect" : "fxmaster.switchWeather", {
|
||||
name: `core_${effect}`,
|
||||
type: effect,
|
||||
options,
|
||||
@@ -1,6 +1,5 @@
|
||||
import * as MODULE from "../MaterialDeck.js";
|
||||
import {streamDeck} from "../MaterialDeck.js";
|
||||
import {compatibleCore} from "./misc.js";
|
||||
import { moduleName, streamDeck, getPermission, hotbarUses } from "../../MaterialDeck.js";
|
||||
import { compatibleCore } from "../misc.js";
|
||||
|
||||
export class MacroControl{
|
||||
constructor(){
|
||||
@@ -39,7 +38,7 @@ export class MacroControl{
|
||||
let uses = undefined;
|
||||
|
||||
if (mode == 'macroBoard') { //Macro board
|
||||
if ((MODULE.getPermission('MACRO','MACROBOARD') == false )) {
|
||||
if ((getPermission('MACRO','MACROBOARD') == false )) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -57,8 +56,8 @@ export class MacroControl{
|
||||
else { //Execute macro
|
||||
macroNumber += this.offset - 1;
|
||||
if (macroNumber < 0) macroNumber = 0;
|
||||
macroId = game.settings.get(MODULE.moduleName,'macroSettings').macros[macroNumber];
|
||||
background = game.settings.get(MODULE.moduleName,'macroSettings').color[macroNumber];
|
||||
macroId = game.settings.get(moduleName,'macroSettings').macros[macroNumber];
|
||||
background = game.settings.get(moduleName,'macroSettings').color[macroNumber];
|
||||
if (background == undefined) background = '#000000';
|
||||
ring = 0;
|
||||
}
|
||||
@@ -69,11 +68,11 @@ export class MacroControl{
|
||||
macroId = macro?.id;
|
||||
}
|
||||
else { //Macro Hotbar
|
||||
if ((MODULE.getPermission('MACRO','HOTBAR') == false )) {
|
||||
if ((getPermission('MACRO','HOTBAR') == false )) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
if (mode == 'hotbar') macroId = game.user.data.hotbar[macroNumber];
|
||||
if (mode == 'hotbar') macroId = compatibleCore('10.0') ? game.user.hotbar[macroNumber] : game.user.data.hotbar[macroNumber];
|
||||
else {
|
||||
let macros;
|
||||
if (mode == 'customHotbar' && game.modules.get('custom-hotbar') != undefined)
|
||||
@@ -91,7 +90,7 @@ export class MacroControl{
|
||||
if (macro != undefined) {
|
||||
if (displayName) name = macro.name;
|
||||
if (displayIcon) src = macro.img;
|
||||
if (MODULE.hotbarUses && displayUses) uses = await this.getUses(macro);
|
||||
if (hotbarUses && displayUses) uses = await this.getUses(macro);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -126,7 +125,7 @@ export class MacroControl{
|
||||
let macroNumber = data.settings.macroNumber;
|
||||
if(macroNumber == undefined || isNaN(parseInt(macroNumber))) macroNumber = 1;
|
||||
|
||||
if ((MODULE.getPermission('MACRO','HOTBAR') == false )) {
|
||||
if ((getPermission('MACRO','HOTBAR') == false )) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -150,7 +149,7 @@ export class MacroControl{
|
||||
if (macro != undefined && macro != null) {
|
||||
if (displayName) name += macro.name;
|
||||
if (displayIcon) src += macro.img;
|
||||
if (MODULE.hotbarUses && displayUses) uses = await this.getUses(macro);
|
||||
if (hotbarUses && displayUses) uses = await this.getUses(macro);
|
||||
}
|
||||
streamDeck.setIcon(context,device,src,{background:background,uses:uses});
|
||||
streamDeck.setTitle(name,context);
|
||||
@@ -165,11 +164,11 @@ export class MacroControl{
|
||||
let target = settings.target ? settings.target : undefined;
|
||||
|
||||
if (mode == 'hotbar' || mode == 'visibleHotbar' || mode == 'customHotbar'){
|
||||
if ((MODULE.getPermission('MACRO','HOTBAR') == false )) return;
|
||||
this.executeHotbar(macroNumber,mode);
|
||||
if ((getPermission('MACRO','HOTBAR') == false )) return;
|
||||
this.executeHotbar(macroNumber,mode,target);
|
||||
}
|
||||
else if (mode == 'name') {
|
||||
if ((MODULE.getPermission('MACRO','BY_NAME') == false )) return;
|
||||
if ((getPermission('MACRO','BY_NAME') == false )) return;
|
||||
const macroName = settings.macroNumber;
|
||||
const macro = game.macros.getName(macroName);
|
||||
|
||||
@@ -177,16 +176,13 @@ export class MacroControl{
|
||||
|
||||
const args = settings.macroArgs ? settings.macroArgs : "";
|
||||
|
||||
let furnaceEnabled = false;
|
||||
let furnace = game.modules.get("furnace");
|
||||
if (furnace != undefined && furnace.active && compatibleCore("0.8.1")==false) furnaceEnabled = true;
|
||||
|
||||
let advancedMacrosEnabled = false;
|
||||
let advancedMacros = game.modules.get("advanced-macros");
|
||||
if (advancedMacros != undefined && advancedMacros.active) furnaceEnabled = true;
|
||||
if (advancedMacros != undefined && advancedMacros.active) advancedMacrosEnabled = true;
|
||||
|
||||
if (args == "" || args == " ") furnaceEnabled = false;
|
||||
if (args == "" || args == " ") advancedMacrosEnabled = false;
|
||||
|
||||
if (furnaceEnabled == false) macro.execute({token:target});
|
||||
if (advancedMacrosEnabled == false) macro.execute({token:target});
|
||||
else {
|
||||
let chatData = {
|
||||
user: game.user._id,
|
||||
@@ -198,7 +194,7 @@ export class MacroControl{
|
||||
|
||||
}
|
||||
else {
|
||||
if ((MODULE.getPermission('MACRO','MACROBOARD') == false )) return;
|
||||
if ((getPermission('MACRO','MACROBOARD') == false )) return;
|
||||
if (settings.macroBoardMode == 'offset') {
|
||||
let macroOffset = settings.macroOffset;
|
||||
if (macroOffset == undefined) macroOffset = 0;
|
||||
@@ -210,9 +206,9 @@ export class MacroControl{
|
||||
}
|
||||
}
|
||||
|
||||
executeHotbar(macroNumber,mode){
|
||||
executeHotbar(macroNumber,mode,target){
|
||||
let macroId
|
||||
if (mode == 'hotbar') macroId = game.user.data.hotbar[macroNumber];
|
||||
if (mode == 'hotbar') macroId = compatibleCore('10.0') ? game.user.hotbar[macroNumber] : game.user.data.hotbar[macroNumber];
|
||||
else {
|
||||
let macros;
|
||||
if (mode == 'customHotbar' && game.modules.get('custom-hotbar') != undefined) {
|
||||
@@ -224,29 +220,26 @@ export class MacroControl{
|
||||
}
|
||||
if (macroId == undefined) return;
|
||||
let macro = game.macros.get(macroId);
|
||||
macro.execute();
|
||||
macro.execute({token:target});
|
||||
}
|
||||
|
||||
executeBoard(macroNumber){
|
||||
macroNumber = parseInt(macroNumber);
|
||||
macroNumber += this.offset - 1;
|
||||
if (macroNumber < 0) macroNumber = 0;
|
||||
var macroId = game.settings.get(MODULE.moduleName,'macroSettings').macros[macroNumber];
|
||||
var macroId = game.settings.get(moduleName,'macroSettings').macros[macroNumber];
|
||||
|
||||
if (macroId != undefined){
|
||||
let macro = game.macros.get(macroId);
|
||||
if (macro != undefined && macro != null) {
|
||||
const args = game.settings.get(MODULE.moduleName,'macroSettings').args;
|
||||
let furnaceEnabled = false;
|
||||
let furnace = game.modules.get("furnace");
|
||||
if (furnace != undefined && furnace.active && compatibleCore("0.8.1")==false) furnaceEnabled = true;
|
||||
|
||||
const args = game.settings.get(moduleName,'macroSettings').args;
|
||||
let advancedMacrosEnabled = false;
|
||||
let advancedMacros = game.modules.get("advanced-macros");
|
||||
if (advancedMacros != undefined && advancedMacros.active) furnaceEnabled = true;
|
||||
if (advancedMacros != undefined && advancedMacros.active) advancedMacrosEnabled = true;
|
||||
|
||||
if (args == undefined || args[macroNumber] == undefined || args[macroNumber] == "") furnaceEnabled = false;
|
||||
if (args == undefined || args[macroNumber] == undefined || args[macroNumber] == "") advancedMacrosEnabled = false;
|
||||
|
||||
if (furnaceEnabled == false) macro.execute();
|
||||
if (advancedMacrosEnabled == false) macro.execute();
|
||||
else {
|
||||
let chatData = {
|
||||
user: game.user._id,
|
||||
@@ -1,6 +1,5 @@
|
||||
import * as MODULE from "../MaterialDeck.js";
|
||||
import {streamDeck, gamingSystem} from "../MaterialDeck.js";
|
||||
import {compatibleCore} from "./misc.js";
|
||||
import { streamDeck, gamingSystem, getPermission } from "../../MaterialDeck.js";
|
||||
import { compatibleCore } from "../misc.js";
|
||||
|
||||
export class OtherControls{
|
||||
constructor(){
|
||||
@@ -94,7 +93,7 @@ export class OtherControls{
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
updatePause(settings,context,device,options={}){
|
||||
if (MODULE.getPermission('OTHER','PAUSE') == false ) {
|
||||
if (getPermission('OTHER','PAUSE') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -119,7 +118,7 @@ export class OtherControls{
|
||||
}
|
||||
|
||||
keyPressPause(settings){
|
||||
if (MODULE.getPermission('OTHER','PAUSE') == false ) return;
|
||||
if (getPermission('OTHER','PAUSE') == false ) return;
|
||||
|
||||
const pauseFunction = settings.pauseFunction ? settings.pauseFunction : 'pause';
|
||||
|
||||
@@ -186,7 +185,7 @@ export class OtherControls{
|
||||
}
|
||||
else {
|
||||
let viewPosition = canvas.scene._viewPosition;
|
||||
const gridSize = canvas.scene.data.grid;
|
||||
const gridSize = compatibleCore('10.0') ? canvas.scene.grid.size : canvas.scene.data.grid;
|
||||
viewPosition.duration = 100;
|
||||
|
||||
if (dir == 'up') viewPosition.y -= gridSize;
|
||||
@@ -220,7 +219,7 @@ export class OtherControls{
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
updateControl(settings,context,device,options={}){
|
||||
if (MODULE.getPermission('OTHER','CONTROL') == false ) {
|
||||
if (getPermission('OTHER','CONTROL') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -248,12 +247,12 @@ export class OtherControls{
|
||||
streamDeck.noPermission(context,device,false);
|
||||
return;
|
||||
}
|
||||
if (tool == 'open'){ //open category
|
||||
//if (tool == 'open'){ //open category
|
||||
txt = game.i18n.localize(selectedControl.title);
|
||||
src = selectedControl.icon;
|
||||
if (activeControl == selectedControl.name)
|
||||
ringColor = "#FF7B00";
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
else if (control == 'dispTools'){ //displayed tools
|
||||
@@ -330,7 +329,7 @@ export class OtherControls{
|
||||
}
|
||||
|
||||
keyPressControl(settings){
|
||||
if (MODULE.getPermission('OTHER','CONTROL') == false ) return;
|
||||
if (getPermission('OTHER','CONTROL') == false ) return;
|
||||
if (canvas.scene == null) return;
|
||||
const control = settings.control ? settings.control : 'dispControls';
|
||||
const tool = settings.tool ? settings.tool : 'open';
|
||||
@@ -346,9 +345,12 @@ export class OtherControls{
|
||||
streamDeck.noPermission(context,device,false);
|
||||
return;
|
||||
}
|
||||
if (compatibleCore('10.0')) {
|
||||
ui.controls.initialize({layer: selectedControl.layer});
|
||||
}
|
||||
else {
|
||||
ui.controls.activeControl = selectedControl.name;
|
||||
selectedControl.activeTool = selectedControl.activeTool;
|
||||
if (compatibleCore("0.8.2")) {
|
||||
for (let layer of canvas.layers) {
|
||||
if (layer.options == undefined) continue;
|
||||
if (layer.options.name == selectedControl.layer) {
|
||||
@@ -357,7 +359,6 @@ export class OtherControls{
|
||||
}
|
||||
}
|
||||
}
|
||||
else canvas.getLayer(selectedControl.layer).activate();
|
||||
}
|
||||
}
|
||||
else if (control == 'dispTools'){ //displayed tools
|
||||
@@ -383,10 +384,17 @@ export class OtherControls{
|
||||
else if (selectedTool.button){
|
||||
selectedTool.onClick();
|
||||
}
|
||||
else
|
||||
else {
|
||||
if (compatibleCore('10.0')) {
|
||||
ui.controls.initialize({layer: selectedControl.layer, tool: selectedTool.name});
|
||||
}
|
||||
else {
|
||||
selectedControl.activeTool = selectedTool.name;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (control == 'controlsOffset') {
|
||||
const offsetType = settings.controlsOffsetType ? settings.controlsOffsetType : 'absoluteOffset';
|
||||
@@ -406,9 +414,12 @@ export class OtherControls{
|
||||
return;
|
||||
}
|
||||
if (tool == 'open'){ //open category
|
||||
if (compatibleCore('10.0')) {
|
||||
ui.controls.initialize({layer: selectedControl.layer});
|
||||
}
|
||||
else {
|
||||
ui.controls.activeControl = control;
|
||||
selectedControl.activeTool = selectedControl.activeTool;
|
||||
if (compatibleCore("0.8.2")) {
|
||||
for (let layer of canvas.layers) {
|
||||
if (layer.options == undefined) continue;
|
||||
if (layer.options.name == selectedControl.layer) {
|
||||
@@ -417,7 +428,7 @@ export class OtherControls{
|
||||
}
|
||||
}
|
||||
}
|
||||
else canvas.getLayer(selectedControl.layer).activate();
|
||||
|
||||
}
|
||||
else {
|
||||
const selectedTool = selectedControl.tools.find(t => t.name == tool);
|
||||
@@ -426,8 +437,21 @@ export class OtherControls{
|
||||
streamDeck.noPermission(context,device,false);
|
||||
return;
|
||||
}
|
||||
if (compatibleCore('10.0')) {
|
||||
if (selectedTool.toggle) {
|
||||
ui.controls.initialize({layer: selectedControl.layer});
|
||||
selectedTool.active = !selectedTool.active;
|
||||
selectedTool.onClick(selectedTool.active);
|
||||
}
|
||||
else if (selectedTool.button){
|
||||
ui.controls.initialize({layer: selectedControl.layer});
|
||||
selectedTool.onClick();
|
||||
}
|
||||
else
|
||||
ui.controls.initialize({layer: selectedControl.layer, tool: selectedTool.name});
|
||||
}
|
||||
else {
|
||||
ui.controls.activeControl = control;
|
||||
if (compatibleCore("0.8.2")) {
|
||||
for (let layer of canvas.layers) {
|
||||
if (layer.options == undefined) continue;
|
||||
if (layer.options.name == selectedControl.layer) {
|
||||
@@ -435,8 +459,6 @@ export class OtherControls{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else canvas.getLayer(selectedControl.layer).activate();
|
||||
if (selectedTool.toggle) {
|
||||
selectedTool.active = !selectedTool.active;
|
||||
selectedTool.onClick(selectedTool.active);
|
||||
@@ -447,6 +469,8 @@ export class OtherControls{
|
||||
else
|
||||
selectedControl.activeTool = tool;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -456,7 +480,7 @@ export class OtherControls{
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
updateDarkness(settings,context,device,options={}){
|
||||
if (MODULE.getPermission('OTHER','DARKNESS') == false ) {
|
||||
if (getPermission('OTHER','DARKNESS') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -476,7 +500,7 @@ export class OtherControls{
|
||||
}
|
||||
else if (func == 'disp'){ //display darkness
|
||||
src = 'modules/MaterialDeck/img/other/darkness/darkness.png';
|
||||
const darkness = canvas.scene != null ? Math.floor(canvas.scene.data.darkness*100)/100 : '';
|
||||
const darkness = canvas.scene != null ? compatibleCore('10.0') ? Math.floor(canvas.scene.darkness*100)/100 : Math.floor(canvas.scene.data.darkness*100)/100 : '';
|
||||
txt += darkness;
|
||||
}
|
||||
streamDeck.setTitle(txt,context);
|
||||
@@ -485,39 +509,48 @@ export class OtherControls{
|
||||
|
||||
keyPressDarkness(settings) {
|
||||
if (canvas.scene == null) return;
|
||||
if (MODULE.getPermission('OTHER','DARKNESS') == false ) return;
|
||||
if (getPermission('OTHER','DARKNESS') == false ) return;
|
||||
const func = settings.darknessFunction ? settings.darknessFunction : 'value';
|
||||
const value = parseFloat(settings.darknessValue) ? parseFloat(settings.darknessValue) : 0;
|
||||
const animateDarkness = parseInt(settings.darknessAnimation) ? parseInt(settings.darknessAnimation) : 500;
|
||||
|
||||
if (func == 'value') //value
|
||||
canvas.scene.update({darkness: value});
|
||||
canvas.scene.update({darkness: value}, {animateDarkness});
|
||||
else if (func == 'incDec'){ //increase/decrease
|
||||
let darkness = canvas.scene.data.darkness - value;
|
||||
let darkness = compatibleCore('10.0') ? canvas.scene.darkness - value : canvas.scene.data.darkness - value;
|
||||
if (darkness > 1) darkness = 1;
|
||||
if (darkness < 0) darkness = 0;
|
||||
canvas.scene.update({darkness: darkness});
|
||||
canvas.scene.update({darkness: darkness}, {animateDarkness});
|
||||
}
|
||||
else if (func == 'transitionDay') {
|
||||
canvas.scene.update({darkness: 0}, {animateDarkness: 10000})
|
||||
}
|
||||
else if (func == 'transitionNight') {
|
||||
canvas.scene.update({darkness: 1}, {animateDarkness: 10000})
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
updateRollDice(settings,context,device,options={}){
|
||||
if (MODULE.getPermission('OTHER','DICE') == false ) {
|
||||
if (getPermission('OTHER','DICE') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
const background = settings.background ? settings.background : '#000000';
|
||||
let txt = '';
|
||||
const formula = settings.rollDiceFormula ? settings.rollDiceFormula : '1d20 + 7';
|
||||
|
||||
if (settings.displayDiceName) txt = 'Roll: ' + settings.rollDiceFormula;
|
||||
if (settings.displayDiceName) txt = 'Roll: ' + formula;
|
||||
|
||||
streamDeck.setTitle(txt,context);
|
||||
streamDeck.setIcon(context,device,'',{background:background});
|
||||
}
|
||||
|
||||
keyPressRollDice(settings,context,device){
|
||||
if (MODULE.getPermission('OTHER','DICE') == false ) return;
|
||||
if (settings.rollDiceFormula == undefined || settings.rollDiceFormula == '') return;
|
||||
if (getPermission('OTHER','DICE') == false ) return;
|
||||
const formula = settings.rollDiceFormula ? settings.rollDiceFormula : '1d20 + 7';
|
||||
if (formula == '') return;
|
||||
const rollFunction = settings.rollDiceFunction ? settings.rollDiceFunction : 'public';
|
||||
|
||||
let actor;
|
||||
@@ -527,8 +560,8 @@ export class OtherControls{
|
||||
if (actor != undefined) tokenControlled = true;
|
||||
|
||||
let r;
|
||||
if (tokenControlled) r = new Roll(settings.rollDiceFormula,actor.getRollData());
|
||||
else r = new Roll(settings.rollDiceFormula);
|
||||
if (tokenControlled) r = new Roll(formula,actor.getRollData());
|
||||
else r = new Roll(formula);
|
||||
|
||||
r.evaluate({async:false});
|
||||
|
||||
@@ -539,12 +572,12 @@ export class OtherControls{
|
||||
r.toMessage(r,{rollMode:"selfroll"})
|
||||
}
|
||||
else if (rollFunction == 'sd'){
|
||||
let txt = settings.displayDiceName ? 'Roll: '+settings.rollDiceFormula + '\nResult: ' : '';
|
||||
let txt = settings.displayDiceName ? 'Roll: '+formula + '\nResult: ' : '';
|
||||
txt += r.total;
|
||||
streamDeck.setTitle(txt,context);
|
||||
let data = this.rollData
|
||||
data[context] = {
|
||||
formula: settings.rollDiceFormula,
|
||||
formula: formula,
|
||||
result: txt
|
||||
}
|
||||
this.rollData = data;
|
||||
@@ -556,7 +589,7 @@ export class OtherControls{
|
||||
updateRollTable(settings,context,device,options={}){
|
||||
const name = settings.rollTableName;
|
||||
if (name == undefined) return;
|
||||
if (MODULE.getPermission('OTHER','TABLES') == false ) {
|
||||
if (getPermission('OTHER','TABLES') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -566,14 +599,14 @@ export class OtherControls{
|
||||
if (table == undefined) return;
|
||||
|
||||
let txt = settings.displayRollName ? table.name : '';
|
||||
let src = settings.displayRollIcon ? table.data.img : '';
|
||||
let src = settings.displayRollIcon ? (compatibleCore('10.0') ? table.img : table.data.img) : '';
|
||||
|
||||
if (table == undefined) {
|
||||
src = '';
|
||||
txt = '';
|
||||
}
|
||||
else {
|
||||
if (table.permission < 2 && MODULE.getPermission('OTHER','TABLES_ALL') == false ) {
|
||||
if (table.permission < 2 && getPermission('OTHER','TABLES_ALL') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -584,7 +617,7 @@ export class OtherControls{
|
||||
}
|
||||
|
||||
keyPressRollTable(settings){
|
||||
if (MODULE.getPermission('OTHER','TABLES') == false ) return;
|
||||
if (getPermission('OTHER','TABLES') == false ) return;
|
||||
const name = settings.rollTableName;
|
||||
if (name == undefined) return;
|
||||
|
||||
@@ -592,7 +625,7 @@ export class OtherControls{
|
||||
const table = game.tables.getName(name);
|
||||
|
||||
if (table != undefined) {
|
||||
if (table.permission < 2 && MODULE.getPermission('OTHER','TABLES_ALL') == false ) return;
|
||||
if (table.permission < 2 && getPermission('OTHER','TABLES_ALL') == false ) return;
|
||||
if (func == 'open'){ //open
|
||||
const element = document.getElementById(table.sheet.id);
|
||||
if (element == null) table.sheet.render(true);
|
||||
@@ -609,6 +642,21 @@ export class OtherControls{
|
||||
|
||||
getSidebarName(nr){
|
||||
let name;
|
||||
if (compatibleCore('10.0')) {
|
||||
if (nr == 'chat') name = game.i18n.localize("DOCUMENT.ChatMessages");
|
||||
else if (nr == 'combat') name = game.i18n.localize("DOCUMENT.Combats");
|
||||
else if (nr == 'scenes') name = game.i18n.localize("DOCUMENT.Scenes");
|
||||
else if (nr == 'actors') name = game.i18n.localize("DOCUMENT.Actors");
|
||||
else if (nr == 'items') name = game.i18n.localize("DOCUMENT.Items");
|
||||
else if (nr == 'journal') name = game.i18n.localize("DOCUMENT.JournalEntries");
|
||||
else if (nr == 'tables') name = game.i18n.localize("DOCUMENT.RollTables");
|
||||
else if (nr == 'cards') name = game.i18n.localize("DOCUMENT.Cards");
|
||||
else if (nr == 'playlists') name = game.i18n.localize("DOCUMENT.Playlists");
|
||||
else if (nr == 'compendium') name = game.i18n.localize("SIDEBAR.TabCompendium");
|
||||
else if (nr == 'settings') name = game.i18n.localize("SIDEBAR.TabSettings");
|
||||
else if (nr == 'collapse') name = game.i18n.localize("SIDEBAR.CollapseToggle");
|
||||
}
|
||||
else {
|
||||
if (nr == 'chat') name = game.i18n.localize("SIDEBAR.TabChat");
|
||||
else if (nr == 'combat') name = game.i18n.localize("SIDEBAR.TabCombat");
|
||||
else if (nr == 'scenes') name = game.i18n.localize("SIDEBAR.TabScenes");
|
||||
@@ -621,6 +669,7 @@ export class OtherControls{
|
||||
else if (nr == 'compendium') name = game.i18n.localize("SIDEBAR.TabCompendium");
|
||||
else if (nr == 'settings') name = game.i18n.localize("SIDEBAR.TabSettings");
|
||||
else if (nr == 'collapse') name = game.i18n.localize("SIDEBAR.CollapseToggle");
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -629,11 +678,11 @@ export class OtherControls{
|
||||
if (nr == 'chat') icon = window.CONFIG.ChatMessage.sidebarIcon;
|
||||
else if (nr == 'combat') icon = window.CONFIG.Combat.sidebarIcon;
|
||||
else if (nr == 'scenes') icon = window.CONFIG.Scene.sidebarIcon;
|
||||
else if (nr == 'actors') icon = "fas fa-users";
|
||||
else if (nr == 'actors') icon = window.CONFIG.Actor.sidebarIcon;
|
||||
else if (nr == 'items') icon = window.CONFIG.Item.sidebarIcon;
|
||||
else if (nr == 'journal') icon = window.CONFIG.JournalEntry.sidebarIcon;
|
||||
else if (nr == 'tables') icon = window.CONFIG.RollTable.sidebarIcon;
|
||||
else if (nr == 'cards') icon = "fas fa-id-badge";
|
||||
else if (nr == 'cards') icon = window.CONFIG.Cards.sidebarIcon;
|
||||
else if (nr == 'playlists') icon = window.CONFIG.Playlist.sidebarIcon;
|
||||
else if (nr == 'compendium') icon = "fas fa-atlas";
|
||||
else if (nr == 'settings') icon = "fas fa-cogs";
|
||||
@@ -642,7 +691,7 @@ export class OtherControls{
|
||||
}
|
||||
|
||||
updateSidebar(settings,context,device,options={}){
|
||||
if (MODULE.getPermission('OTHER','SIDEBAR') == false ) {
|
||||
if (getPermission('OTHER','SIDEBAR') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -666,7 +715,7 @@ export class OtherControls{
|
||||
}
|
||||
|
||||
keyPressSidebar(settings){
|
||||
if (MODULE.getPermission('OTHER','SIDEBAR') == false ) return;
|
||||
if (getPermission('OTHER','SIDEBAR') == false ) return;
|
||||
const sidebarTab = settings.sidebarTab ? settings.sidebarTab : 'chat';
|
||||
const popOut = settings.sidebarPopOut ? settings.sidebarPopOut : false;
|
||||
|
||||
@@ -718,17 +767,17 @@ export class OtherControls{
|
||||
updateCompendium(settings,context,device,options={}){
|
||||
const name = settings.compendiumName;
|
||||
if (name == undefined) return;
|
||||
if (MODULE.getPermission('OTHER','COMPENDIUM') == false ) {
|
||||
if (getPermission('OTHER','COMPENDIUM') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
const compendium = game.packs.find(p=>p.metadata.label == name);
|
||||
if (compendium == undefined) return;
|
||||
if (compendium.private && MODULE.getPermission('OTHER','COMPENDIUM_ALL') == false) {
|
||||
if (compendium.private && getPermission('OTHER','COMPENDIUM_ALL') == false) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
const rendered = compatibleCore("0.8.5") ? compendium.apps[0].rendered : compendium.rendered;
|
||||
const rendered = compendium.apps[0].rendered;
|
||||
const background = settings.background ? settings.background : '#000000';
|
||||
const ringOffColor = settings.offRing ? settings.offRing : '#000000';
|
||||
const ringOnColor = settings.onRing ? settings.onRing : '#00FF00';
|
||||
@@ -742,13 +791,13 @@ export class OtherControls{
|
||||
keyPressCompendium(settings){
|
||||
let name = settings.compendiumName;
|
||||
if (name == undefined) return;
|
||||
if (MODULE.getPermission('OTHER','COMPENDIUM') == false ) return;
|
||||
if (getPermission('OTHER','COMPENDIUM') == false ) return;
|
||||
|
||||
const compendium = game.packs.find(p=>p.metadata.label == name);
|
||||
const rendered = compatibleCore("0.8.5") ? compendium.apps[0].rendered : compendium.rendered;
|
||||
const rendered = compendium.apps[0].rendered;
|
||||
if (compendium == undefined) return;
|
||||
if (compendium.private && MODULE.getPermission('OTHER','COMPENDIUM_ALL') == false) return;
|
||||
else if (rendered) compatibleCore("0.8.5") ? compendium.apps[0].close() : compendium.close();
|
||||
if (compendium.private && getPermission('OTHER','COMPENDIUM_ALL') == false) return;
|
||||
else if (rendered) compendium.apps[0].close();
|
||||
else compendium.render(true);
|
||||
}
|
||||
|
||||
@@ -761,11 +810,11 @@ export class OtherControls{
|
||||
const journal = game.journal.getName(name);
|
||||
if (journal == undefined) return;
|
||||
|
||||
if (MODULE.getPermission('OTHER','JOURNAL') == false ) {
|
||||
if (getPermission('OTHER','JOURNAL') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
if (journal.permission < 2 && MODULE.getPermission('OTHER','JOURNAL_ALL') == false ) {
|
||||
if (journal.permission < 2 && getPermission('OTHER','JOURNAL_ALL') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -795,8 +844,8 @@ export class OtherControls{
|
||||
const journal = game.journal.getName(name);
|
||||
if (journal == undefined) return;
|
||||
|
||||
if (MODULE.getPermission('OTHER','JOURNAL') == false ) return;
|
||||
if (journal.permission < 2 && MODULE.getPermission('OTHER','JOURNAL_ALL') == false ) return;
|
||||
if (getPermission('OTHER','JOURNAL') == false ) return;
|
||||
if (journal.permission < 2 && getPermission('OTHER','JOURNAL_ALL') == false ) return;
|
||||
|
||||
if (journal.sheet.rendered == false) journal.sheet.render(true);
|
||||
else journal.sheet.close();
|
||||
@@ -805,7 +854,7 @@ export class OtherControls{
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
updateChatMessage(settings,context,device,options={}){
|
||||
if (MODULE.getPermission('OTHER','CHAT') == false ) {
|
||||
if (getPermission('OTHER','CHAT') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -815,7 +864,7 @@ export class OtherControls{
|
||||
}
|
||||
|
||||
keyPressChatMessage(settings){
|
||||
if (MODULE.getPermission('OTHER','CHAT') == false ) return;
|
||||
if (getPermission('OTHER','CHAT') == false ) return;
|
||||
const message = settings.chatMessage ? settings.chatMessage : '';
|
||||
|
||||
let chatData = {
|
||||
@@ -1,6 +1,4 @@
|
||||
import * as MODULE from "../MaterialDeck.js";
|
||||
import {streamDeck} from "../MaterialDeck.js";
|
||||
import {compatibleCore} from "./misc.js";
|
||||
import { moduleName, streamDeck, getPermission } from "../../MaterialDeck.js";
|
||||
|
||||
export class PlaylistControl{
|
||||
constructor(){
|
||||
@@ -22,7 +20,7 @@ export class PlaylistControl{
|
||||
}
|
||||
|
||||
update(settings,context,device){
|
||||
if (MODULE.getPermission('PLAYLIST','PLAY') == false ) {
|
||||
if (getPermission('PLAYLIST','PLAY') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -84,7 +82,7 @@ export class PlaylistControl{
|
||||
let playlistOffset = parseInt(settings.offset);
|
||||
if (isNaN(playlistOffset)) playlistOffset = 0;
|
||||
let number = parseInt(this.playlistOffset + playlistOffset);
|
||||
const nrOfPlaylists = parseInt(game.settings.get(MODULE.moduleName,'playlists').playlistNumber);
|
||||
const nrOfPlaylists = parseInt(game.settings.get(moduleName,'playlists').playlistNumber);
|
||||
if (number < 0) number += nrOfPlaylists;
|
||||
else if (number >= nrOfPlaylists) number -= nrOfPlaylists;
|
||||
const targetPlaylist = this.getPlaylist(number);
|
||||
@@ -116,7 +114,7 @@ export class PlaylistControl{
|
||||
|
||||
let playlist = this.getPlaylist(playlistNr);
|
||||
if (playlist != undefined){
|
||||
const track = compatibleCore("0.8.1") ? playlist.sounds.contents[trackNr] : playlist.sounds[trackNr];
|
||||
const track = playlist.sounds.contents[trackNr];
|
||||
if (track != undefined){
|
||||
if (track.playing)
|
||||
ringColor = ringOnColor;
|
||||
@@ -157,7 +155,7 @@ export class PlaylistControl{
|
||||
}
|
||||
else {
|
||||
let playing = game.playlists.playing;
|
||||
let settings = game.settings.get(MODULE.moduleName,'playlists');
|
||||
let settings = game.settings.get(moduleName,'playlists');
|
||||
let selectedPlaylists = settings.selectedPlaylist;
|
||||
for (let i=0; i<playing.length; i++){
|
||||
const playlistNr = selectedPlaylists.findIndex(p => p == playing[i]._id);
|
||||
@@ -189,14 +187,14 @@ export class PlaylistControl{
|
||||
}
|
||||
|
||||
getPlaylist(num){
|
||||
let selectedPlaylists = game.settings.get(MODULE.moduleName,'playlists').selectedPlaylist;
|
||||
let selectedPlaylists = game.settings.get(moduleName,'playlists').selectedPlaylist;
|
||||
if (selectedPlaylists != undefined)
|
||||
return game.playlists.get(selectedPlaylists[num]);
|
||||
else return undefined;
|
||||
}
|
||||
|
||||
keyPress(settings,context,device){
|
||||
if (MODULE.getPermission('PLAYLIST','PLAY') == false ) return;
|
||||
if (getPermission('PLAYLIST','PLAY') == false ) return;
|
||||
let playlistNr = settings.playlistNr;
|
||||
if (playlistNr == undefined || playlistNr < 1) playlistNr = 1;
|
||||
playlistNr--;
|
||||
@@ -222,7 +220,7 @@ export class PlaylistControl{
|
||||
if (playlistMode == 'playlist')
|
||||
this.playPlaylist(playlist,playlistNr);
|
||||
else {
|
||||
const track = compatibleCore("0.8.1") ? playlist.sounds.contents[trackNr] : playlist.sounds[trackNr];
|
||||
const track = playlist.sounds.contents[trackNr];
|
||||
if (track != undefined){
|
||||
this.playTrack(track,playlist,playlistNr);
|
||||
}
|
||||
@@ -251,7 +249,7 @@ export class PlaylistControl{
|
||||
let playlistOffset = parseInt(settings.offset);
|
||||
if (isNaN(playlistOffset)) playlistOffset = 0;
|
||||
let number = parseInt(this.playlistOffset + playlistOffset);
|
||||
const nrOfPlaylists = parseInt(game.settings.get(MODULE.moduleName,'playlists').playlistNumber);
|
||||
const nrOfPlaylists = parseInt(game.settings.get(moduleName,'playlists').playlistNumber);
|
||||
if (number < 0) number += nrOfPlaylists;
|
||||
else if (number >= nrOfPlaylists) number -= nrOfPlaylists;
|
||||
this.playlistOffset = number;
|
||||
@@ -281,12 +279,15 @@ export class PlaylistControl{
|
||||
playlist.stopAll();
|
||||
return;
|
||||
}
|
||||
let mode = game.settings.get(MODULE.moduleName,'playlists').playlistMode[playlistNr];
|
||||
let mode = game.settings.get(moduleName,'playlists').playlistMode[playlistNr];
|
||||
const originalPlayMode = playlist.mode;
|
||||
await playlist.update({mode: CONST.PLAYLIST_MODES.SEQUENTIAL});
|
||||
if (mode == 0) {
|
||||
mode = game.settings.get(MODULE.moduleName,'playlists').playMode;
|
||||
if (mode == 2) await this.stopAll();
|
||||
mode = game.settings.get(moduleName,'playlists').playMode;
|
||||
if (mode == 2) await this.stopAll(true);
|
||||
}
|
||||
playlist.playAll();
|
||||
await playlist.update({mode: originalPlayMode});
|
||||
}
|
||||
|
||||
async playTrack(track,playlist,playlistNr){
|
||||
@@ -301,23 +302,25 @@ export class PlaylistControl{
|
||||
return;
|
||||
}
|
||||
let play;
|
||||
const originalPlayMode = playlist.mode;
|
||||
if (track.playing)
|
||||
play = false;
|
||||
else {
|
||||
play = true;
|
||||
let mode = game.settings.get(MODULE.moduleName,'playlists').playlistMode[playlistNr];
|
||||
let mode = game.settings.get(moduleName,'playlists').playlistMode[playlistNr];
|
||||
if (mode == 0) {
|
||||
mode = game.settings.get(MODULE.moduleName,'playlists').playMode;
|
||||
if (mode == 1) await playlist.stopAll();
|
||||
else if (mode == 2) await this.stopAll();
|
||||
mode = game.settings.get(moduleName,'playlists').playMode;
|
||||
if (mode == 0) await playlist.update({mode: CONST.PLAYLIST_MODES.SIMULTANEOUS});
|
||||
else if (mode == 1) await playlist.stopAll();
|
||||
else if (mode == 2) await this.stopAll(true);
|
||||
}
|
||||
else if (mode == 2) await playlist.stopAll();
|
||||
else if (mode == 2) await playlist.stopAll(true);
|
||||
}
|
||||
|
||||
if (compatibleCore("0.8.1") && play) await playlist.playSound(track);
|
||||
else if (compatibleCore("0.8.1")) await playlist.stopSound(track);
|
||||
else await playlist.updateEmbeddedEntity("PlaylistSound", {_id: track._id, playing: play});
|
||||
if (play) await playlist.playSound(track);
|
||||
else await playlist.stopSound(track);
|
||||
|
||||
playlist.update({playing: play});
|
||||
await playlist.update({mode: originalPlayMode});
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import * as MODULE from "../MaterialDeck.js";
|
||||
import {streamDeck} from "../MaterialDeck.js";
|
||||
import {compatibleCore} from "./misc.js";
|
||||
import { streamDeck, getPermission } from "../../MaterialDeck.js";
|
||||
import { compatibleCore } from "../misc.js";
|
||||
|
||||
export class SceneControl{
|
||||
constructor(){
|
||||
@@ -34,7 +33,7 @@ export class SceneControl{
|
||||
let src = "";
|
||||
let name = "";
|
||||
if (func == 'visible') { //visible scenes
|
||||
if (MODULE.getPermission('SCENE','VISIBLE') == false ) {
|
||||
if (getPermission('SCENE','VISIBLE') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -47,12 +46,12 @@ export class SceneControl{
|
||||
if (scene != undefined){
|
||||
ringColor = scene.isView ? ringOnColor : ringOffColor;
|
||||
if (settings.displaySceneName) name = scene.name;
|
||||
if (settings.displaySceneIcon) src = scene.img;
|
||||
if (settings.displaySceneIcon) src = compatibleCore('10.0') ? scene.background.src : scene.img;
|
||||
if (scene.active) name += "\n(Active)";
|
||||
}
|
||||
}
|
||||
else if (func == 'dir') { //from directory
|
||||
if (MODULE.getPermission('SCENE','DIRECTORY') == false ) {
|
||||
if (getPermission('SCENE','DIRECTORY') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -61,33 +60,39 @@ export class SceneControl{
|
||||
nr--;
|
||||
|
||||
let sceneList = [];
|
||||
if (compatibleCore('10.0')) {
|
||||
sceneList = ui.scenes.documents;
|
||||
}
|
||||
else {
|
||||
for (let i=0; i<ui.scenes.tree.children.length; i++){
|
||||
const scenesInFolder = compatibleCore("0.8.1") ? ui.scenes.tree.children[i].contents : ui.scenes.tree.children[i].entities;
|
||||
const scenesInFolder = ui.scenes.tree.children[i].contents;
|
||||
for (let j=0; j<scenesInFolder.length; j++)
|
||||
sceneList.push(scenesInFolder[j])
|
||||
}
|
||||
for (let i=0; i<ui.scenes.tree.content.length; i++)
|
||||
sceneList.push(ui.scenes.tree.content[i])
|
||||
}
|
||||
|
||||
|
||||
const scene = sceneList[nr+this.sceneOffset];
|
||||
|
||||
if (scene != undefined){
|
||||
if (scene.isView)
|
||||
ringColor = ringOnColor;
|
||||
else if (scene.data.navigation && scene.data.permission.default == 0)
|
||||
else if ((compatibleCore('10.0') && scene.navigation && scene.permission.default == 0) || (!compatibleCore('10.0') && scene.data.navigation && scene.data.permission.default == 0))
|
||||
ringColor = '#000791';
|
||||
else if (scene.data.navigation)
|
||||
else if ((compatibleCore('10.0') && scene.navigation) || (!compatibleCore('10.0') && scene.data.navigation))
|
||||
ringColor = '#2d2d2d';
|
||||
else
|
||||
ringColor = ringOffColor;
|
||||
|
||||
if (settings.displaySceneName) name = scene.name;
|
||||
if (settings.displaySceneIcon) src = scene.img;
|
||||
if (settings.displaySceneIcon) src = compatibleCore('10.0') ? scene.background.src : scene.img;
|
||||
if (scene.active) name += "\n(Active)";
|
||||
}
|
||||
}
|
||||
else if (func == 'any') { //by name
|
||||
if (MODULE.getPermission('SCENE','NAME') == false ) {
|
||||
if (getPermission('SCENE','NAME') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -97,19 +102,19 @@ export class SceneControl{
|
||||
if (scene != undefined){
|
||||
ringColor = scene.isView ? ringOnColor : ringOffColor;
|
||||
if (settings.displaySceneName) name = scene.name;
|
||||
if (settings.displaySceneIcon) src = scene.img;
|
||||
if (settings.displaySceneIcon) src = compatibleCore('10.0') ? scene.background.src : scene.img;
|
||||
if (scene.active) name += "\n(Active)";
|
||||
}
|
||||
}
|
||||
else if (func == 'active'){
|
||||
if (MODULE.getPermission('SCENE','ACTIVE') == false ) {
|
||||
if (getPermission('SCENE','ACTIVE') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
const scene = game.scenes.active;
|
||||
if (scene == undefined) return;
|
||||
if (settings.displaySceneName) name = scene.name;
|
||||
if (settings.displaySceneIcon) src = scene.img;
|
||||
if (settings.displaySceneIcon) src = compatibleCore('10.0') ? scene.background.src : scene.img;
|
||||
ring = 0;
|
||||
}
|
||||
else if (func == 'offset'){
|
||||
@@ -126,7 +131,7 @@ export class SceneControl{
|
||||
const func = settings.sceneFunction ? settings.sceneFunction : 'visible';
|
||||
|
||||
if (func == 'visible'){ //visible scenes
|
||||
if (MODULE.getPermission('SCENE','VISIBLE') == false ) return;
|
||||
if (getPermission('SCENE','VISIBLE') == false ) return;
|
||||
const viewFunc = settings.sceneViewFunction ? settings.sceneViewFunction : 'view';
|
||||
let nr = parseInt(settings.sceneNr);
|
||||
if (isNaN(nr) || nr < 1) nr = 1;
|
||||
@@ -147,20 +152,25 @@ export class SceneControl{
|
||||
}
|
||||
}
|
||||
else if (func == 'dir') { //from directory
|
||||
if (MODULE.getPermission('SCENE','DIRECTORY') == false ) return;
|
||||
if (getPermission('SCENE','DIRECTORY') == false ) return;
|
||||
const viewFunc = settings.sceneViewFunction ? settings.sceneViewFunction : 'view';
|
||||
let nr = parseInt(settings.sceneNr);
|
||||
if (isNaN(nr) || nr < 1) nr = 1;
|
||||
nr--;
|
||||
|
||||
let sceneList = [];
|
||||
if (compatibleCore('10.0')) {
|
||||
sceneList = ui.scenes.documents;
|
||||
}
|
||||
else {
|
||||
for (let i=0; i<ui.scenes.tree.children.length; i++){
|
||||
const scenesInFolder = compatibleCore("0.8.1") ? ui.scenes.tree.children[i].contents : ui.scenes.tree.children[i].entities;
|
||||
const scenesInFolder = ui.scenes.tree.children[i].contents;
|
||||
for (let j=0; j<scenesInFolder.length; j++)
|
||||
sceneList.push(scenesInFolder[j])
|
||||
}
|
||||
for (let i=0; i<ui.scenes.tree.content.length; i++)
|
||||
sceneList.push(ui.scenes.tree.content[i])
|
||||
}
|
||||
|
||||
const scene = sceneList[nr+this.sceneOffset];
|
||||
|
||||
@@ -179,7 +189,7 @@ export class SceneControl{
|
||||
|
||||
}
|
||||
else if (func == 'any'){ //by name
|
||||
if (MODULE.getPermission('SCENE','NAME') == false ) return;
|
||||
if (getPermission('SCENE','NAME') == false ) return;
|
||||
if (settings.sceneName == undefined || settings.sceneName == '') return;
|
||||
const scenes = game.scenes.entries;
|
||||
let scene = game.scenes.getName(settings.sceneName);
|
||||
@@ -199,7 +209,7 @@ export class SceneControl{
|
||||
}
|
||||
}
|
||||
else if (func == 'active'){
|
||||
if (MODULE.getPermission('SCENE','ACTIVE') == false ) return;
|
||||
if (getPermission('SCENE','ACTIVE') == false ) return;
|
||||
const scene = game.scenes.active;
|
||||
if (scene == undefined) return;
|
||||
scene.view();
|
||||
@@ -1,6 +1,4 @@
|
||||
import * as MODULE from "../MaterialDeck.js";
|
||||
import {streamDeck} from "../MaterialDeck.js";
|
||||
import {compatibleCore} from "./misc.js";
|
||||
import { moduleName, streamDeck, getPermission } from "../../MaterialDeck.js";
|
||||
|
||||
export class SoundboardControl{
|
||||
constructor(){
|
||||
@@ -22,7 +20,7 @@ export class SoundboardControl{
|
||||
}
|
||||
|
||||
update(settings,context,device){
|
||||
if (MODULE.getPermission('SOUNDBOARD','PLAY') == false ) {
|
||||
if (getPermission('SOUNDBOARD','PLAY') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -40,7 +38,7 @@ export class SoundboardControl{
|
||||
soundNr--;
|
||||
soundNr += this.offset;
|
||||
|
||||
let soundboardSettings = game.settings.get(MODULE.moduleName, 'soundboardSettings');
|
||||
let soundboardSettings = game.settings.get(moduleName, 'soundboardSettings');
|
||||
ringColor = (this.activeSounds[soundNr]==undefined) ? soundboardSettings.colorOff[soundNr] : soundboardSettings.colorOn[soundNr];
|
||||
|
||||
if (settings.displayName && soundboardSettings.name != undefined) txt = soundboardSettings.name[soundNr];
|
||||
@@ -76,7 +74,7 @@ export class SoundboardControl{
|
||||
}
|
||||
|
||||
keyPressDown(settings){
|
||||
if (MODULE.getPermission('SOUNDBOARD','PLAY') == false ) return;
|
||||
if (getPermission('SOUNDBOARD','PLAY') == false ) return;
|
||||
const mode = settings.soundboardMode ? settings.soundboardMode : 'playSound';
|
||||
|
||||
if (mode == 'playSound') { //Play sound
|
||||
@@ -85,7 +83,7 @@ export class SoundboardControl{
|
||||
soundNr--;
|
||||
soundNr += this.offset;
|
||||
|
||||
const playMode = game.settings.get(MODULE.moduleName,'soundboardSettings').mode[soundNr];
|
||||
const playMode = game.settings.get(moduleName,'soundboardSettings').mode[soundNr];
|
||||
const repeat = (playMode > 0) ? true : false;
|
||||
const play = (this.activeSounds[soundNr] == undefined) ? true : false;
|
||||
|
||||
@@ -107,7 +105,7 @@ export class SoundboardControl{
|
||||
}
|
||||
|
||||
keyPressUp(settings){
|
||||
if (MODULE.getPermission('SOUNDBOARD','PLAY') == false ) return;
|
||||
if (getPermission('SOUNDBOARD','PLAY') == false ) return;
|
||||
const mode = settings.soundboardMode ? settings.soundboardMode : 'playSound';
|
||||
|
||||
if (mode != 'playSound') return;
|
||||
@@ -117,14 +115,14 @@ export class SoundboardControl{
|
||||
soundNr--;
|
||||
soundNr += this.offset;
|
||||
|
||||
const playMode = game.settings.get(MODULE.moduleName,'soundboardSettings').mode[soundNr];
|
||||
const playMode = game.settings.get(moduleName,'soundboardSettings').mode[soundNr];
|
||||
|
||||
if (playMode == 2)
|
||||
this.prePlaySound(soundNr,false,false);
|
||||
}
|
||||
|
||||
async prePlaySound(soundNr,repeat,play){
|
||||
const soundBoardSettings = game.settings.get(MODULE.moduleName,'soundboardSettings');
|
||||
const soundBoardSettings = game.settings.get(moduleName,'soundboardSettings');
|
||||
const playlistId = (soundBoardSettings.selectedPlaylists != undefined) ? soundBoardSettings.selectedPlaylists[soundNr] : undefined;
|
||||
let src;
|
||||
if (playlistId == "" || playlistId == undefined) return;
|
||||
@@ -144,12 +142,12 @@ export class SoundboardControl{
|
||||
const soundId = soundBoardSettings.sounds[soundNr];
|
||||
const sounds = game.playlists.get(playlistId).sounds;
|
||||
if (sounds == undefined) return;
|
||||
const sound = compatibleCore("0.8.1") ? sounds.find(p => p.id == soundId) : sounds.find(p => p._id == soundId);
|
||||
const sound = sounds.find(p => p.id == soundId);
|
||||
if (sound == undefined) return;
|
||||
src = sound.path;
|
||||
}
|
||||
|
||||
let volume = game.settings.get(MODULE.moduleName,'soundboardSettings').volume[soundNr]/100;
|
||||
let volume = game.settings.get(moduleName,'soundboardSettings').volume[soundNr]/100;
|
||||
volume = AudioHelper.inputToVolume(volume);
|
||||
|
||||
let payload = {
|
||||
@@ -169,7 +167,6 @@ export class SoundboardControl{
|
||||
if (play){
|
||||
volume *= game.settings.get("core", "globalAmbientVolume");
|
||||
|
||||
if (compatibleCore("0.8.1")) {
|
||||
let newSound = new Sound(src);
|
||||
if(newSound.loaded == false) await newSound.load({autoplay:true});
|
||||
newSound.on('end', ()=>{
|
||||
@@ -181,21 +178,6 @@ export class SoundboardControl{
|
||||
newSound.play({loop:repeat,volume:volume});
|
||||
this.activeSounds[soundNr] = newSound;
|
||||
}
|
||||
else {
|
||||
let howl = new Howl({src, volume, loop: repeat, onend: (id)=>{
|
||||
if (repeat == false){
|
||||
this.activeSounds[soundNr] = undefined;
|
||||
this.updateAll();
|
||||
}
|
||||
},
|
||||
onstop: ()=>{
|
||||
this.activeSounds[soundNr] = undefined;
|
||||
this.updateAll();
|
||||
}});
|
||||
howl.play();
|
||||
this.activeSounds[soundNr] = howl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.activeSounds[soundNr] != undefined) this.activeSounds[soundNr].stop();
|
||||
this.activeSounds[soundNr] = undefined;
|
||||
@@ -1,11 +1,11 @@
|
||||
import * as MODULE from "../MaterialDeck.js";
|
||||
import {streamDeck, macroControl, otherControls, tokenHelper} from "../MaterialDeck.js";
|
||||
import { compatibleCore } from "./misc.js";
|
||||
import { streamDeck, macroControl, otherControls, tokenHelper, getPermission } from "../../MaterialDeck.js";
|
||||
import { compatibleCore } from "../misc.js";
|
||||
|
||||
export class TokenControl{
|
||||
constructor(){
|
||||
this.active = false;
|
||||
this.wildcardOffset = 0;
|
||||
this.itemOffset = 0;
|
||||
}
|
||||
|
||||
async update(tokenId=null){
|
||||
@@ -43,11 +43,11 @@ export class TokenControl{
|
||||
let uses = undefined;
|
||||
let hp = undefined;
|
||||
if (validToken) {
|
||||
if (token.owner == false && token.observer == true && MODULE.getPermission('TOKEN','OBSERVER') == false ) {
|
||||
if (token.owner == false && token.observer == true && getPermission('TOKEN','OBSERVER') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
if (token.owner == false && token.observer == false && MODULE.getPermission('TOKEN','NON_OWNED') == false ) {
|
||||
if (token.owner == false && token.observer == false && getPermission('TOKEN','NON_OWNED') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -58,16 +58,16 @@ export class TokenControl{
|
||||
|
||||
const permission = token.actor?.permission;
|
||||
if (settings.combat){
|
||||
if (permission == 0 && MODULE.getPermission('COMBAT','DISPLAY_ALL_NAMES') == false) txt = "";
|
||||
else if (permission == 1 && MODULE.getPermission('COMBAT','DISPLAY_LIMITED_NAME') == false) txt = "";
|
||||
else if (permission == 2 && MODULE.getPermission('COMBAT','DISPLAY_OBSERVER_NAME') == false) txt = "";
|
||||
if (permission == 0 && getPermission('COMBAT','DISPLAY_ALL_NAMES') == false) txt = "";
|
||||
else if (permission == 1 && getPermission('COMBAT','DISPLAY_LIMITED_NAME') == false) txt = "";
|
||||
else if (permission == 2 && getPermission('COMBAT','DISPLAY_OBSERVER_NAME') == false) txt = "";
|
||||
|
||||
if (permission == 0 && stats == 'HP') stats = 'none';
|
||||
else if (stats == 'HP' && permission == 1 && MODULE.getPermission('COMBAT','DISPLAY_LIMITED_HP') == false) stats = 'none';
|
||||
else if (stats == 'HP' && permission == 2 && MODULE.getPermission('COMBAT','DISPLAY_OBSERVER_HP') == false) stats = 'none';
|
||||
else if (stats != 'HP' && permission < 3 && MODULE.getPermission('COMBAT','DISPLAY_NON_OWNED_STATS') == false) stats = 'none';
|
||||
else if (stats == 'HP' && permission == 1 && getPermission('COMBAT','DISPLAY_LIMITED_HP') == false) stats = 'none';
|
||||
else if (stats == 'HP' && permission == 2 && getPermission('COMBAT','DISPLAY_OBSERVER_HP') == false) stats = 'none';
|
||||
else if (stats != 'HP' && permission < 3 && getPermission('COMBAT','DISPLAY_NON_OWNED_STATS') == false) stats = 'none';
|
||||
}
|
||||
else if (MODULE.getPermission('TOKEN','STATS') == false) {
|
||||
else if (getPermission('TOKEN','STATS') == false) {
|
||||
statsOld = stats;
|
||||
stats = 'none';
|
||||
}
|
||||
@@ -231,12 +231,12 @@ export class TokenControl{
|
||||
}
|
||||
|
||||
if (settings.onClick == 'visibility') { //toggle visibility
|
||||
if (MODULE.getPermission('TOKEN','VISIBILITY') == false ) {
|
||||
if (getPermission('TOKEN','VISIBILITY') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
ring = 1;
|
||||
if (token.data.hidden){
|
||||
if (compatibleCore('10.0') ? token.document.hidden : token.data.hidden){
|
||||
ring = 2;
|
||||
ringColor = "#FF7B00";
|
||||
}
|
||||
@@ -246,7 +246,7 @@ export class TokenControl{
|
||||
}
|
||||
}
|
||||
else if (settings.onClick == 'combatState') { //toggle combat state
|
||||
if (MODULE.getPermission('TOKEN','COMBAT') == false ) {
|
||||
if (getPermission('TOKEN','COMBAT') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -271,7 +271,7 @@ export class TokenControl{
|
||||
}
|
||||
}
|
||||
else if (settings.onClick == 'condition') { //handle condition
|
||||
if (MODULE.getPermission('TOKEN','CONDITIONS') == false ) {
|
||||
if (getPermission('TOKEN','CONDITIONS') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -286,7 +286,7 @@ export class TokenControl{
|
||||
}
|
||||
}
|
||||
else if (settings.onClick == 'cubCondition') { //Combat Utility Belt conditions
|
||||
if (MODULE.getPermission('TOKEN','CONDITIONS') == false ) {
|
||||
if (getPermission('TOKEN','CONDITIONS') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -303,7 +303,7 @@ export class TokenControl{
|
||||
}
|
||||
}
|
||||
else if (settings.onClick == 'wildcard') { //wildcard images
|
||||
if (MODULE.getPermission('TOKEN','WILDCARD') == false ) {
|
||||
if (getPermission('TOKEN','WILDCARD') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -316,7 +316,7 @@ export class TokenControl{
|
||||
let currentImgNr = 0
|
||||
let imgNr;
|
||||
for (let i=0; i<images.length; i++)
|
||||
if (images[i] == token.data.img){
|
||||
if (images[i] == tokenHelper.getTokenIcon(token)){
|
||||
currentImgNr = i;
|
||||
break;
|
||||
}
|
||||
@@ -342,32 +342,61 @@ export class TokenControl{
|
||||
else if (settings.onClick == 'initiative') //Initiative
|
||||
iconSrc = "modules/MaterialDeck/img/token/init.png";
|
||||
}
|
||||
else if (mode == 'offset') {
|
||||
iconSrc = "modules/MaterialDeck/img/black.png";
|
||||
const itemOffset = settings.itemOffset ? settings.itemOffset : 0;
|
||||
ringColor = settings.offRing ? settings.offRing : '#000000';
|
||||
const ringOnColor = settings.onRing ? settings.onRing : '#00FF00';
|
||||
ring = 1;
|
||||
if (itemOffset == this.itemOffset) {
|
||||
|
||||
ring = 2;
|
||||
ringColor = ringOnColor;
|
||||
}
|
||||
}
|
||||
else if (mode == 'offsetRel') {
|
||||
|
||||
}
|
||||
else if (mode == 'dispOffset') {
|
||||
iconSrc = "modules/MaterialDeck/img/black.png";
|
||||
const prependTitle = settings.offsetPrepend ? settings.offsetPrepend : '';
|
||||
txt += prependTitle + this.itemOffset;
|
||||
}
|
||||
//Items
|
||||
else {
|
||||
txt += prependTitle;
|
||||
const allItems = token.actor.items;
|
||||
const itemNr = settings.itemNr ? settings.itemNr - 1 : 0;
|
||||
let itemNr = settings.itemNr ? settings.itemNr - 1 : 0;
|
||||
itemNr += this.itemOffset;
|
||||
const displayUses = settings.displayUses ? settings.displayUses : false;
|
||||
const displayName = settings.displayInventoryName ? settings.displayInventoryName : false;
|
||||
const displayIcon = settings.displayInventoryIcon ? settings.displayInventoryIcon : false;
|
||||
const selectionMode = settings.inventorySelection ? settings.inventorySelection : 'order';
|
||||
let items = allItems;
|
||||
let item;
|
||||
if (mode == 'inventory') {
|
||||
items = tokenHelper.getItems(token,settings.inventoryType);
|
||||
items = this.sortItems(items);
|
||||
item = items[itemNr];
|
||||
if (selectionMode == 'order') item = items[itemNr];
|
||||
else if (selectionMode == 'name') item = items.filter(i => i.name == settings.itemName)[0];
|
||||
else if (selectionMode == 'id') item = items.filter(i => i.id == settings.itemName)[0];
|
||||
|
||||
if (item != undefined && displayUses) uses = tokenHelper.getItemUses(item);
|
||||
}
|
||||
else if (mode == 'features') {
|
||||
items = tokenHelper.getFeatures(token,settings.featureType);
|
||||
items = this.sortItems(items);
|
||||
item = items[itemNr];
|
||||
if (selectionMode == 'order') item = items[itemNr];
|
||||
else if (selectionMode == 'name') item = items.filter(i => i.name == settings.itemName)[0];
|
||||
else if (selectionMode == 'id') item = items.filter(i => i.id == settings.itemName)[0];
|
||||
if (item != undefined && displayUses) uses = tokenHelper.getFeatureUses(item);
|
||||
}
|
||||
else if (mode == 'spellbook') {
|
||||
items = tokenHelper.getSpells(token,settings.spellType);
|
||||
items = this.sortItems(items);
|
||||
item = items[itemNr];
|
||||
if (selectionMode == 'order') item = items[itemNr];
|
||||
else if (selectionMode == 'name') item = items.filter(i => i.name == settings.itemName)[0];
|
||||
else if (selectionMode == 'id') item = items.filter(i => i.id == settings.itemName)[0];
|
||||
if (displayUses && item != undefined) uses = tokenHelper.getSpellUses(token,settings.spellType,item);
|
||||
}
|
||||
if (item != undefined) {
|
||||
@@ -382,7 +411,7 @@ export class TokenControl{
|
||||
if (mode == 'token') {
|
||||
iconSrc += "";
|
||||
if (settings.onClick == 'visibility') { //toggle visibility
|
||||
if (MODULE.getPermission('TOKEN','VISIBILITY') == false ) {
|
||||
if (getPermission('TOKEN','VISIBILITY') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -393,7 +422,7 @@ export class TokenControl{
|
||||
}
|
||||
}
|
||||
else if (settings.onClick == 'combatState') { //toggle combat state
|
||||
if (MODULE.getPermission('TOKEN','COMBAT') == false ) {
|
||||
if (getPermission('TOKEN','COMBAT') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -411,7 +440,7 @@ export class TokenControl{
|
||||
}
|
||||
}
|
||||
else if (settings.onClick == 'condition') { //toggle condition
|
||||
if (MODULE.getPermission('TOKEN','CONDITIONS') == false ) {
|
||||
if (getPermission('TOKEN','CONDITIONS') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -420,7 +449,7 @@ export class TokenControl{
|
||||
if (icon == 'stats') iconSrc = tokenHelper.getConditionIcon(settings.condition);
|
||||
}
|
||||
else if (settings.onClick == 'cubCondition') { //Combat Utility Belt conditions
|
||||
if (MODULE.getPermission('TOKEN','CONDITIONS') == false ) {
|
||||
if (getPermission('TOKEN','CONDITIONS') == false ) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
@@ -435,8 +464,8 @@ export class TokenControl{
|
||||
}
|
||||
}
|
||||
|
||||
if (icon == 'stats'){
|
||||
if (MODULE.getPermission('TOKEN','STATS') == false) stats = statsOld;
|
||||
if (icon == 'stats' && mode != 'offset' && mode != 'offsetRel'){
|
||||
if (getPermission('TOKEN','STATS') == false) stats = statsOld;
|
||||
if (stats == 'HP') //HP
|
||||
iconSrc = "modules/MaterialDeck/img/token/hp_empty.png";
|
||||
if (stats == 'TempHP') //Temp HP
|
||||
@@ -503,13 +532,15 @@ export class TokenControl{
|
||||
iconSrc = "modules/MaterialDeck/img/move/rotateccw.png";
|
||||
}
|
||||
}
|
||||
|
||||
streamDeck.setIcon(context,device,iconSrc,{background:background,ring:ring,ringColor:ringColor,overlay:overlay,uses:uses,hp:hp});
|
||||
streamDeck.setTitle(txt,context);
|
||||
}
|
||||
|
||||
sortItems(items) {
|
||||
let sorted = Object.values(items);
|
||||
sorted.sort((a,b) => a.data.sort - b.data.sort);
|
||||
if (compatibleCore('10.0')) sorted.sort((a,b) => a.sort - b.sort);
|
||||
else sorted.sort((a,b) => a.data.sort - b.data.sort);
|
||||
return sorted;
|
||||
}
|
||||
|
||||
@@ -522,13 +553,11 @@ export class TokenControl{
|
||||
const tokenIdentifier = settings.tokenName ? settings.tokenName : '';
|
||||
const mode = settings.tokenMode ? settings.tokenMode : 'token';
|
||||
|
||||
let token;
|
||||
if (selection == 'selected') token = canvas.tokens.controlled[0];
|
||||
else token = tokenHelper.getToken(selection,tokenIdentifier);
|
||||
let token = tokenHelper.getToken(selection,tokenIdentifier);
|
||||
|
||||
if (token == undefined) return;
|
||||
if (token.owner == false && token.observer == true && MODULE.getPermission('TOKEN','OBSERVER') == false ) return;
|
||||
if (token.owner == false && token.observer == false && MODULE.getPermission('TOKEN','NON_OWNED') == false ) return;
|
||||
if (token.owner == false && token.observer == true && getPermission('TOKEN','OBSERVER') == false ) return;
|
||||
if (token.owner == false && token.observer == false && getPermission('TOKEN','NON_OWNED') == false ) return;
|
||||
|
||||
if (mode == 'token') {
|
||||
|
||||
@@ -565,18 +594,18 @@ export class TokenControl{
|
||||
else token.sheet.close();
|
||||
}
|
||||
else if (onClick == 'visibility') { //Toggle visibility
|
||||
if (MODULE.getPermission('TOKEN','VISIBILITY') == false ) return;
|
||||
if (getPermission('TOKEN','VISIBILITY') == false ) return;
|
||||
token.toggleVisibility();
|
||||
}
|
||||
else if (onClick == 'combatState') { //Toggle combat state
|
||||
if (MODULE.getPermission('TOKEN','COMBAT') == false ) return;
|
||||
if (getPermission('TOKEN','COMBAT') == false ) return;
|
||||
token.toggleCombat();
|
||||
}
|
||||
else if (onClick == 'target') { //Target token
|
||||
token.setTarget(!token.isTargeted,{releaseOthers:false});
|
||||
}
|
||||
else if (onClick == 'condition') { //Handle condition
|
||||
if (MODULE.getPermission('TOKEN','CONDITIONS') == false ) return;
|
||||
if (getPermission('TOKEN','CONDITIONS') == false ) return;
|
||||
const func = settings.conditionFunction ? settings.conditionFunction : 'toggle';
|
||||
|
||||
if (func == 'toggle'){ //toggle
|
||||
@@ -594,7 +623,7 @@ export class TokenControl{
|
||||
|
||||
}
|
||||
else if (onClick == 'cubCondition') { //Combat Utility Belt conditions
|
||||
if (MODULE.getPermission('TOKEN','CONDITIONS') == false ) return;
|
||||
if (getPermission('TOKEN','CONDITIONS') == false ) return;
|
||||
const condition = settings.cubConditionName;
|
||||
if (condition == undefined || condition == '') return;
|
||||
const effect = CONFIG.statusEffects.find(e => e.label === condition);
|
||||
@@ -602,57 +631,108 @@ export class TokenControl{
|
||||
this.update(tokenId);
|
||||
}
|
||||
else if (onClick == 'vision'){
|
||||
if (MODULE.getPermission('TOKEN','VISION') == false ) return;
|
||||
const token = canvas.tokens.children[0].children.find(p => p.id == tokenId);
|
||||
if (token == undefined) return;
|
||||
let tokenData = token.data;
|
||||
if (getPermission('TOKEN','VISION') == false ) return;
|
||||
|
||||
const dimVision = parseInt(settings.dimVision);
|
||||
const brightVision = parseInt(settings.brightVision);
|
||||
const sightAngle = parseInt(settings.sightAngle);
|
||||
const dimRadius = parseInt(settings.dimRadius);
|
||||
const brightRadius = parseInt(settings.brightRadius);
|
||||
const emissionAngle = parseInt(settings.emissionAngle);
|
||||
const lightColor = settings.lightColor ? settings.lightColor : '#000000';
|
||||
const colorIntensity = isNaN(parseInt(settings.colorIntensity)) ? 0 : parseInt(settings.colorIntensity)/100;
|
||||
const animationType = settings.animationType ? settings.animationType : 'none';
|
||||
const animationSpeed = isNaN(parseInt(settings.animationSpeed)) ? 1 : parseInt(settings.animationSpeed);
|
||||
const animationIntensity = isNaN(parseInt(settings.animationIntensity)) ? 1 : parseInt(settings.animationIntensity);
|
||||
|
||||
let data = {};
|
||||
if (isNaN(dimVision)==false) data.dimSight = dimVision;
|
||||
if (isNaN(brightVision)==false) data.brightSight = brightVision;
|
||||
if (isNaN(sightAngle)==false) data.sightAngle = sightAngle;
|
||||
|
||||
let light = {};
|
||||
|
||||
|
||||
if (isNaN(dimRadius)==false) light.dim = dimRadius;
|
||||
if (isNaN(brightRadius)==false) light.bright = brightRadius;
|
||||
if (isNaN(emissionAngle)==false) light.angle = emissionAngle;
|
||||
light.color = lightColor;
|
||||
light.alpha = Math.sqrt(colorIntensity).toNearest(0.05)
|
||||
|
||||
let animation = {
|
||||
type: '',
|
||||
speed: tokenData.light.animation.speed,
|
||||
intensity: tokenData.light.animation.intensity
|
||||
};
|
||||
if (animationType != 'none'){
|
||||
animation.type = animationType;
|
||||
animation.intensity = animationIntensity;
|
||||
animation.speed = animationSpeed;
|
||||
let sight = {};
|
||||
let light = {
|
||||
animation: {}
|
||||
}
|
||||
light.animation = animation;
|
||||
|
||||
//Vision basic config
|
||||
if (settings.visionEnabled && settings.visionEnabled != 'noChange') {
|
||||
if (compatibleCore('10.0')) {
|
||||
if (settings.visionEnabled == 'toggle')
|
||||
sight.enabled = !token.document.sight.enabled;
|
||||
else
|
||||
sight.enabled = settings.visionEnabled == 'enable';
|
||||
}
|
||||
else {
|
||||
if (settings.visionEnabled == 'toggle')
|
||||
sight.vision = !token.data.vision;
|
||||
else
|
||||
sight.vision = settings.visionEnabled == 'enable';
|
||||
}
|
||||
}
|
||||
if (settings.visionRange && isNaN(settings.visionRange) == false) sight.range = parseInt(settings.visionRange);
|
||||
if (settings.visionDimRange && isNaN(settings.visionDimRange) == false) sight.dimSight = parseInt(settings.visionDimRange);
|
||||
if (settings.visionBrightRange && isNaN(settings.visionBrightRange) == false) sight.brightSight = parseInt(settings.visionBrightRange);
|
||||
if (compatibleCore('10.0') && settings.visionAngle && isNaN(settings.visionAngle) == false) sight.angle = parseInt(settings.visionAngle);
|
||||
else if (!compatibleCore('10.0') && settings.visionAngle && isNaN(settings.visionAngle) == false) sight.sightAngle = parseInt(settings.visionAngle);
|
||||
if (settings.visionMode && settings.visionMode != 'noChange') sight.visionMode = settings.visionMode;
|
||||
|
||||
//Vision detection modes
|
||||
let detectionModes = token.document.detectionModes;
|
||||
if (settings.visionDetectionModeEnable && settings.visionDetectionModeEnable != 'noChange' && settings.visionDetectionModeNumber && detectionModes[settings.visionDetectionModeNumber-1] != undefined) {
|
||||
if (settings.visionDetectionModeEnable == 'toggle')
|
||||
detectionModes[settings.visionDetectionModeNumber-1].enabled = !detectionModes[settings.visionDetectionModeNumber-1].enabled;
|
||||
else if (settings.visionDetectionModeEnable == 'enable')
|
||||
detectionModes[settings.visionDetectionModeNumber-1].enabled = true;
|
||||
else if (settings.visionDetectionModeEnable == 'disable')
|
||||
detectionModes[settings.visionDetectionModeNumber-1].enabled = false;
|
||||
detectionModes = detectionModes;
|
||||
}
|
||||
|
||||
//Vision advanced options
|
||||
if (settings.visionColorEnable) sight.color = settings.visionColor ? (settings.visionColor == '#000000' ? null : settings.visionColor) : null;
|
||||
if (settings.visionAttenuationEnable) sight.attenuation = settings.visionAttenuation ? parseFloat(settings.visionAttenuation) : 0;
|
||||
if (settings.visionBrightnessEnable) sight.brightness = settings.visionBrightness ? parseFloat(settings.visionBrightness) : 0;
|
||||
if (settings.visionSaturationEnable) sight.saturation = settings.visionSaturation ? parseFloat(settings.visionSaturation) : 0;
|
||||
if (settings.visionContrastEnable) sight.contrast = settings.visionContrast ? parseFloat(settings.visionContrast) : 0;
|
||||
|
||||
//Light basic config
|
||||
if (settings.lightDimRadius && isNaN(settings.lightDimRadius) == false) light.dim = parseInt(settings.lightDimRadius);
|
||||
if (settings.lightBrightRadius && isNaN(settings.lightBrightRadius) == false) light.bright = parseInt(settings.lightBrightRadius);
|
||||
if (settings.lightEmissionAngle && isNaN(settings.lightEmissionAngle) == false) light.angle = parseInt(settings.lightEmissionAngle);
|
||||
if (settings.lightColorEnable) light.color = settings.lightColor ? (settings.lightColor == '#000000' ? null : settings.lightColor) : null;
|
||||
if (settings.lightColorIntensityEnable) light.alpha = settings.lightColorIntensity ? parseFloat(settings.lightColorIntensity) : 0;
|
||||
|
||||
//Light animation
|
||||
if (settings.lightAnimationType && settings.lightAnimationType != 'noChange') light.animation.type = settings.lightAnimationType == 'none' ? null : settings.lightAnimationType;
|
||||
if (settings.lightAnimationSpeedEnable) light.animation.speed = settings.lightAnimationSpeed ? parseFloat(settings.lightAnimationSpeed) : 5;
|
||||
if (settings.lightAnimationReverseDirection && settings.lightAnimationReverseDirection != 'noChange') {
|
||||
if (settings.lightAnimationReverseDirection == 'toggle')
|
||||
light.animation.reverse = compatibleCore('10.0') ? !token.document.light.animation.reverse : !token.data.light.animation.reverse;
|
||||
else if (settings.lightAnimationReverseDirection == 'enable')
|
||||
light.animation.reverse = true;
|
||||
else if (settings.lightAnimationReverseDirection == 'disable')
|
||||
light.animation.reverse = false;
|
||||
}
|
||||
if (settings.lightAnimationIntensityEnable) light.animation.intensity = settings.lightAnimationIntensity ? parseFloat(settings.lightAnimationIntensity) : 5;
|
||||
|
||||
//Light advanced options
|
||||
if (settings.lightColorationTechnique && settings.lightColorationTechnique != 'noChange') light.coloration = parseInt(settings.lightColorationTechnique);
|
||||
if (settings.lightLuminosityEnable) light.luminosity = settings.lightLuminosity ? parseFloat(settings.lightLuminosity) : 0.5;
|
||||
if (settings.lightGradualIllumination && settings.lightGradualIllumination != 'noChange') {
|
||||
if (settings.lightGradualIllumination == 'toggle')
|
||||
light.gradual = !token.data.light.gradual;
|
||||
else if (settings.lightGradualIllumination == 'enable')
|
||||
light.gradual = true;
|
||||
else if (settings.lightGradualIllumination == 'disable')
|
||||
light.gradual = false;
|
||||
}
|
||||
if (settings.lightAttenuationEnable) light.attenuation = settings.lightAttenuation ? parseFloat(settings.lightAttenuation) : 0.5;
|
||||
if (settings.lightSaturationEnable) light.saturation = settings.lightSaturation ? parseFloat(settings.lightSaturation) : 0;
|
||||
if (settings.lightContrastEnable) light.contrast = settings.lightContrast ? parseFloat(settings.lightContrast) : 0;
|
||||
if (settings.lightShadowsEnable) light.shadows = settings.lightShadows ? parseFloat(settings.lightShadows) : 0;
|
||||
|
||||
let data;
|
||||
if (compatibleCore('10.0')) {
|
||||
data = {
|
||||
sight,
|
||||
light
|
||||
}
|
||||
}
|
||||
else {
|
||||
data = sight;
|
||||
data.light = light;
|
||||
if (compatibleCore('0.8.1')) token.document.update(data);
|
||||
else token.update(data);
|
||||
}
|
||||
token.document.update(data);
|
||||
}
|
||||
else if (onClick == 'initiative'){
|
||||
tokenHelper.toggleInitiative(token);
|
||||
}
|
||||
else if (onClick == 'wildcard') { //wildcard images
|
||||
if (MODULE.getPermission('TOKEN','WILDCARD') == false ) return;
|
||||
if (getPermission('TOKEN','WILDCARD') == false ) return;
|
||||
const method = settings.wildcardMethod ? settings.wildcardMethod : 'iterate';
|
||||
let value = parseInt(settings.wildcardValue);
|
||||
if (isNaN(value)) value = 1;
|
||||
@@ -663,7 +743,7 @@ export class TokenControl{
|
||||
if (method == 'iterate'){
|
||||
let currentImgNr = 0
|
||||
for (let i=0; i<images.length; i++)
|
||||
if (images[i] == token.data.img){
|
||||
if (images[i] == tokenHelper.getTokenIcon(token)){
|
||||
currentImgNr = i;
|
||||
break;
|
||||
}
|
||||
@@ -684,8 +764,7 @@ export class TokenControl{
|
||||
else return;
|
||||
|
||||
iconSrc = images[imgNr];
|
||||
if (compatibleCore('0.8.1')) token.document.update({img: iconSrc});
|
||||
else token.update({img: iconSrc})
|
||||
token.document.update({img: iconSrc});
|
||||
}
|
||||
else if (onClick == 'macro') { //call a macro
|
||||
const settingsNew = {
|
||||
@@ -712,7 +791,7 @@ export class TokenControl{
|
||||
if (otherControls.rollOption != 'dialog') otherControls.setRollOption('normal');
|
||||
}
|
||||
else if (onClick == 'custom') {//custom onClick function
|
||||
if (MODULE.getPermission('TOKEN','CUSTOM') == false ) return;
|
||||
if (getPermission('TOKEN','CUSTOM') == false ) return;
|
||||
const formula = settings.customOnClickFormula ? settings.customOnClickFormula : '';
|
||||
if (formula == '') return;
|
||||
|
||||
@@ -828,8 +907,7 @@ export class TokenControl{
|
||||
if (path != '') path += '.';
|
||||
path += targetArray[i][j];
|
||||
}
|
||||
if (compatibleCore('0.8.1')) await token.document.update({[path]:value});
|
||||
else await token.update({[path]:value})
|
||||
await token.document.update({[path]:value});
|
||||
this.update(token.id);
|
||||
}
|
||||
|
||||
@@ -837,9 +915,20 @@ export class TokenControl{
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mode == 'offset') {
|
||||
const itemOffset = settings.itemOffset ? settings.itemOffset : 0;
|
||||
this.itemOffset = parseInt(itemOffset);
|
||||
this.update(tokenId);
|
||||
}
|
||||
else if (mode == 'offsetRel') {
|
||||
const itemOffset = settings.itemOffset ? settings.itemOffset : 0;
|
||||
this.itemOffset += parseInt(itemOffset);
|
||||
this.update(tokenId);
|
||||
}
|
||||
else {
|
||||
const allItems = token.actor.items;
|
||||
const itemNr = settings.itemNr ? settings.itemNr - 1 : 0;
|
||||
const selectionMode = settings.inventorySelection ? settings.inventorySelection : 'order';
|
||||
let items = allItems;
|
||||
if (mode == 'inventory') {
|
||||
items = tokenHelper.getItems(token,settings.inventoryType);
|
||||
@@ -851,10 +940,12 @@ export class TokenControl{
|
||||
items = tokenHelper.getSpells(token,settings.spellType);
|
||||
}
|
||||
items = this.sortItems(items);
|
||||
|
||||
const item = items[itemNr];
|
||||
let item;
|
||||
if (selectionMode == 'order') item = items[itemNr];
|
||||
else if (selectionMode == 'name') item = items.filter(i => i.name == settings.itemName)[0];
|
||||
else if (selectionMode == 'id') item = items.filter(i => i.id == settings.itemName)[0];
|
||||
if (item != undefined) {
|
||||
tokenHelper.rollItem(item, settings);
|
||||
tokenHelper.rollItem(item, settings, otherControls.rollOption);
|
||||
}
|
||||
|
||||
}
|
||||
199
src/misc.js
199
src/misc.js
@@ -1,16 +1,34 @@
|
||||
import {sdVersion, msVersion, moduleName, getPermission, enableModule, streamDeck} from "../MaterialDeck.js";
|
||||
import {macroControl,soundboard,playlistControl} from "../MaterialDeck.js";
|
||||
import { sdVersion, msVersion, moduleName, getPermission, enableModule, streamDeck, macroControl,soundboard,playlistControl, minimumMSversion, minimumSDversion } from "../MaterialDeck.js";
|
||||
|
||||
export function compareVersions(checkedVersion, requiredVersion) {
|
||||
requiredVersion = requiredVersion.split(".");
|
||||
checkedVersion = checkedVersion.split(".");
|
||||
|
||||
for (let i=0; i<3; i++) {
|
||||
requiredVersion[i] = isNaN(parseInt(requiredVersion[i])) ? 0 : parseInt(requiredVersion[i]);
|
||||
checkedVersion[i] = isNaN(parseInt(checkedVersion[i])) ? 0 : parseInt(checkedVersion[i]);
|
||||
}
|
||||
|
||||
if (checkedVersion[0] > requiredVersion[0]) return false;
|
||||
if (checkedVersion[0] < requiredVersion[0]) return true;
|
||||
if (checkedVersion[1] > requiredVersion[1]) return false;
|
||||
if (checkedVersion[1] < requiredVersion[1]) return true;
|
||||
if (checkedVersion[2] > requiredVersion[2]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function compatibleCore(compatibleVersion){
|
||||
const split = compatibleVersion.split(".");
|
||||
if (split.length == 2) compatibleVersion = `0.${compatibleVersion}`;
|
||||
let coreVersion = game.version == undefined ? game.data.version : `0.${game.version}`;
|
||||
coreVersion = coreVersion.split(".");
|
||||
compatibleVersion = compatibleVersion.split(".");
|
||||
if (compatibleVersion[0] > coreVersion[0]) return false;
|
||||
if (compatibleVersion[0] < coreVersion[0]) return true;
|
||||
if (compatibleVersion[1] > coreVersion[1]) return false;
|
||||
if (compatibleVersion[1] < coreVersion[1]) return true;
|
||||
if (compatibleVersion[2] > coreVersion[2]) return false;
|
||||
return true;
|
||||
return compareVersions(compatibleVersion, coreVersion);
|
||||
}
|
||||
|
||||
export function compatibleSystem(compatibleVersion){
|
||||
const split = compatibleVersion.split(".");
|
||||
if (split.length == 2) compatibleVersion = `0.${compatibleVersion}`;
|
||||
let coreVersion = game.system.data.version;
|
||||
return compareVersions(compatibleVersion, coreVersion);
|
||||
}
|
||||
|
||||
export class playlistConfigForm extends FormApplication {
|
||||
@@ -78,7 +96,7 @@ export class playlistConfigForm extends FormApplication {
|
||||
}
|
||||
|
||||
return {
|
||||
playlists: compatibleCore("0.8.1") ? game.playlists.contents : game.playlists.entities,
|
||||
playlists: game.playlists.contents,
|
||||
numberOfPlaylists: numberOfPlaylists,
|
||||
playlistData: playlistData,
|
||||
playMode: playMode
|
||||
@@ -156,7 +174,7 @@ export class macroConfigForm extends FormApplication {
|
||||
*/
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
id: "macro-config",
|
||||
id: "materialDeck_macroConfig",
|
||||
title: "Material Deck: "+game.i18n.localize("MaterialDeck.Sett.MacroConfig"),
|
||||
template: "./modules/MaterialDeck/templates/macroConfig.html",
|
||||
classes: ["sheet"]
|
||||
@@ -182,12 +200,12 @@ export class macroConfigForm extends FormApplication {
|
||||
if (args == undefined) args = [];
|
||||
|
||||
//Check if the Furnace is installed and enabled
|
||||
let furnaceEnabled = false;
|
||||
let height = 95;
|
||||
let furnace = game.modules.get("furnace");
|
||||
let advancedMacrosEnabled = false;
|
||||
let advancedMacros = game.modules.get("advanced-macros");
|
||||
if ((furnace != undefined && furnace.active && compatibleCore("0.8.1")==false) || (advancedMacros != undefined && advancedMacros.active)) {
|
||||
furnaceEnabled = true;
|
||||
if (advancedMacros != undefined && advancedMacros.active) advancedMacrosEnabled = true;
|
||||
if (advancedMacrosEnabled) {
|
||||
advancedMacrosEnabled = true;
|
||||
height += 50;
|
||||
}
|
||||
|
||||
@@ -226,7 +244,7 @@ export class macroConfigForm extends FormApplication {
|
||||
macros: game.macros,
|
||||
selectedMacros: selectedMacros,
|
||||
macroData: macroData,
|
||||
furnace: furnaceEnabled,
|
||||
furnace: advancedMacrosEnabled,
|
||||
macroRange: `${this.page*32 + 1} - ${this.page*32 + 32}`,
|
||||
prevDisabled: this.page == 0 ? 'disabled' : '',
|
||||
totalMacros: Math.max(Math.ceil(selectedMacros.length/32)*32, this.page*32 + 32)
|
||||
@@ -244,12 +262,12 @@ export class macroConfigForm extends FormApplication {
|
||||
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
const navNext = html.find("button[id='navNext']");
|
||||
const navPrev = html.find("button[id='navPrev']");
|
||||
const clearAll = html.find("button[id='clearAll']");
|
||||
const clearPage = html.find("button[id='clearPage']");
|
||||
const importBtn = html.find("button[id='import']");
|
||||
const exportBtn = html.find("button[id='export']");
|
||||
const navNext = html.find("button[name='navNext']");
|
||||
const navPrev = html.find("button[name='navPrev']");
|
||||
const clearAll = html.find("button[name='clearAll']");
|
||||
const clearPage = html.find("button[name='clearPage']");
|
||||
const importBtn = html.find("button[name='import']");
|
||||
const exportBtn = html.find("button[name='export']");
|
||||
const macro = html.find("select[name='macros']");
|
||||
const args = html.find("input[name='args']");
|
||||
const color = html.find("input[name='colorPicker']");
|
||||
@@ -340,21 +358,21 @@ export class macroConfigForm extends FormApplication {
|
||||
})
|
||||
|
||||
macro.on("change", event => {
|
||||
let id = event.target.id.replace('macros','');
|
||||
let id = event.target.id.replace('materialDeck_macroConfig_macros','');
|
||||
let settings = game.settings.get(moduleName,'macroSettings');
|
||||
settings.macros[id-1]=event.target.value;
|
||||
this.updateSettings(settings);
|
||||
});
|
||||
|
||||
args.on("change", event => {
|
||||
let id = event.target.id.replace('args','');
|
||||
let id = event.target.id.replace('materialDeck_macroConfig_args','');
|
||||
let settings = game.settings.get(moduleName,'macroSettings');
|
||||
settings.args[id-1]=event.target.value;
|
||||
this.updateSettings(settings);
|
||||
});
|
||||
|
||||
color.on("change", event => {
|
||||
let id = event.target.id.replace('colorpicker','');
|
||||
let id = event.target.id.replace('materialDeck_macroConfig_colorpicker','');
|
||||
let settings = game.settings.get(moduleName,'macroSettings');
|
||||
settings.color[id-1]=event.target.value;
|
||||
this.updateSettings(settings);
|
||||
@@ -434,7 +452,7 @@ export class soundboardConfigForm extends FormApplication {
|
||||
*/
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
id: "soundboard-config",
|
||||
id: "materialDeck_soundboardConfig",
|
||||
title: "Material Deck: "+game.i18n.localize("MaterialDeck.Sett.SoundboardConfig"),
|
||||
template: "./modules/MaterialDeck/templates/soundboardConfig.html",
|
||||
classes: ["sheet"],
|
||||
@@ -470,7 +488,7 @@ export class soundboardConfigForm extends FormApplication {
|
||||
playlists.push({id:"none",name:game.i18n.localize("MaterialDeck.None")});
|
||||
playlists.push({id:"FP",name:game.i18n.localize("MaterialDeck.FilePicker")})
|
||||
|
||||
const playlistArray = compatibleCore("0.8.1") ? game.playlists.contents : game.playlists.entities;
|
||||
const playlistArray = game.playlists.contents;
|
||||
for (let playlist of playlistArray)
|
||||
playlists.push({id: playlist.id, name: playlist.name})
|
||||
|
||||
@@ -496,7 +514,7 @@ export class soundboardConfigForm extends FormApplication {
|
||||
else if (this.settings.selectedPlaylists[iteration] == 'FP') selectedPlaylist = 'FP';
|
||||
else {
|
||||
//Get the playlist
|
||||
const playlistArray = compatibleCore("0.8.1") ? game.playlists.contents : game.playlists.entities;
|
||||
const playlistArray = game.playlists.contents;
|
||||
let pl = playlistArray.find(p => p.id == this.settings.selectedPlaylists[iteration])
|
||||
|
||||
if (pl == undefined){
|
||||
@@ -505,19 +523,12 @@ export class soundboardConfigForm extends FormApplication {
|
||||
}
|
||||
else {
|
||||
//Add the sound name and id to the sounds array
|
||||
if (compatibleCore("0.8.1"))
|
||||
for (let sound of pl.sounds.contents)
|
||||
sounds.push({
|
||||
name: sound.name,
|
||||
id: sound.id
|
||||
});
|
||||
else {
|
||||
for (let sound of pl.sounds)
|
||||
sounds.push({
|
||||
name: sound.name,
|
||||
id: sound._id
|
||||
});
|
||||
}
|
||||
|
||||
//Get the playlist id
|
||||
selectedPlaylist = pl.id;
|
||||
}
|
||||
@@ -538,8 +549,8 @@ export class soundboardConfigForm extends FormApplication {
|
||||
sound: this.settings.sounds[iteration],
|
||||
sounds: sounds,
|
||||
srcPath: this.settings.src[iteration],
|
||||
colorOn: this.settings.colorOn[iteration],
|
||||
colorOff: this.settings.colorOff[iteration],
|
||||
colorOn: this.settings.colorOn[iteration] == 0 ? '#000000' : this.settings.colorOn[iteration],
|
||||
colorOff: this.settings.colorOff[iteration] == 0 ? '#000000' : this.settings.colorOff[iteration],
|
||||
mode: this.settings.mode[iteration],
|
||||
volume: this.settings.volume[iteration],
|
||||
imgPath: this.settings.img[iteration],
|
||||
@@ -578,12 +589,12 @@ export class soundboardConfigForm extends FormApplication {
|
||||
|
||||
async activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
const navNext = html.find("button[id='navNext']");
|
||||
const navPrev = html.find("button[id='navPrev']");
|
||||
const clearAll = html.find("button[id='clearAll']");
|
||||
const clearPage = html.find("button[id='clearPage']");
|
||||
const importBtn = html.find("button[id='import']");
|
||||
const exportBtn = html.find("button[id='export']");
|
||||
const navNext = html.find("button[name='navNext']");
|
||||
const navPrev = html.find("button[name='navPrev']");
|
||||
const clearAll = html.find("button[name='clearAll']");
|
||||
const clearPage = html.find("button[name='clearPage']");
|
||||
const importBtn = html.find("button[name='import']");
|
||||
const exportBtn = html.find("button[name='export']");
|
||||
const nameField = html.find("input[name='namebox']");
|
||||
const playlistSelect = html.find("select[name='playlist']");
|
||||
const soundSelect = html.find("select[name='sounds']");
|
||||
@@ -678,7 +689,7 @@ export class soundboardConfigForm extends FormApplication {
|
||||
})
|
||||
|
||||
nameField.on("change",event => {
|
||||
let id = event.target.id.replace('name','')-1;
|
||||
let id = event.target.id.replace('materialDeck_sbConfig_name','')-1;
|
||||
this.settings.name[id]=event.target.value;
|
||||
this.updateSettings(this.settings);
|
||||
});
|
||||
@@ -688,7 +699,7 @@ export class soundboardConfigForm extends FormApplication {
|
||||
//Listener for when the playlist is changed
|
||||
playlistSelect.on("change", event => {
|
||||
//Get the sound number
|
||||
const iteration = event.target.id.replace('playlists','');
|
||||
const iteration = event.target.id.replace('materialDeck_sbConfig_playlists','');
|
||||
|
||||
//Get the selected playlist and the sounds of that playlist
|
||||
let selectedPlaylist;
|
||||
@@ -699,24 +710,24 @@ export class soundboardConfigForm extends FormApplication {
|
||||
selectedPlaylist = 'FP';
|
||||
|
||||
//Show the file picker
|
||||
document.querySelector(`#fp${iteration}`).style='';
|
||||
document.querySelector(`#materialDeck_sbConfig_fp${iteration}`).style='';
|
||||
|
||||
//Hide the sound selector
|
||||
document.querySelector(`#ss${iteration}`).style='display:none';
|
||||
document.querySelector(`#materialDeck_sbConfig_ss${iteration}`).style='display:none';
|
||||
}
|
||||
else {
|
||||
//Hide the file picker
|
||||
document.querySelector(`#fp${iteration}`).style='display:none';
|
||||
document.querySelector(`#materialDeck_sbConfig_fp${iteration}`).style='display:none';
|
||||
|
||||
//Show the sound selector
|
||||
document.querySelector(`#ss${iteration}`).style='';
|
||||
document.querySelector(`#materialDeck_sbConfig_ss${iteration}`).style='';
|
||||
|
||||
const playlistArray = compatibleCore("0.8.1") ? game.playlists.contents : game.playlists.entities;
|
||||
const playlistArray = game.playlists.contents;
|
||||
const pl = playlistArray.find(p => p.id == event.target.value)
|
||||
selectedPlaylist = pl.id;
|
||||
|
||||
//Get the sound select element
|
||||
let SSpicker = document.getElementById(`soundSelect${iteration}`);
|
||||
let SSpicker = document.getElementById(`materialDeck_sbConfig_soundSelect${iteration}`);
|
||||
|
||||
//Empty ss element
|
||||
SSpicker.options.length=0;
|
||||
@@ -727,20 +738,12 @@ export class soundboardConfigForm extends FormApplication {
|
||||
optionNone.innerHTML = game.i18n.localize("MaterialDeck.None");
|
||||
SSpicker.appendChild(optionNone);
|
||||
|
||||
if (compatibleCore("0.8.1"))
|
||||
for (let sound of pl.sounds.contents) {
|
||||
let newOption = document.createElement('option');
|
||||
newOption.value = sound.id;
|
||||
newOption.innerHTML = sound.name;
|
||||
SSpicker.appendChild(newOption);
|
||||
}
|
||||
else
|
||||
for (let sound of pl.sounds) {
|
||||
let newOption = document.createElement('option');
|
||||
newOption.value = sound._id;
|
||||
newOption.innerHTML = sound.name;
|
||||
SSpicker.appendChild(newOption);
|
||||
}
|
||||
}
|
||||
|
||||
//Save the new playlist to this.settings, and update the settings
|
||||
@@ -750,43 +753,43 @@ export class soundboardConfigForm extends FormApplication {
|
||||
}
|
||||
|
||||
soundSelect.on("change", event => {
|
||||
let id = event.target.id.replace('soundSelect','')-1;
|
||||
let id = event.target.id.replace('materialDeck_sbConfig_soundSelect','')-1;
|
||||
this.settings.sounds[id]=event.target.value;
|
||||
this.updateSettings(this.settings);
|
||||
});
|
||||
|
||||
soundFP.on("change",event => {
|
||||
let id = event.target.id.replace('srcPath','')-1;
|
||||
let id = event.target.id.replace('materialDeck_sbConfig_srcPath','')-1;
|
||||
this.settings.src[id]=event.target.value;
|
||||
this.updateSettings(this.settings);
|
||||
});
|
||||
|
||||
imgFP.on("change",event => {
|
||||
let id = event.target.id.replace('imgPath','')-1;
|
||||
let id = event.target.id.replace('materialDeck_sbConfig_imgPath','')-1;
|
||||
this.settings.img[id]=event.target.value;
|
||||
this.updateSettings(this.settings);
|
||||
});
|
||||
|
||||
onCP.on("change",event => {
|
||||
let id = event.target.id.replace('colorOn','')-1;
|
||||
let id = event.target.id.replace('materialDeck_sbConfig_colorOn','')-1;
|
||||
this.settings.colorOn[id]=event.target.value;
|
||||
this.updateSettings(this.settings);
|
||||
});
|
||||
|
||||
offCP.on("change",event => {
|
||||
let id = event.target.id.replace('colorOff','')-1;
|
||||
let id = event.target.id.replace('materialDeck_sbConfig_colorOff','')-1;
|
||||
this.settings.colorOff[id]=event.target.value;
|
||||
this.updateSettings(this.settings);
|
||||
});
|
||||
|
||||
playMode.on("change",event => {
|
||||
let id = event.target.id.replace('playmode','')-1;
|
||||
let id = event.target.id.replace('materialDeck_sbConfig_playmode','')-1;
|
||||
this.settings.mode[id]=event.target.value;
|
||||
this.updateSettings(this.settings);
|
||||
});
|
||||
|
||||
volume.on("change",event => {
|
||||
let id = event.target.id.replace('volume','')-1;
|
||||
let id = event.target.id.replace('materialDeck_sbConfig_volume','')-1;
|
||||
this.settings.volume[id]=event.target.value;
|
||||
this.updateSettings(this.settings);
|
||||
});
|
||||
@@ -885,7 +888,7 @@ export class exportConfigForm extends FormApplication {
|
||||
*/
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
id: "MD_Export",
|
||||
id: "materialDeck_Export",
|
||||
title: "Material Deck: " + game.i18n.localize("MaterialDeck.ExportDialog.Title"),
|
||||
template: "./modules/MaterialDeck/templates/exportDialog.html",
|
||||
width: 500,
|
||||
@@ -948,7 +951,7 @@ export class importConfigForm extends FormApplication {
|
||||
*/
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
id: "MD_Import",
|
||||
id: "materialDeck_Import",
|
||||
title: "Material Deck: " + game.i18n.localize("MaterialDeck.ImportDialog.Title"),
|
||||
template: "./modules/MaterialDeck/templates/importDialog.html",
|
||||
width: 500,
|
||||
@@ -986,7 +989,7 @@ export class importConfigForm extends FormApplication {
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
const upload = html.find("input[id='uploadJson']");
|
||||
const upload = html.find("input[id='materialDeck_import_uploadJson']");
|
||||
|
||||
upload.on('change',(event) => {
|
||||
event.preventDefault();
|
||||
@@ -1033,7 +1036,7 @@ export class downloadUtility extends FormApplication {
|
||||
*/
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
id: "MD_DownloadUtility",
|
||||
id: "materialDeck_downloadUtility",
|
||||
title: "Material Deck: " + game.i18n.localize("MaterialDeck.DownloadUtility.Title"),
|
||||
template: "./modules/MaterialDeck/templates/downloadUtility.html",
|
||||
width: 500,
|
||||
@@ -1059,23 +1062,12 @@ export class downloadUtility extends FormApplication {
|
||||
}
|
||||
if (this.localMSversion == undefined) this.localMSversion = 'unknown';
|
||||
|
||||
let minimumSdVersion;
|
||||
let minimumMsVersion;
|
||||
if (compatibleCore("0.8.5")) {
|
||||
minimumSdVersion = game.modules.get("MaterialDeck").data.flags.minimumSDversion.replace('v','');
|
||||
minimumMsVersion = game.modules.get("MaterialDeck").data.flags.minimumMSversion;
|
||||
}
|
||||
else {
|
||||
minimumSdVersion = game.modules.get("MaterialDeck").data.minimumSDversion.replace('v','');
|
||||
minimumMsVersion = game.modules.get("MaterialDeck").data.minimumMSversion;
|
||||
}
|
||||
|
||||
return {
|
||||
minimumSdVersion,
|
||||
minimumSdVersion: minimumSDversion,
|
||||
localSdVersion: this.localSDversion,
|
||||
masterSdVersion: this.masterSDversion,
|
||||
sdDlDisable: this.masterSDversion == undefined,
|
||||
minimumMsVersion,
|
||||
minimumMsVersion: minimumMSversion,
|
||||
localMsVersion: this.localMSversion,
|
||||
masterMsVersion: this.masterMSversion,
|
||||
msDlDisable: this.masterMSversion == undefined,
|
||||
@@ -1096,20 +1088,20 @@ export class downloadUtility extends FormApplication {
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
const downloadSd = html.find("button[id='downloadSd']");
|
||||
const downloadMs = html.find("button[id='downloadMs']");
|
||||
const downloadSd = html.find("button[id='materialDeck_dlUtil_downloadSd']");
|
||||
const downloadMs = html.find("button[id='materialDeck_dlUtil_downloadMs']");
|
||||
const downloadProfile = html.find("button[name='downloadProfile']")
|
||||
const refresh = html.find("button[id='refresh']");
|
||||
const refresh = html.find("button[id='materialDeck_dlUtil_refresh']");
|
||||
|
||||
downloadSd.on('click', () => {
|
||||
const version = document.getElementById('masterSdVersion').innerHTML;
|
||||
const version = document.getElementById('materialDeck_dlUtil_masterSdVersion').innerHTML;
|
||||
if (version == '' || version == undefined || version == 'Error') return;
|
||||
const url = `https://github.com/CDeenen/MaterialDeck_SD/releases/download/v${version}/com.cdeenen.materialdeck.streamDeckPlugin`;
|
||||
this.downloadURI(url,'com.cdeenen.materialdeck.streamDeckPlugin')
|
||||
})
|
||||
downloadMs.on('click', () => {
|
||||
const version = document.getElementById('masterMsVersion').innerHTML;
|
||||
const os = document.getElementById('os').value;
|
||||
const version = document.getElementById('materialDeck_dlUtil_masterMsVersion').innerHTML;
|
||||
const os = document.getElementById('materialDeck_dlUtil_os').value;
|
||||
if (version == '' || version == undefined || version == 'Error') return;
|
||||
let name = `MaterialServer-${os}.zip`;
|
||||
let url;
|
||||
@@ -1118,13 +1110,13 @@ export class downloadUtility extends FormApplication {
|
||||
this.downloadURI(url,name)
|
||||
})
|
||||
downloadProfile.on('click',(event) => {
|
||||
let id = event.currentTarget.id.replace('dlProfile-','');
|
||||
let id = event.currentTarget.id.replace('materialDeck_dlUtil_dlProfile-','');
|
||||
this.downloadURI(this.profiles[id].url,`${this.profiles[id].label}.streamDeckProfile`);
|
||||
})
|
||||
refresh.on('click', () => {
|
||||
document.getElementById('masterSdVersion').value = 'Getting data';
|
||||
document.getElementById('materialDeck_dlUtil_masterSdVersion').value = 'Getting data';
|
||||
this.checkForUpdate('SD');
|
||||
document.getElementById('masterMsVersion').value = 'Getting data';
|
||||
document.getElementById('materialDeck_dlUtil_masterMsVersion').value = 'Getting data';
|
||||
this.checkForUpdate('MS');
|
||||
this.getReleaseData();
|
||||
})
|
||||
@@ -1151,22 +1143,18 @@ export class downloadUtility extends FormApplication {
|
||||
const data = JSON.parse(request.responseText);
|
||||
parent.releaseAssets = data.assets;
|
||||
parent.render(true);
|
||||
if (type.indexOf("text") !== 1) {
|
||||
|
||||
return;
|
||||
if (type.indexOf("text") !== 1) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
request.onerror = function () {
|
||||
}
|
||||
request.onerror = function () {}
|
||||
}
|
||||
|
||||
checkForUpdate(reqType) {
|
||||
let parent = this;
|
||||
let url;
|
||||
if (reqType == 'SD') url = 'https://raw.githubusercontent.com/CDeenen/MaterialDeck_SD/master/Plugin/com.cdeenen.materialdeck.sdPlugin/manifest.json';
|
||||
else if (reqType == 'MS') url = 'https://raw.githubusercontent.com/CDeenen/MaterialServer/master/src/Windows/package.json';
|
||||
const elementId = reqType == 'SD' ? 'masterSdVersion' : 'masterMsVersion';
|
||||
else if (reqType == 'MS') url = 'https://raw.githubusercontent.com/CDeenen/MaterialServer/master/package.json';
|
||||
const elementId = reqType == 'SD' ? 'materialDeck_dlUtil_masterSdVersion' : 'materialDeck_dlUtil_masterMsVersion';
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('GET', url, true);
|
||||
@@ -1180,7 +1168,6 @@ export class downloadUtility extends FormApplication {
|
||||
parent.render(true);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
request.onerror = function () {
|
||||
@@ -1201,7 +1188,7 @@ export class deviceConfig extends FormApplication {
|
||||
*/
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
id: "MD_DeviceConfig",
|
||||
id: "materialDeck_deviceConfig",
|
||||
title: "Material Deck: " + game.i18n.localize("MaterialDeck.DeviceConfig.Title"),
|
||||
template: "./modules/MaterialDeck/templates/deviceConfig.html",
|
||||
width: 500,
|
||||
@@ -1221,6 +1208,7 @@ export class deviceConfig extends FormApplication {
|
||||
}
|
||||
|
||||
for (let d of streamDeck.buttonContext) {
|
||||
if (d == undefined) continue;
|
||||
let type;
|
||||
if (d.type == 0) type = 'Stream Deck';
|
||||
else if (d.type == 1) type = 'Stream Deck Mini';
|
||||
@@ -1243,6 +1231,7 @@ export class deviceConfig extends FormApplication {
|
||||
this.devices.push(device);
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
devices: this.devices
|
||||
}
|
||||
@@ -1261,7 +1250,7 @@ export class deviceConfig extends FormApplication {
|
||||
super.activateListeners(html);
|
||||
|
||||
html.find("input[name='enable']").on('change', (event) => {
|
||||
const id = event.currentTarget.id;
|
||||
const id = event.currentTarget.id.replace('materialDeck_devConf_','');;
|
||||
for (let d of this.devices) {
|
||||
if (d.id == id) {
|
||||
let dConfig = game.settings.get(moduleName, 'devices');
|
||||
|
||||
119
src/settings.js
119
src/settings.js
@@ -1,4 +1,4 @@
|
||||
import * as MODULE from "../MaterialDeck.js";
|
||||
import { moduleName, isEmpty } from "../MaterialDeck.js";
|
||||
import { playlistConfigForm, macroConfigForm, soundboardConfigForm, downloadUtility, deviceConfig } from "./misc.js";
|
||||
|
||||
let userPermissions = {};
|
||||
@@ -70,7 +70,7 @@ export const registerSettings = async function() {
|
||||
//world,global,client
|
||||
|
||||
//Enabled the module
|
||||
game.settings.register(MODULE.moduleName,'Enable', {
|
||||
game.settings.register(moduleName,'Enable', {
|
||||
name: "MaterialDeck.Sett.Enable",
|
||||
scope: "client",
|
||||
config: true,
|
||||
@@ -82,20 +82,31 @@ export const registerSettings = async function() {
|
||||
/**
|
||||
* System override
|
||||
*/
|
||||
game.settings.register(MODULE.moduleName,'systemOverride', {
|
||||
game.settings.register(moduleName,'systemOverride', {
|
||||
name: "MaterialDeck.Sett.SystemOverride",
|
||||
hint: "MaterialDeck.Sett.SystemOverrideHint",
|
||||
scope: "client",
|
||||
config: true,
|
||||
default: "",
|
||||
type: String,
|
||||
choices: {
|
||||
"": "Autodetect",
|
||||
"D35E": "Dungeons & Dragons 3.5e",
|
||||
"dnd5e": "Dungeons & Dragons 5e",
|
||||
"forbidden-lands": "Forbidden Lands",
|
||||
"pf1": "Pathfinder 1e",
|
||||
"pf2e": "Pathfinder 2e",
|
||||
"demonlord": "Shadow of the Demon Lord",
|
||||
"sfrpg": "Starfinder",
|
||||
"wfrp4e": "Warhammer Fantasy Roleplay 4e",
|
||||
},
|
||||
onChange: x => window.location.reload()
|
||||
});
|
||||
|
||||
/**
|
||||
* Sets the ip address of the server
|
||||
*/
|
||||
game.settings.register(MODULE.moduleName,'address', {
|
||||
game.settings.register(moduleName,'address', {
|
||||
name: "MaterialDeck.Sett.ServerAddr",
|
||||
hint: "MaterialDeck.Sett.ServerAddrHint",
|
||||
scope: "client",
|
||||
@@ -105,7 +116,7 @@ export const registerSettings = async function() {
|
||||
onChange: x => window.location.reload()
|
||||
});
|
||||
|
||||
game.settings.register(MODULE.moduleName, 'imageBuffer', {
|
||||
game.settings.register(moduleName, 'imageBuffer', {
|
||||
name: "MaterialDeck.Sett.ImageBuffer",
|
||||
hint: "MaterialDeck.Sett.ImageBufferHint",
|
||||
default: 100,
|
||||
@@ -116,7 +127,7 @@ export const registerSettings = async function() {
|
||||
|
||||
});
|
||||
|
||||
game.settings.register(MODULE.moduleName, 'imageBrightness', {
|
||||
game.settings.register(moduleName, 'imageBrightness', {
|
||||
name: "MaterialDeck.Sett.ImageBrightness",
|
||||
hint: "MaterialDeck.Sett.ImageBrightnessHint",
|
||||
default: 50,
|
||||
@@ -127,7 +138,7 @@ export const registerSettings = async function() {
|
||||
|
||||
});
|
||||
|
||||
game.settings.register(MODULE.moduleName, 'nrOfConnMessages', {
|
||||
game.settings.register(moduleName, 'nrOfConnMessages', {
|
||||
name: "MaterialDeck.Sett.NrOfConnMessages",
|
||||
hint: "MaterialDeck.Sett.NrOfConnMessagesHint",
|
||||
default: 5,
|
||||
@@ -139,59 +150,62 @@ export const registerSettings = async function() {
|
||||
});
|
||||
|
||||
//Create the Help button
|
||||
game.settings.registerMenu(MODULE.moduleName, 'helpMenu',{
|
||||
game.settings.registerMenu(moduleName, 'helpMenu',{
|
||||
name: "MaterialDeck.Sett.Help",
|
||||
label: "MaterialDeck.Sett.Help",
|
||||
type: helpMenu,
|
||||
restricted: false
|
||||
});
|
||||
|
||||
game.settings.registerMenu(MODULE.moduleName, 'downloadUtility',{
|
||||
game.settings.registerMenu(moduleName, 'downloadUtility',{
|
||||
name: "MaterialDeck.DownloadUtility.Title",
|
||||
label: "MaterialDeck.DownloadUtility.Title",
|
||||
type: downloadUtility,
|
||||
restricted: false
|
||||
});
|
||||
|
||||
game.settings.registerMenu(MODULE.moduleName, 'deviceConfig',{
|
||||
game.settings.registerMenu(moduleName, 'deviceConfig',{
|
||||
name: "MaterialDeck.DeviceConfig.Title",
|
||||
label: "MaterialDeck.DeviceConfig.Title",
|
||||
type: deviceConfig,
|
||||
restricted: false
|
||||
});
|
||||
|
||||
game.settings.register(MODULE.moduleName, 'devices', {
|
||||
game.settings.register(moduleName, 'devices', {
|
||||
name: "devices",
|
||||
scope: "client",
|
||||
type: Object,
|
||||
config: false
|
||||
config: false,
|
||||
default: {}
|
||||
});
|
||||
|
||||
game.settings.registerMenu(MODULE.moduleName, 'permissionConfig',{
|
||||
game.settings.registerMenu(moduleName, 'permissionConfig',{
|
||||
name: "MaterialDeck.Sett.Permission",
|
||||
label: "MaterialDeck.Sett.Permission",
|
||||
type: userPermission,
|
||||
restricted: true
|
||||
});
|
||||
|
||||
game.settings.register(MODULE.moduleName, 'userPermission', {
|
||||
game.settings.register(moduleName, 'userPermission', {
|
||||
name: "userPermission",
|
||||
label: "",
|
||||
scope: "world",
|
||||
type: Object,
|
||||
config: false
|
||||
config: false,
|
||||
default: {}
|
||||
});
|
||||
|
||||
/**
|
||||
* Playlist soundboard
|
||||
*/
|
||||
game.settings.registerMenu(MODULE.moduleName, 'playlistConfigMenu',{
|
||||
game.settings.registerMenu(moduleName, 'playlistConfigMenu',{
|
||||
name: "MaterialDeck.Sett.PlaylistConfig",
|
||||
label: "MaterialDeck.Sett.PlaylistConfig",
|
||||
type: playlistConfigForm,
|
||||
restricted: false
|
||||
});
|
||||
|
||||
game.settings.register(MODULE.moduleName, 'playlists', {
|
||||
game.settings.register(moduleName, 'playlists', {
|
||||
name: "selectedPlaylists",
|
||||
scope: "world",
|
||||
type: Object,
|
||||
@@ -202,31 +216,33 @@ export const registerSettings = async function() {
|
||||
/**
|
||||
* Macro Board
|
||||
*/
|
||||
game.settings.registerMenu(MODULE.moduleName, 'macroConfigMenu',{
|
||||
game.settings.registerMenu(moduleName, 'macroConfigMenu',{
|
||||
name: "MaterialDeck.Sett.MacroConfig",
|
||||
label: "MaterialDeck.Sett.MacroConfig",
|
||||
type: macroConfigForm,
|
||||
restricted: false
|
||||
});
|
||||
|
||||
game.settings.register(MODULE.moduleName, 'macroSettings', {
|
||||
game.settings.register(moduleName, 'macroSettings', {
|
||||
name: "macroSettings",
|
||||
scope: "world",
|
||||
type: Object,
|
||||
config: false
|
||||
config: false,
|
||||
default: {}
|
||||
});
|
||||
|
||||
game.settings.register(MODULE.moduleName, 'macroArgs', {
|
||||
game.settings.register(moduleName, 'macroArgs', {
|
||||
name: "macroArgs",
|
||||
scope: "world",
|
||||
type: Object,
|
||||
config: false
|
||||
config: false,
|
||||
default: {}
|
||||
});
|
||||
|
||||
/**
|
||||
* Soundboard
|
||||
*/
|
||||
game.settings.register(MODULE.moduleName, 'soundboardSettings', {
|
||||
game.settings.register(moduleName, 'soundboardSettings', {
|
||||
name: "soundboardSettings",
|
||||
scope: "world",
|
||||
type: Object,
|
||||
@@ -234,15 +250,16 @@ export const registerSettings = async function() {
|
||||
config: false
|
||||
});
|
||||
|
||||
game.settings.registerMenu(MODULE.moduleName, 'soundboardConfigMenu',{
|
||||
game.settings.registerMenu(moduleName, 'soundboardConfigMenu',{
|
||||
name: "MaterialDeck.Sett.SoundboardConfig",
|
||||
label: "MaterialDeck.Sett.SoundboardConfig",
|
||||
type: soundboardConfigForm,
|
||||
restricted: false
|
||||
});
|
||||
|
||||
let permissionSettings = game.settings.get(MODULE.moduleName,'userPermission');
|
||||
if (permissionSettings == undefined || permissionSettings == null || MODULE.isEmpty(permissionSettings)) {
|
||||
let permissionSettings = game.settings.get(moduleName,'userPermission');
|
||||
|
||||
if (permissionSettings == undefined || permissionSettings == null || isEmpty(permissionSettings)) {
|
||||
permissionSettings = {
|
||||
enable: defaultEnable,
|
||||
permissions: defaultUserPermissions
|
||||
@@ -254,7 +271,7 @@ export const registerSettings = async function() {
|
||||
if (permissionSettings.permissions.MACRO.BY_NAME == undefined) permissionSettings.permissions.MACRO.BY_NAME = [false,false,true,true];
|
||||
}
|
||||
if (game.user.isGM)
|
||||
game.settings.set(MODULE.moduleName,'userPermission',permissionSettings);
|
||||
game.settings.set(moduleName,'userPermission',permissionSettings);
|
||||
}
|
||||
|
||||
|
||||
@@ -311,7 +328,7 @@ export class helpMenu extends FormApplication {
|
||||
*/
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
id: "userPermissionConfig",
|
||||
id: "materialDeck_userPermissionConfig",
|
||||
title: "Material Deck: "+game.i18n.localize("MaterialDeck.Sett.Permission"),
|
||||
template: "./modules/MaterialDeck/templates/userPermissionConfig.html",
|
||||
width: 660,
|
||||
@@ -324,8 +341,8 @@ export class helpMenu extends FormApplication {
|
||||
* Provide data to the template
|
||||
*/
|
||||
async getData() {
|
||||
let settings = game.settings.get(MODULE.moduleName,'userPermission');
|
||||
if (settings == undefined || settings == null || MODULE.isEmpty(settings)) {
|
||||
let settings = game.settings.get(moduleName,'userPermission');
|
||||
if (settings == undefined || settings == null || isEmpty(settings)) {
|
||||
settings = {
|
||||
enable: defaultEnable,
|
||||
permissions: defaultUserPermissions
|
||||
@@ -335,7 +352,12 @@ export class helpMenu extends FormApplication {
|
||||
const actions = Object.entries(duplicate(settings.permissions)).reduce((arr, e) => {
|
||||
const perms = Object.entries(duplicate(e[1])).reduce((arr, p) => {
|
||||
let perm = {};
|
||||
perm.roles = [p[1][0],p[1][1],p[1][2],p[1][3]]
|
||||
perm.roles = [
|
||||
{role:'player',en:p[1][0]},
|
||||
{role:'trusted',en:p[1][1]},
|
||||
{role:'assistent',en:p[1][2]},
|
||||
{role:'gm',en:p[1][3]}
|
||||
]
|
||||
perm.id = p[0];
|
||||
perm.label = game.i18n.localize("MaterialDeck.Perm."+e[0]+"."+p[0]+".label");
|
||||
perm.hint = game.i18n.localize("MaterialDeck.Perm."+e[0]+"."+p[0]+".hint");
|
||||
@@ -355,14 +377,21 @@ export class helpMenu extends FormApplication {
|
||||
if (actions[i].id == 'MOVE')
|
||||
actions.splice(i,1);
|
||||
}
|
||||
|
||||
const enable = [
|
||||
{role:'player',en:settings.enable[0]},
|
||||
{role:'trusted',en:settings.enable[1]},
|
||||
{role:'assistent',en:settings.enable[2]},
|
||||
{role:'gm',en:settings.enable[3]}
|
||||
]
|
||||
return {
|
||||
roles: Object.keys(CONST.USER_ROLES).reduce((obj, r) => {
|
||||
if ( r === "NONE" ) return obj;
|
||||
obj[r] = `USER.Role${r.titleCase()}`;
|
||||
return obj;
|
||||
}, {}),
|
||||
actions: actions,
|
||||
enable: settings.enable
|
||||
actions,
|
||||
enable
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,12 +401,28 @@ export class helpMenu extends FormApplication {
|
||||
* @param {*} formData
|
||||
*/
|
||||
async _updateObject(event, formData) {
|
||||
let permissions = expandObject(formData);
|
||||
let settings = {};
|
||||
settings.enable = permissions.ENABLE;
|
||||
let permissions = expandObject(formData);
|
||||
|
||||
for (const [key, value] of Object.entries(permissions)) {
|
||||
const val = value;
|
||||
let conf = {};
|
||||
if (key == 'ENABLE') {
|
||||
settings.enable = [value.player, value.trusted, value.assistent, value.gm];
|
||||
}
|
||||
else {
|
||||
conf = {};
|
||||
for (const [key, value] of Object.entries(val)) {
|
||||
const arr = [value.player, value.trusted, value.assistent, value.gm];
|
||||
conf[key] = arr;
|
||||
}
|
||||
}
|
||||
permissions[key] = conf;
|
||||
}
|
||||
|
||||
delete permissions.ENABLE;
|
||||
settings.permissions = permissions;
|
||||
// game.settings.set(MODULE.moduleName,'userPermission',settings);
|
||||
game.settings.set(moduleName,'userPermission',settings);
|
||||
}
|
||||
|
||||
async activateListeners(html) {
|
||||
@@ -396,7 +441,7 @@ export class helpMenu extends FormApplication {
|
||||
enable: defaultEnable,
|
||||
permissions: defaultUserPermissions
|
||||
}
|
||||
await game.settings.set(MODULE.moduleName,'userPermission',settings);
|
||||
await game.settings.set(moduleName,'userPermission',settings);
|
||||
this.render();
|
||||
ui.notifications.info(game.i18n.localize("MaterialDeck.Perm.DefaultNotification"));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as MODULE from "../MaterialDeck.js";
|
||||
import { moduleName, sendWS, tokenControl, macroControl, combatTracker, playlistControl, soundboard, otherControls, externalModules, sceneControl } from "../MaterialDeck.js";
|
||||
|
||||
export class StreamDeck{
|
||||
constructor() {
|
||||
@@ -90,14 +90,14 @@ export class StreamDeck{
|
||||
}
|
||||
|
||||
if (this.getActive(action) == false){
|
||||
if (action == 'token') MODULE.tokenControl.active = false;
|
||||
else if (action == 'macro') MODULE.macroControl.active = false;
|
||||
else if (action == 'combattracker') MODULE.combatTracker.active = false;
|
||||
else if (action == 'playlist') MODULE.playlistControl.active = false;
|
||||
else if (action == 'soundboard') MODULE.soundboard.active = false;
|
||||
else if (action == 'other') MODULE.otherControls.active = false;
|
||||
else if (action == 'external') MODULE.externalModules.active = false;
|
||||
else if (action == 'scene') MODULE.sceneControl.active = false;
|
||||
if (action == 'token') tokenControl.active = false;
|
||||
else if (action == 'macro') macroControl.active = false;
|
||||
else if (action == 'combattracker') combatTracker.active = false;
|
||||
else if (action == 'playlist') playlistControl.active = false;
|
||||
else if (action == 'soundboard') soundboard.active = false;
|
||||
else if (action == 'other') otherControls.active = false;
|
||||
else if (action == 'external') externalModules.active = false;
|
||||
else if (action == 'scene') sceneControl.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ export class StreamDeck{
|
||||
target: 0
|
||||
}
|
||||
};
|
||||
MODULE.sendWS(JSON.stringify(msg));
|
||||
sendWS(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
setColor(context,color = '#000000'){
|
||||
@@ -216,7 +216,7 @@ export class StreamDeck{
|
||||
format: 'color',
|
||||
background: color
|
||||
};
|
||||
MODULE.sendWS(JSON.stringify(msg));
|
||||
sendWS(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
setImage(image,context,device,nr,id){
|
||||
@@ -232,7 +232,7 @@ export class StreamDeck{
|
||||
target: 0
|
||||
}
|
||||
};
|
||||
MODULE.sendWS(JSON.stringify(json));
|
||||
sendWS(JSON.stringify(json));
|
||||
}
|
||||
|
||||
setBufferImage(context,device,nr,id){
|
||||
@@ -247,7 +247,7 @@ export class StreamDeck{
|
||||
target: 0
|
||||
}
|
||||
};
|
||||
MODULE.sendWS(JSON.stringify(json));
|
||||
sendWS(JSON.stringify(json));
|
||||
}
|
||||
|
||||
setIcon(context,device,src='',options = {}){
|
||||
@@ -301,6 +301,8 @@ export class StreamDeck{
|
||||
let format = split[split.length-1].split('?')[0];
|
||||
split = split[0].split(' ');
|
||||
if (split[0] == 'fas' || split[0] == 'far' || split[0] == 'fal' || split[0] == 'fad') format = 'icon';
|
||||
let split2 = split[0].split('-');
|
||||
if (split2[0] == 'fa') format = 'icon';
|
||||
let msg = {
|
||||
target: "SD",
|
||||
event: 'setIcon',
|
||||
@@ -326,7 +328,7 @@ export class StreamDeck{
|
||||
action: action,
|
||||
state: state
|
||||
};
|
||||
MODULE.sendWS(JSON.stringify(msg));
|
||||
sendWS(JSON.stringify(msg));
|
||||
}
|
||||
|
||||
setProfile(action,device){
|
||||
@@ -343,7 +345,7 @@ export class StreamDeck{
|
||||
profile: profile
|
||||
}
|
||||
};
|
||||
MODULE.sendWS(JSON.stringify(json));
|
||||
sendWS(JSON.stringify(json));
|
||||
}
|
||||
|
||||
setPluginId(id){
|
||||
@@ -439,7 +441,7 @@ export class StreamDeck{
|
||||
img.onload = () => {
|
||||
if (format == 'color') ctx.filter = "opacity(0)";
|
||||
|
||||
if (data.overlay == true) ctx.filter = "brightness(" + game.settings.get(MODULE.moduleName,'imageBrightness') + "%)";
|
||||
if (data.overlay == true) ctx.filter = "brightness(" + game.settings.get(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;
|
||||
@@ -564,7 +566,7 @@ export class StreamDeck{
|
||||
|
||||
addToImageBuffer(img,data){
|
||||
const id = this.getImageBufferId(data);
|
||||
const maxBufferSize = game.settings.get(MODULE.moduleName,'imageBuffer');
|
||||
const maxBufferSize = game.settings.get(moduleName,'imageBuffer');
|
||||
if (maxBufferSize == 0) return false;
|
||||
if (this.imageBufferCounter > maxBufferSize) this.imageBufferCounter = 0;
|
||||
|
||||
@@ -581,7 +583,7 @@ export class StreamDeck{
|
||||
}
|
||||
|
||||
checkImageBuffer(data){
|
||||
if (game.settings.get(MODULE.moduleName,'imageBuffer') == 0) return false;
|
||||
if (game.settings.get(moduleName,'imageBuffer') == 0) return false;
|
||||
const id = this.getImageBufferId(data);
|
||||
|
||||
for (let i=0; i<this.imageBuffer.length; i++){
|
||||
|
||||
@@ -2,11 +2,19 @@ import {compatibleCore} from "../misc.js";
|
||||
|
||||
export class demonlord{
|
||||
constructor(){
|
||||
console.log("Material Deck: Using system 'Shadow of the Demon Lord'");
|
||||
}
|
||||
|
||||
getActorData(token) {
|
||||
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
|
||||
}
|
||||
|
||||
getItemData(item) {
|
||||
return compatibleCore('10.0') ? item.system : item.data.data;
|
||||
}
|
||||
|
||||
getHP(token) {
|
||||
const hp = token.actor.data.data.characteristics.health;
|
||||
const hp = this.getActorData(token).characteristics.health;
|
||||
return {
|
||||
value: hp.value,
|
||||
max: hp.max
|
||||
@@ -18,7 +26,7 @@ export class demonlord{
|
||||
}
|
||||
|
||||
getAC(token) {
|
||||
return token.actor.data.data.characteristics.defense;
|
||||
return this.getActorData(token).characteristics.defense;
|
||||
}
|
||||
|
||||
getShieldHP(token) {
|
||||
@@ -26,11 +34,11 @@ export class demonlord{
|
||||
}
|
||||
|
||||
getSpeed(token) {
|
||||
return token.actor.data.data.characteristics.speed;
|
||||
return this.getActorData(token).characteristics.speed;
|
||||
}
|
||||
|
||||
getInitiative(token) {
|
||||
return token.actor.data.data.fastturn ? "FAST" : "SLOW";
|
||||
return this.getActorData(token).fastturn ? "FAST" : "SLOW";
|
||||
}
|
||||
|
||||
toggleInitiative(token) {
|
||||
@@ -50,12 +58,12 @@ export class demonlord{
|
||||
|
||||
getAbility(token, ability) {
|
||||
if (ability == undefined) ability = 'strength';
|
||||
return token.actor.data.data.attributes?.[ability].value;
|
||||
return this.getActorData(token).attributes?.[ability].value;
|
||||
}
|
||||
|
||||
getAbilityModifier(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
let val = token.actor.data.data.attributes?.[ability].modifier;
|
||||
let val = this.getActorData(token).attributes?.[ability].modifier;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
@@ -65,7 +73,7 @@ export class demonlord{
|
||||
|
||||
getSkill(token, skill) {
|
||||
if (skill == undefined) skill = 'acr';
|
||||
const val = token.actor.data.data.skills?.[skill].total;
|
||||
const val = this.getActorData(token).skills?.[skill].total;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
@@ -114,7 +122,7 @@ export class demonlord{
|
||||
}
|
||||
|
||||
getItemUses(item) {
|
||||
return {available: item.data.data.quantity};
|
||||
return {available: getItemData(item).quantity};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,7 +132,7 @@ export class demonlord{
|
||||
if (level == undefined) level = 'any';
|
||||
const allItems = token.actor.items;
|
||||
if (level == 'any') return allItems.filter(i => i.type == 'spell')
|
||||
else return allItems.filter(i => i.type == 'spell' && i.data.data.rank == level)
|
||||
else return allItems.filter(i => i.type == 'spell' && getItemData(i).rank == level)
|
||||
}
|
||||
|
||||
getSpellUses(token,level,item) {
|
||||
|
||||
@@ -2,11 +2,19 @@ import {compatibleCore} from "../misc.js";
|
||||
|
||||
export class dnd35e{
|
||||
constructor(){
|
||||
console.log("Material Deck: Using system 'Dungeons & Dragons 3.5e'/'Pathfinder 1e'");
|
||||
}
|
||||
|
||||
getActorData(token) {
|
||||
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
|
||||
}
|
||||
|
||||
getItemData(item) {
|
||||
return compatibleCore('10.0') ? item.system : item.data.data;
|
||||
}
|
||||
|
||||
getHP(token) {
|
||||
const hp = token.actor.data.data.attributes.hp;
|
||||
const hp = this.getActorData(token).attributes.hp;
|
||||
return {
|
||||
value: hp.value,
|
||||
max: hp.max
|
||||
@@ -14,7 +22,7 @@ export class dnd35e{
|
||||
}
|
||||
|
||||
getTempHP(token) {
|
||||
const hp = token.actor.data.data.attributes.hp;
|
||||
const hp = this.getActorData(token).attributes.hp;
|
||||
return {
|
||||
value: (hp.temp == null) ? 0 : hp.temp,
|
||||
max: (hp.tempmax == null) ? 0 : hp.tempmax
|
||||
@@ -22,7 +30,7 @@ export class dnd35e{
|
||||
}
|
||||
|
||||
getAC(token) {
|
||||
return token.actor.data.data.attributes.ac.normal.total;
|
||||
return this.getActorData(token).attributes.ac.normal.total;
|
||||
}
|
||||
|
||||
getShieldHP(token) {
|
||||
@@ -30,7 +38,7 @@ export class dnd35e{
|
||||
}
|
||||
|
||||
getSpeed(token) {
|
||||
const movement = token.actor.data.data.attributes.speed;
|
||||
const movement = this.getActorData(token).attributes.speed;
|
||||
let speed = "";
|
||||
if (movement.burrow.total > 0) speed += `Burrow: ${movement.burrow.total}Ft`;
|
||||
if (movement.climb.total > 0) {
|
||||
@@ -53,7 +61,7 @@ export class dnd35e{
|
||||
}
|
||||
|
||||
getInitiative(token) {
|
||||
let initiative = token.actor.data.data.attributes.init.total;
|
||||
let initiative = this.getActorData(token).attributes.init.total;
|
||||
return (initiative >= 0) ? `+${initiative}` : initiative;
|
||||
}
|
||||
|
||||
@@ -71,29 +79,29 @@ export class dnd35e{
|
||||
|
||||
getAbility(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
return token.actor.data.data.abilities?.[ability].value;
|
||||
return this.getActorData(token).abilities?.[ability].value;
|
||||
}
|
||||
|
||||
getAbilityModifier(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
let val = token.actor.data.data.abilities?.[ability].mod;
|
||||
let val = this.getActorData(token).abilities?.[ability].mod;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getAbilitySave(token, ability) {
|
||||
if (ability == undefined) ability = 'fort';
|
||||
let val = token.actor.data.data.attributes.savingThrows?.[ability].total;
|
||||
let val = this.getActorData(token).attributes.savingThrows?.[ability].total;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getSkill(token, skill) {
|
||||
if (skill == undefined) skill = 'apr';
|
||||
const val = token.actor.data.data.skills?.[skill].mod;
|
||||
const val = this.getActorData(token).skills?.[skill].mod;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getProficiency(token) {
|
||||
const val = token.actor.data.data.attributes.prof;
|
||||
const val = this.getActorData(token).attributes.prof;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
@@ -133,7 +141,10 @@ export class dnd35e{
|
||||
if (roll == 'ability') token.actor.rollAbilityTest(ability,options);
|
||||
else if (roll == 'save') token.actor.rollSavingThrow(save, null, null,options);
|
||||
else if (roll == 'skill') token.actor.rollSkill(skill,options);
|
||||
else if (roll == 'initiative') token.actor.rollInitiative(options);
|
||||
else if (roll == 'initiative') {
|
||||
options.rerollInitiative = true;
|
||||
token.actor.rollInitiative(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);
|
||||
@@ -147,16 +158,16 @@ export class dnd35e{
|
||||
if (itemType == undefined) itemType = 'any';
|
||||
const allItems = token.actor.items;
|
||||
if (itemType == 'any') return allItems.filter(i => i.type == 'weapon' || i.type == 'equipment' || i.type == 'consumable' || i.type == 'loot' || i.type == 'container');
|
||||
else if (game.system.id == 'D35E' && itemType == 'container') return allItems.filter(i => i.type == 'loot' && i.data.data.subType == itemType);
|
||||
else if (game.system.id == 'D35E' && itemType == 'container') return allItems.filter(i => i.type == 'loot' && this.getItemData(i).subType == itemType);
|
||||
else {
|
||||
if (itemType == 'gear' || itemType == 'ammo' || itemType == 'misc' || itemType == 'tradeGoods')
|
||||
return allItems.filter(i => i.type == 'loot' && i.data.data.subType == itemType);
|
||||
return allItems.filter(i => i.type == 'loot' && this.getItemData(i).subType == itemType);
|
||||
else return allItems.filter(i => i.type == itemType);
|
||||
}
|
||||
}
|
||||
|
||||
getItemUses(item) {
|
||||
return {available: item.data.data.quantity};
|
||||
return {available: this.getItemData(item).quantity};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,10 +181,10 @@ export class dnd35e{
|
||||
}
|
||||
|
||||
getFeatureUses(item) {
|
||||
if (item.data.type == 'class') return {available: item.data.data.levels};
|
||||
if (item.data.type == 'class') return {available: this.getItemData(item).levels};
|
||||
else return {
|
||||
available: item.data.data.uses.value,
|
||||
maximum: item.data.data.uses.max
|
||||
available: this.getItemData(item).uses.value,
|
||||
maximum: this.getItemData(item).uses.max
|
||||
};
|
||||
}
|
||||
|
||||
@@ -184,12 +195,12 @@ export class dnd35e{
|
||||
if (level == undefined) level = 'any';
|
||||
const allItems = token.actor.items;
|
||||
if (level == 'any') return allItems.filter(i => i.type == 'spell')
|
||||
else return allItems.filter(i => i.type == 'spell' && i.data.data.level == level)
|
||||
else return allItems.filter(i => i.type == 'spell' && this.getItemData(i).level == level)
|
||||
}
|
||||
|
||||
getSpellUses(token,level,item) {
|
||||
if (level == undefined) level = 'any';
|
||||
if (item.data.data.level == 0) return;
|
||||
if (this.getItemData(item).level == 0) return;
|
||||
return {
|
||||
available: item.charges,
|
||||
maximum: item.maxCharges
|
||||
|
||||
@@ -9,11 +9,19 @@ const proficiencyColors = {
|
||||
|
||||
export class dnd5e{
|
||||
constructor(){
|
||||
console.log("Material Deck: Using system 'Dungeons & Dragons 5e'");
|
||||
}
|
||||
|
||||
getActorData(token) {
|
||||
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
|
||||
}
|
||||
|
||||
getItemData(item) {
|
||||
return compatibleCore('10.0') ? item.system : item.data.data;
|
||||
}
|
||||
|
||||
getHP(token) {
|
||||
const hp = token.actor.data.data.attributes.hp;
|
||||
const hp = this.getActorData(token).attributes.hp;
|
||||
return {
|
||||
value: hp.value,
|
||||
max: hp.max
|
||||
@@ -21,7 +29,7 @@ export class dnd5e{
|
||||
}
|
||||
|
||||
getTempHP(token) {
|
||||
const hp = token.actor.data.data.attributes.hp;
|
||||
const hp = this.getActorData(token).attributes.hp;
|
||||
return {
|
||||
value: (hp.temp == null) ? 0 : hp.temp,
|
||||
max: (hp.tempmax == null) ? 0 : hp.tempmax
|
||||
@@ -29,7 +37,7 @@ export class dnd5e{
|
||||
}
|
||||
|
||||
getAC(token) {
|
||||
return token.actor.data.data.attributes.ac.value;
|
||||
return this.getActorData(token).attributes.ac.value;
|
||||
}
|
||||
|
||||
getShieldHP(token) {
|
||||
@@ -37,9 +45,9 @@ export class dnd5e{
|
||||
}
|
||||
|
||||
getSpeed(token) {
|
||||
const movement = token.actor.data.data.attributes.movement;
|
||||
const movement = this.getActorData(token).attributes.movement;
|
||||
let speed = "";
|
||||
if (movement != undefined){
|
||||
|
||||
if (movement.burrow > 0) speed += `${game.i18n.localize("DND5E.MovementBurrow")}: ${movement.burrow + movement.units}`;
|
||||
if (movement.climb > 0) {
|
||||
if (speed.length > 0) speed += '\n';
|
||||
@@ -61,17 +69,12 @@ export class dnd5e{
|
||||
if (speed.length > 0) speed += '\n';
|
||||
speed += `${game.i18n.localize("DND5E.MovementWalk")}: ${movement.walk + movement.units}`;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const spd = token.actor.data.data.attributes.speed;
|
||||
speed = spd.value;
|
||||
if (spd.special.length > 0) speed + "\n" + spd.special;
|
||||
}
|
||||
|
||||
return speed;
|
||||
}
|
||||
|
||||
getInitiative(token) {
|
||||
let initiative = token.actor.data.data.attributes.init.total;
|
||||
let initiative = this.getActorData(token).attributes.init.total;
|
||||
return (initiative >= 0) ? `+${initiative}` : initiative;
|
||||
}
|
||||
|
||||
@@ -80,38 +83,38 @@ export class dnd5e{
|
||||
}
|
||||
|
||||
getPassivePerception(token) {
|
||||
return token.actor.data.data.skills.prc.passive;
|
||||
return this.getActorData(token).skills.prc.passive;
|
||||
}
|
||||
|
||||
getPassiveInvestigation(token) {
|
||||
return token.actor.data.data.skills.inv.passive;
|
||||
return this.getActorData(token).skills.inv.passive;
|
||||
}
|
||||
|
||||
getAbility(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
return token.actor.data.data.abilities?.[ability].value;
|
||||
return this.getActorData(token).abilities?.[ability].value;
|
||||
}
|
||||
|
||||
getAbilityModifier(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
let val = token.actor.data.data.abilities?.[ability].mod;
|
||||
let val = this.getActorData(token).abilities?.[ability].mod;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getAbilitySave(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
let val = token.actor.data.data.abilities?.[ability].save;
|
||||
let val = this.getActorData(token).abilities?.[ability].save;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getSkill(token, skill) {
|
||||
if (skill == undefined) skill = 'acr';
|
||||
const val = token.actor.data.data.skills?.[skill].total;
|
||||
const val = this.getActorData(token).skills?.[skill].total;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getProficiency(token) {
|
||||
const val = token.actor.data.data.attributes.prof;
|
||||
const val = this.getActorData(token).attributes.prof;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
@@ -151,7 +154,10 @@ export class dnd5e{
|
||||
if (roll == 'ability') token.actor.rollAbilityTest(ability,options);
|
||||
else if (roll == 'save') token.actor.rollAbilitySave(save,options);
|
||||
else if (roll == 'skill') token.actor.rollSkill(skill,options);
|
||||
else if (roll == 'initiative') token.actor.rollInitiative(options);
|
||||
else if (roll == 'initiative') {
|
||||
options.rerollInitiative = true;
|
||||
token.actor.rollInitiative(options);
|
||||
}
|
||||
else if (roll == 'deathSave') token.actor.rollDeathSave(options);
|
||||
}
|
||||
|
||||
@@ -166,7 +172,7 @@ export class dnd5e{
|
||||
}
|
||||
|
||||
getItemUses(item) {
|
||||
return {available: item.data.data.quantity};
|
||||
return {available: this.getItemData(item).quantity};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,15 +181,18 @@ export class dnd5e{
|
||||
getFeatures(token,featureType) {
|
||||
if (featureType == undefined) featureType = 'any';
|
||||
const allItems = token.actor.items;
|
||||
|
||||
if (featureType == 'any') return allItems.filter(i => i.type == 'class' || i.type == 'feat')
|
||||
else if (featureType == 'activeAbilities') return allItems.filter(i => i.type == 'feat' && i.labels.featType == 'Action')
|
||||
else if (featureType == 'passiveAbilities') return allItems.filter(i => i.type == 'feat' && i.labels.featType == 'Passive')
|
||||
else return allItems.filter(i => i.type == featureType)
|
||||
}
|
||||
|
||||
getFeatureUses(item) {
|
||||
if (item.data.type == 'class') return {available: item.data.data.levels};
|
||||
if (item.type == 'class') return {available: this.getItemData(item).levels};
|
||||
else return {
|
||||
available: item.data.data.uses.value,
|
||||
maximum: item.data.data.uses.max
|
||||
available: this.getItemData(item).uses.value,
|
||||
maximum: this.getItemData(item).uses.max
|
||||
};
|
||||
}
|
||||
|
||||
@@ -194,33 +203,65 @@ export class dnd5e{
|
||||
if (level == undefined) level = 'any';
|
||||
const allItems = token.actor.items;
|
||||
if (level == 'any') return allItems.filter(i => i.type == 'spell')
|
||||
else return allItems.filter(i => i.type == 'spell' && i.data.data.level == level)
|
||||
else return allItems.filter(i => i.type == 'spell' && this.getItemData(i).level == level)
|
||||
}
|
||||
|
||||
getSpellUses(token,level,item) {
|
||||
if (level == undefined) level = 'any';
|
||||
if (item.data.data.level == 0) return;
|
||||
if (level == undefined || level == 'any') level = this.getItemData(item).level;
|
||||
if (this.getItemData(item).level == 0) return;
|
||||
return {
|
||||
available: token.actor.data.data.spells?.[`spell${level}`].value,
|
||||
maximum: token.actor.data.data.spells?.[`spell${level}`].max
|
||||
available: this.getActorData(token).spells?.[`spell${level}`].value,
|
||||
maximum: this.getActorData(token).spells?.[`spell${level}`].max
|
||||
}
|
||||
}
|
||||
|
||||
rollItem(item) {
|
||||
return item.roll()
|
||||
rollItem(item, settings, rollOption) {
|
||||
let options = {
|
||||
fastForward: rollOption != 'dialog',
|
||||
advantage: rollOption == 'advantage',
|
||||
disadvantage: rollOption == 'disadvantage'
|
||||
}
|
||||
if (settings.inventoryType == 'weapon') {
|
||||
if (settings.weaponRollMode == 'attack') {
|
||||
options.fastForward = true;
|
||||
return item.rollAttack(options);
|
||||
}
|
||||
else if (settings.weaponRollMode == 'damage' || settings.weaponRollMode == 'versatile') {
|
||||
options.fastForward = true;
|
||||
return item.rollDamage({
|
||||
options,
|
||||
critical:false,
|
||||
versatile: settings.weaponRollMode == 'versatile'
|
||||
});
|
||||
}
|
||||
else if (settings.weaponRollMode == 'damageCrit' || settings.weaponRollMode == 'versatileCrit') {
|
||||
options.fastForward = true;
|
||||
return item.rollDamage({
|
||||
options,
|
||||
critical:true,
|
||||
versatile: settings.weaponRollMode == 'versatile' || settings.weaponRollMode == 'versatileCrit'
|
||||
});
|
||||
}
|
||||
else if (settings.weaponRollMode == 'otherFormula') {
|
||||
return item.rollFormula(options);
|
||||
}
|
||||
}
|
||||
|
||||
if (compatibleCore('10.0')) item.use(options)
|
||||
else item.roll(options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Ring Colors
|
||||
*/
|
||||
getSkillRingColor(token, skill) {
|
||||
const profLevel = token.actor.data.data?.skills[skill]?.proficient;
|
||||
const profLevel = this.getActorData(token).skills[skill]?.proficient;
|
||||
if (profLevel == undefined) return;
|
||||
return proficiencyColors?.[profLevel];
|
||||
}
|
||||
|
||||
getSaveRingColor(token, save) {
|
||||
const profLevel = token.actor.data.data?.abilities[save]?.proficient;
|
||||
const profLevel = this.getActorData(token).abilities[save]?.proficient;
|
||||
if (profLevel == undefined) return;
|
||||
return proficiencyColors?.[profLevel];
|
||||
}
|
||||
|
||||
@@ -2,29 +2,35 @@ import {compatibleCore} from "../misc.js";
|
||||
|
||||
export class forbiddenlands{
|
||||
constructor(){
|
||||
console.log("Material Deck: Using system 'Forbidden Lands'");
|
||||
}
|
||||
|
||||
getActorData(token) {
|
||||
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
|
||||
}
|
||||
|
||||
getItemData(item) {
|
||||
return compatibleCore('10.0') ? item.system : item.data.data;
|
||||
}
|
||||
|
||||
getHP(token) {
|
||||
const hp = token.actor.data.data.attribute.strength;
|
||||
const hp = this.getActorData(token).attribute.strength;
|
||||
return {
|
||||
value: hp.value,
|
||||
max: hp.max
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getAgility(token) {
|
||||
const agility = token.actor.data.data.attribute.agility;
|
||||
const agility = this.getActorData(token).attribute.agility;
|
||||
return {
|
||||
value: agility.value,
|
||||
max: agility.max
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getWits(token) {
|
||||
const wits = token.actor.data.data.attribute.wits;
|
||||
const wits = this.getActorData(token).attribute.wits;
|
||||
return {
|
||||
value: wits.value,
|
||||
max: wits.max
|
||||
@@ -32,7 +38,7 @@ export class forbiddenlands{
|
||||
}
|
||||
|
||||
getEmpathy(token) {
|
||||
const empathy = token.actor.data.data.attribute.empathy;
|
||||
const empathy = this.getActorData(token).attribute.empathy;
|
||||
return {
|
||||
value: empathy.value,
|
||||
max: empathy.max
|
||||
@@ -40,7 +46,7 @@ export class forbiddenlands{
|
||||
}
|
||||
|
||||
getWillPower(token) {
|
||||
const wp = token.actor.data.data.bio.willpower;
|
||||
const wp = this.getActorData(token).bio.willpower;
|
||||
return {
|
||||
value: wp.value,
|
||||
max: wp.max
|
||||
@@ -49,15 +55,9 @@ export class forbiddenlands{
|
||||
|
||||
getTempHP(token) {
|
||||
return 0;
|
||||
const hp = token.actor.data.data.attributes.hp;
|
||||
return {
|
||||
value: (hp.temp == null) ? 0 : hp.temp,
|
||||
max: (hp.tempmax == null) ? 0 : hp.tempmax
|
||||
}
|
||||
}
|
||||
|
||||
getAC(token) {
|
||||
|
||||
const totalArmor = token.actor.itemTypes.armor.reduce((sum, armor) => {
|
||||
if (armor.itemProperties.part === "shield") return sum;
|
||||
const value = armor.itemProperties.bonus.value;
|
||||
@@ -76,8 +76,6 @@ export class forbiddenlands{
|
||||
|
||||
getInitiative(token) {
|
||||
return 0;
|
||||
let initiative = token.actor.data.data.attributes.init.total;
|
||||
return (initiative >= 0) ? `+${initiative}` : initiative;
|
||||
}
|
||||
|
||||
toggleInitiative(token) {
|
||||
@@ -86,17 +84,15 @@ export class forbiddenlands{
|
||||
|
||||
getPassivePerception(token) {
|
||||
return 0;
|
||||
return token.actor.data.data.skills.prc.passive;
|
||||
}
|
||||
|
||||
getPassiveInvestigation(token) {
|
||||
return;
|
||||
return token.actor.data.data.skills.inv.passive;
|
||||
}
|
||||
|
||||
getAbility(token, ability) {
|
||||
if (ability == undefined) ability = 'strength';
|
||||
return token.actor.data.data.attribute?.[ability].value;
|
||||
return this.getActorData(token).attribute?.[ability].value;
|
||||
}
|
||||
|
||||
getAbilityModifier(token, ability) {
|
||||
@@ -116,8 +112,6 @@ export class forbiddenlands{
|
||||
|
||||
getProficiency(token) {
|
||||
return;
|
||||
const val = token.actor.data.data.attributes.prof;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getConditionIcon(condition) {
|
||||
@@ -181,9 +175,9 @@ export class forbiddenlands{
|
||||
|
||||
getItemUses(item) {
|
||||
if (item.type == 'monsterAttack') return;
|
||||
if (item.type == 'rawMaterial') return {available: item.data.data.quantity};
|
||||
return {available: item.data.data.bonus.value,
|
||||
maximum: item.data.data.bonus.max};
|
||||
if (item.type == 'rawMaterial') return {available: this.getItemData(item).quantity};
|
||||
return {available: this.getItemData(item).bonus.value,
|
||||
maximum: this.getItemData(item).bonus.max};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,10 +191,10 @@ export class forbiddenlands{
|
||||
}
|
||||
|
||||
getFeatureUses(item) {
|
||||
if (item.data.type == 'class') return {available: item.data.data.levels};
|
||||
if (item.data.type == 'class') return {available: this.getItemData(item).levels};
|
||||
else return {
|
||||
available: item.data.data.uses.value,
|
||||
maximum: item.data.data.uses.max
|
||||
available: this.getItemData(item).uses.value,
|
||||
maximum: this.getItemData(item).uses.max
|
||||
};
|
||||
}
|
||||
|
||||
@@ -211,15 +205,15 @@ export class forbiddenlands{
|
||||
if (level == undefined) level = 'any';
|
||||
const allItems = token.actor.items;
|
||||
if (level == 'any') return allItems.filter(i => i.type == 'spell')
|
||||
else return allItems.filter(i => i.type == 'spell' && i.data.data.level == level)
|
||||
else return allItems.filter(i => i.type == 'spell' && this.getItemData(i).level == level)
|
||||
}
|
||||
|
||||
getSpellUses(token,level,item) {
|
||||
if (level == undefined) level = 'any';
|
||||
if (item.data.data.level == 0) return;
|
||||
if (this.getItemData(item).level == 0) return;
|
||||
return {
|
||||
available: token.actor.data.data.spells?.[`spell${level}`].value,
|
||||
maximum: token.actor.data.data.spells?.[`spell${level}`].max
|
||||
available: this.getActorData(token).spells?.[`spell${level}`].value,
|
||||
maximum: this.getActorData(token).spells?.[`spell${level}`].max
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {compatibleCore} from "../misc.js";
|
||||
import { otherControls } from "../../MaterialDeck.js";
|
||||
import { compatibleCore } from "../misc.js";
|
||||
|
||||
const limitedSheets = ['loot', 'vehicle'];
|
||||
const proficiencyColors =
|
||||
@@ -14,11 +14,19 @@ const proficiencyColors =
|
||||
export class pf2e{
|
||||
|
||||
constructor(){
|
||||
|
||||
console.log("Material Deck: Using system 'Pathfinder 2e'");
|
||||
}
|
||||
|
||||
tokenSpellData = new Map();
|
||||
|
||||
getActorData(token) {
|
||||
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
|
||||
}
|
||||
|
||||
getItemData(item) {
|
||||
return compatibleCore('10.0') ? item.system : item.data.data;
|
||||
}
|
||||
|
||||
getHP(token) {
|
||||
const hp = token.actor.attributes?.hp;
|
||||
return {
|
||||
@@ -48,7 +56,7 @@ export class pf2e{
|
||||
getSpeed(token) {
|
||||
if (this.isLimitedSheet(token.actor) || token.actor.type == 'hazard') {
|
||||
if (token.actor.type == 'vehicle') {
|
||||
return token.actor.data.data.details.speed;
|
||||
return this.getActorData(token).details.speed;
|
||||
} else return '';
|
||||
}
|
||||
let speed = `${token.actor.attributes.speed?.total}'`;
|
||||
@@ -117,7 +125,7 @@ export class pf2e{
|
||||
|
||||
findSave(token, ability) {
|
||||
if (this.isLimitedSheet(token.actor)) return;
|
||||
return token.actor.data.data.saves?.[ability];
|
||||
return this.getActorData(token).saves?.[ability];
|
||||
}
|
||||
|
||||
fixSave(ability) {
|
||||
@@ -151,12 +159,12 @@ export class pf2e{
|
||||
return;
|
||||
}
|
||||
}
|
||||
return token.actor.data.data.skills?.[skill];
|
||||
return this.getActorData(token).skills?.[skill];
|
||||
}
|
||||
|
||||
getLoreSkills(token) {
|
||||
if (this.isLimitedSheet(token.actor)) return [];
|
||||
const skills = token.actor.data.data.skills;
|
||||
const skills = this.getActorData(token).skills;
|
||||
return Object.keys(skills).map(key => skills[key]).filter(s => s.lore == true);
|
||||
}
|
||||
|
||||
@@ -270,7 +278,7 @@ export class pf2e{
|
||||
return;
|
||||
}
|
||||
}
|
||||
let skillName = token.actor.data.data.skills?.[skill].name;
|
||||
let skillName = this.getActorData(token).skills?.[skill].name;
|
||||
skillName = skillName.charAt(0).toUpperCase() + skillName.slice(1);
|
||||
this.checkRoll(`Skill Check: ${skillName}`, token.actor.skills?.[skill], 'skill-check', token.actor);
|
||||
}
|
||||
@@ -294,7 +302,7 @@ export class pf2e{
|
||||
}
|
||||
|
||||
getItemUses(item) {
|
||||
return {available: item.quantity.value};
|
||||
return {available: item.quantity};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,16 +312,25 @@ export class pf2e{
|
||||
if (this.isLimitedSheet(token.actor)) return [];
|
||||
if (featureType == undefined) featureType = 'any';
|
||||
const allItems = token.actor.items;
|
||||
if (featureType == 'any') return allItems.filter(i => i.type == 'ancestry' || i.type == 'background' || i.type == 'class' || i.type == 'feat' || i.type == 'action');
|
||||
if (featureType == 'any') return allItems.filter(i => i.type == 'ancestry' || i.type == 'background' || i.type == 'class' || i.type == 'feat' || i.type == 'action' || i.type == 'heritage' || i.type == 'deity' || i.type == '');
|
||||
if (featureType == 'feat-any') return allItems.filter(i => i.type == 'feat');
|
||||
if (featureType == 'ancestryfeature') return allItems.filter(i => i.type == 'feat' && i.featType == 'ancestryfeature');
|
||||
if (featureType == 'classfeature') return allItems.filter(i => i.type == 'feat' && i.featType == 'classfeature');
|
||||
if (featureType == 'feat-anc') return allItems.filter(i => i.type == 'feat' && i.featType == 'ancestry');
|
||||
if (featureType == 'feat-arc') return allItems.filter(i => i.type == 'feat' && i.featType == 'archetype' && i.name.indexOf('Dedication') < 0);
|
||||
if (featureType == 'feat-ded') return allItems.filter(i => i.type == 'feat' && i.featType == 'archetype' && i.name.indexOf('Dedication') > 0);
|
||||
if (featureType == 'feat-cla') return allItems.filter(i => i.type == 'feat' && i.featType == 'class');
|
||||
if (featureType == 'feat-gen') return allItems.filter(i => i.type == 'feat' && i.featType == 'general');
|
||||
if (featureType == 'feat-ski') return allItems.filter(i => i.type == 'feat' && i.featType == 'skill');
|
||||
if (featureType == 'action-any') return allItems.filter(i => i.type == 'action');
|
||||
if (featureType == 'action-def') return allItems.filter(i => i.type == 'action' && i.data.data.actionCategory?.value == 'defensive');
|
||||
if (featureType == 'action-int') return allItems.filter(i => i.type == 'action' && i.data.data.actionCategory?.value == 'interaction');
|
||||
if (featureType == 'action-off') return allItems.filter(i => i.type == 'action' && i.data.data.actionCategory?.value == 'offensive');
|
||||
if (featureType == 'action-def') return allItems.filter(i => i.type == 'action' && this.getItemData(i).actionCategory?.value == 'defensive');
|
||||
if (featureType == 'action-int') return allItems.filter(i => i.type == 'action' && this.getItemData(i).actionCategory?.value == 'interaction');
|
||||
if (featureType == 'action-off') return allItems.filter(i => i.type == 'action' && this.getItemData(i).actionCategory?.value == 'offensive');
|
||||
if (featureType == 'strike') { //Strikes are not in the actor.items collection
|
||||
if (token.actor.type == 'hazard' || token.actor.type == 'familiar') {
|
||||
return allItems.filter(i => i.type == 'melee' || i.type == 'ranged');
|
||||
}
|
||||
let actions = token.actor.data.data.actions?.filter(a=>a.type == 'strike');
|
||||
let actions = this.getActorData(token).actions?.filter(a=>a.type == 'strike');
|
||||
for (let a of actions) {
|
||||
a.img = a.imageUrl;
|
||||
a.data = {
|
||||
@@ -326,7 +343,7 @@ export class pf2e{
|
||||
}
|
||||
|
||||
getFeatureUses(item) {
|
||||
if (item.data.type == 'class') return {available: item.actor.details.level.value};
|
||||
if (item.data.type == 'class') return {available: item.parent.data.data.details.level.value};
|
||||
else return;
|
||||
}
|
||||
|
||||
@@ -336,7 +353,7 @@ export class pf2e{
|
||||
buildSpellData(token) {
|
||||
let spellData = [[],[],[],[],[],[],[],[],[],[],[],[]];
|
||||
let spellcastingEntries = token.actor.spellcasting;
|
||||
const actorLevel = token.actor.data.data.details.level.value;
|
||||
const actorLevel = this.getActorData(token).details.level.value;
|
||||
spellcastingEntries.forEach(spellCastingEntry => {
|
||||
let highestSpellSlot = Math.ceil(actorLevel/2);
|
||||
while (spellCastingEntry.data.data.slots?.[`slot${highestSpellSlot}`]?.max <= 0) highestSpellSlot--;
|
||||
@@ -404,15 +421,15 @@ export class pf2e{
|
||||
if (level == undefined || level == 'any') level = item.level;
|
||||
if (item.isCantrip == true) return;
|
||||
if (item.isFocusSpell == true) return {
|
||||
available: token.actor.data.data.resources.focus.value,
|
||||
maximum: token.actor.data.data.resources.focus.max
|
||||
available: this.getActorData(token).resources.focus.value,
|
||||
maximum: this.getActorData(token).resources.focus.max
|
||||
}
|
||||
const spellbook = this.findSpellcastingEntry(token.actor, item);
|
||||
if (spellbook == undefined) return;
|
||||
if (spellbook.data.data.prepared.value == 'innate') {
|
||||
return {
|
||||
available: item.data.data.location.uses.value,
|
||||
maximum: item.data.data.location.uses.max
|
||||
available: this.getItemData(item).location.uses.value,
|
||||
maximum: this.getItemData(item).location.uses.max
|
||||
}
|
||||
}
|
||||
if (spellbook.data.data.prepared.value == 'prepared') {
|
||||
@@ -457,7 +474,7 @@ export class pf2e{
|
||||
if (otherControls.rollOption == 'map2') variant = 2;
|
||||
if (item?.parent?.type == 'hazard' && item.type==='melee') return item.rollNPCAttack({}, variant+1);
|
||||
if (item.type==='strike') return item.variants[variant].roll({event});
|
||||
if (item?.parent?.type !== 'hazard' && (item.type==='weapon' || item.type==='melee')) return item.parent.actions.find(a=>a.name===item.name).variants[variant].roll({event});
|
||||
if (item?.parent?.type !== 'hazard' && (item.type==='weapon' || item.type==='melee')) return item.parent.data.data.actions.find(a=>a.name===item.name).variants[variant].roll({event});
|
||||
if (item.type === 'spell') {
|
||||
const spellbook = this.findSpellcastingEntry(item.parent, item);
|
||||
if (spellbook != undefined) {
|
||||
|
||||
@@ -9,11 +9,19 @@ const proficiencyColors = {
|
||||
|
||||
export class starfinder{
|
||||
constructor(){
|
||||
console.log("Material Deck: Using system 'Starfinder'");
|
||||
}
|
||||
|
||||
getActorData(token) {
|
||||
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
|
||||
}
|
||||
|
||||
getItemData(item) {
|
||||
return compatibleCore('10.0') ? item.system : item.data.data;
|
||||
}
|
||||
|
||||
getHP(token) {
|
||||
const hp = token.actor.data.data.attributes.hp;
|
||||
const hp = this.getActorData(token).attributes.hp;
|
||||
return {
|
||||
value: hp.value,
|
||||
max: hp.max
|
||||
@@ -25,7 +33,7 @@ export class starfinder{
|
||||
}
|
||||
|
||||
getStamina(token) {
|
||||
const stamina = token.actor.data.data.attributes.sp;
|
||||
const stamina = this.getActorData(token).attributes.sp;
|
||||
return {
|
||||
value: stamina.value,
|
||||
max: stamina.max
|
||||
@@ -33,11 +41,11 @@ export class starfinder{
|
||||
}
|
||||
|
||||
getAC(token) {
|
||||
return token.actor.data.data.attributes.eac.value;
|
||||
return this.getActorData(token).attributes.eac.value;
|
||||
}
|
||||
|
||||
getKinAC(token) {
|
||||
return token.actor.data.data.attributes.kac.value;
|
||||
return this.getActorData(token).attributes.kac.value;
|
||||
}
|
||||
|
||||
getShieldHP(token) {
|
||||
@@ -45,7 +53,7 @@ export class starfinder{
|
||||
}
|
||||
|
||||
getSpeed(token) {
|
||||
const movement = token.actor.data.data.attributes.speed;
|
||||
const movement = this.getActorData(token).attributes.speed;
|
||||
let speed = "";
|
||||
if (movement.burrowing.value > 0) speed += `Burrow: ${movement.burrowing.value}Ft`;
|
||||
if (movement.climbing.value > 0) {
|
||||
@@ -68,7 +76,7 @@ export class starfinder{
|
||||
}
|
||||
|
||||
getInitiative(token) {
|
||||
let initiative = token.actor.data.data.attributes.init.total;
|
||||
let initiative = this.getActorData(token).attributes.init.total;
|
||||
return (initiative >= 0) ? `+${initiative}` : initiative;
|
||||
}
|
||||
|
||||
@@ -86,25 +94,25 @@ export class starfinder{
|
||||
|
||||
getAbility(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
return token.actor.data.data.abilities?.[ability].value;
|
||||
return this.getActorData(token).abilities?.[ability].value;
|
||||
}
|
||||
|
||||
getAbilityModifier(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
let val = token.actor.data.data.abilities?.[ability].mod;
|
||||
let val = this.getActorData(token).abilities?.[ability].mod;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getAbilitySave(token, ability) {
|
||||
if (ability == undefined) ability = 'fort';
|
||||
else if (ability == 'ref') ability = 'reflex';
|
||||
let val = token.actor.data.data.attributes?.[ability].bonus;
|
||||
let val = this.getActorData(token).attributes?.[ability].bonus;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getSkill(token, skill) {
|
||||
if (skill == undefined) skill = 'acr';
|
||||
const val = token.actor.data.data.skills?.[skill].mod;
|
||||
const val = this.getActorData(token).skills?.[skill].mod;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
@@ -130,8 +138,8 @@ export class starfinder{
|
||||
await effect.delete();
|
||||
}
|
||||
else {
|
||||
const effect = CONFIG.statusEffects.find(e => e.id === condition);
|
||||
await token.toggleEffect(effect);
|
||||
if (this.getConditionActive(token,condition)) token.actor.setCondition(condition,false);
|
||||
else token.actor.setCondition(condition,true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -148,7 +156,10 @@ export class starfinder{
|
||||
if (roll == 'ability') token.actor.rollAbilityTest(ability,options);
|
||||
else if (roll == 'save') token.actor.rollAbilitySave(save,options);
|
||||
else if (roll == 'skill') token.actor.rollSkill(skill,options);
|
||||
else if (roll == 'initiative') token.actor.rollInitiative(options);
|
||||
else if (roll == 'initiative') {
|
||||
options.rerollInitiative = true;
|
||||
token.actor.rollInitiative(options);
|
||||
}
|
||||
else if (roll == 'deathSave') token.actor.rollDeathSave(options);
|
||||
}
|
||||
|
||||
@@ -164,7 +175,7 @@ export class starfinder{
|
||||
}
|
||||
|
||||
getItemUses(item) {
|
||||
return {available: item.data.data.quantity};
|
||||
return {available: this.getItemData(item).quantity};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,10 +194,10 @@ export class starfinder{
|
||||
}
|
||||
|
||||
getFeatureUses(item) {
|
||||
if (item.data.type == 'class') return {available: item.data.data.levels};
|
||||
if (item.data.type == 'class') return {available: this.getItemData(item).levels};
|
||||
else return {
|
||||
available: item.data.data.uses.value,
|
||||
maximum: item.data.data.uses.max
|
||||
available: this.getItemData(item).uses.value,
|
||||
maximum: this.getItemData(item).uses.max
|
||||
};
|
||||
}
|
||||
|
||||
@@ -197,16 +208,16 @@ export class starfinder{
|
||||
if (level == undefined) level = 'any';
|
||||
const allItems = token.actor.items;
|
||||
if (level == 'any') return allItems.filter(i => i.type == 'spell')
|
||||
else if (level == 'innate') return allItems.filter(i => i.type == 'spell' && i.data.data.preparation.mode == 'innate');
|
||||
else return allItems.filter(i => i.type == 'spell' && i.data.data.preparation.mode == '' && i.data.data.level == level)
|
||||
else if (level == 'innate') return allItems.filter(i => i.type == 'spell' && this.getItemData(i).preparation.mode == 'innate');
|
||||
else return allItems.filter(i => i.type == 'spell' && this.getItemData(i).preparation.mode == '' && this.getItemData(i).level == level)
|
||||
}
|
||||
|
||||
getSpellUses(token,level,item) {
|
||||
if (level == undefined) level = 'any';
|
||||
if (item.data.data.level == 0) return;
|
||||
if (this.getItemData(item).level == 0) return;
|
||||
|
||||
const spellSlots = token.actor.data.data.spells;
|
||||
const allowedClasses = item.data.data.allowedClasses;
|
||||
const spellSlots = this.getActorData(token).spells;
|
||||
const allowedClasses = this.getItemData(item).allowedClasses;
|
||||
|
||||
let uses = {available: 0, maximum: 0};
|
||||
if (allowedClasses.myst && spellSlots?.[`spell${level}`].perClass?.mystic?.max > uses.maximum)
|
||||
@@ -229,13 +240,13 @@ export class starfinder{
|
||||
* Ring Colors
|
||||
*/
|
||||
getSkillRingColor(token, skill) {
|
||||
const profLevel = token.actor.data.data?.skills[skill]?.proficient;
|
||||
const profLevel = this.getActorData(token)?.skills[skill]?.proficient;
|
||||
if (profLevel == undefined) return;
|
||||
return proficiencyColors?.[profLevel];
|
||||
}
|
||||
|
||||
getSaveRingColor(token, save) {
|
||||
const profLevel = token.actor.data.data?.abilities[save]?.proficient;
|
||||
const profLevel = this.getActorData(token)?.abilities[save]?.proficient;
|
||||
if (profLevel == undefined) return;
|
||||
return proficiencyColors?.[profLevel];
|
||||
}
|
||||
|
||||
325
src/systems/template.js
Normal file
325
src/systems/template.js
Normal file
@@ -0,0 +1,325 @@
|
||||
/**
|
||||
* This is a template for adding a new gaming system.
|
||||
* Edit it to suit your system, for inspiration, look at other system files.
|
||||
* Functions that are unused in your system can be left empty, but don't delete the function.
|
||||
*
|
||||
* Use the compatibleCore function to get the right value for the Foundry core:
|
||||
* return compatibleCore('10.0') ? [value in v10+] : [value pre v10];
|
||||
*
|
||||
* Use the compatibleSystem function to get the right value for the gaming system version:
|
||||
* return compatibleSystem('1.6.3') ? [value in v1.6.3+] : [value pre v1.6.3];
|
||||
*/
|
||||
|
||||
import { compatibleCore, compatibleSystem } from "../misc";
|
||||
|
||||
/**
|
||||
* Proficiency colors to show if a token is proficient in for example a skill
|
||||
*/
|
||||
const proficiencyColors = {
|
||||
0: "#000000",
|
||||
0.5: "#804A00",
|
||||
1: "#C0C0C0",
|
||||
2: "#FFD700"
|
||||
}
|
||||
|
||||
//Rename 'template' to the name of your system
|
||||
export class template{
|
||||
constructor(){
|
||||
console.log("Material Deck: Using system 'SystemName'");
|
||||
}
|
||||
|
||||
getActorData(token) {
|
||||
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
|
||||
}
|
||||
|
||||
getItemData(item) {
|
||||
return compatibleCore('10.0') ? item.system : item.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HP of the token
|
||||
* @param {Token} token Token instance to get the HP from
|
||||
* @returns {object} Token hp value and max: {value: ##, max: ##}
|
||||
*/
|
||||
getHP(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the temporary HP of the token
|
||||
* @param {Token} token Token instance to get the temp HP from
|
||||
* @returns {object} Token temp hp value and max: {value: ##, max: ##}
|
||||
*/
|
||||
getTempHP(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the armor class of the token
|
||||
* @param {Token} token Token instance to get the AC from
|
||||
* @returns {number} AC value
|
||||
*/
|
||||
getAC(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shield HP of the token
|
||||
* @param {Token} token Token instance to get the shield HP from
|
||||
* @returns {number} Shield HP
|
||||
*/
|
||||
getShieldHP(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string with movement speeds of the token
|
||||
* @param {Token} token Token instance to get the speed from
|
||||
* @returns {string} Movement speed string
|
||||
*/
|
||||
getSpeed(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initiative of the token
|
||||
* @param {Token} token Token instance to get the initiative from
|
||||
* @returns {number} Initiative value
|
||||
*/
|
||||
getInitiative(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the initiative of the token
|
||||
* @param {Token} token Token instance to toggle the initiative for
|
||||
*/
|
||||
toggleInitiative(token) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the passive perception of the token
|
||||
* @param {Token} token Token instance to get the passive perception from
|
||||
* @returns {number} Passive perception value
|
||||
*/
|
||||
getPassivePerception(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the passive investigation of the token
|
||||
* @param {Token} token Token instance to get the passive investigation from
|
||||
* @returns {number} Passive investigation value
|
||||
*/
|
||||
getPassiveInvestigation(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ability value of the token
|
||||
* @param {Token} token Token instance to get the ability value from
|
||||
* @param {string} ability Ability to get the value from
|
||||
* @returns {number} Ability value
|
||||
*/
|
||||
getAbility(token, ability) {
|
||||
if (ability == undefined) ability = ''; //default ability
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ability modifier of the token
|
||||
* @param {Token} token Token instance to get the ability modifier from
|
||||
* @param {string} ability Ability to get the value from
|
||||
* @returns {number} Ability modifier
|
||||
*/
|
||||
getAbilityModifier(token, ability) {
|
||||
if (ability == undefined) ability = ''; //default ability
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ability save of the token
|
||||
* @param {Token} token Token instance to get the ability save from
|
||||
* @param {string} ability Ability to get the value from
|
||||
* @returns {number} Ability save
|
||||
*/
|
||||
getAbilitySave(token, ability) {
|
||||
if (ability == undefined) ability = ''; //default ability
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the skill value of the token
|
||||
* @param {Token} token Token instance to get the skill value from
|
||||
* @param {string} skill Skill to get the value from
|
||||
* @returns {number} Skill value
|
||||
*/
|
||||
getSkill(token, skill) {
|
||||
if (skill == undefined) skill = '';
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the proficiency value of the token
|
||||
* @param {Token} token Token instance to get the proficiency from
|
||||
* @returns {number} Proficiency value
|
||||
*/
|
||||
getProficiency(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the icon location of a condition
|
||||
* @param {string} condition Name of the condition
|
||||
* @returns {string} Icon location
|
||||
*/
|
||||
getConditionIcon(condition) {
|
||||
if (condition == undefined) condition = 'removeAll';
|
||||
if (condition == 'removeAll') return;
|
||||
else return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a condition is active on the token
|
||||
* @param {Token} token Token instance to get the value from
|
||||
* @param {string} condition Name of the condition
|
||||
* @returns {boolean} Condition is active or not
|
||||
*/
|
||||
getConditionActive(token,condition) {
|
||||
if (condition == undefined) condition = 'removeAll';
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles a condition on a token
|
||||
* @param {Token} token Token instance to get the value from
|
||||
* @param {string} condition Name of the condition
|
||||
*/
|
||||
async toggleCondition(token,condition) {
|
||||
if (condition == undefined) condition = 'removeAll';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll for a token
|
||||
* @param {Token} token Token instance to roll for
|
||||
* @param {string} roll Roll type (ability/save/skill/initiative/deathSave)
|
||||
* @param {bbject} options Roll options
|
||||
* @param {string} ability Name of the ability to roll
|
||||
* @param {string} skill Name of the skill to roll
|
||||
* @param {string} save Name of the save to roll
|
||||
*/
|
||||
roll(token,roll,options,ability,skill,save) {
|
||||
if (roll == undefined) roll = 'ability';
|
||||
if (ability == undefined) ability = ''; //default ability
|
||||
if (skill == undefined) skill = ''; //default skill
|
||||
if (save == undefined) save = ''; //default save
|
||||
|
||||
if (roll == 'ability')
|
||||
else if (roll == 'save')
|
||||
else if (roll == 'skill')
|
||||
else if (roll == 'initiative')
|
||||
else if (roll == 'deathSave')
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of items
|
||||
* @param {Token} token Token instance to get the items from
|
||||
* @param {string} itemType Item type
|
||||
* @returns {array} Array of items
|
||||
*/
|
||||
getItems(token,itemType) {
|
||||
if (itemType == undefined) itemType = 'any';
|
||||
if (itemType == 'any') return ;
|
||||
else return ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns uses/quantity of an item
|
||||
* @param {Item} item Item instance to get the uses/quantity from
|
||||
* @returns {object} Uses/quantity available {available: ###, maximum: ###}
|
||||
*/
|
||||
getItemUses(item) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the features of a token
|
||||
* @param {Token} token Token instance to get the features from
|
||||
* @param {string} featureType Feature types to return
|
||||
* @returns {array} Array of features
|
||||
*/
|
||||
getFeatures(token,featureType) {
|
||||
if (featureType == undefined) featureType = 'any';
|
||||
if (featureType == 'any') return;
|
||||
else return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns uses/quantity of a feature
|
||||
* @param {Item} item Item/feature instance to get the uses/quantity from
|
||||
* @returns {object} Uses/quantity available {available: ###, maximum: ###}
|
||||
*/
|
||||
getFeatureUses(item) {
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the spells of a token
|
||||
* @param {Token} token Token instance to get the spells from
|
||||
* @param {string} level Spell level
|
||||
* @returns {array} Array of spells
|
||||
*/
|
||||
getSpells(token,level) {
|
||||
if (level == undefined) level = 'any';
|
||||
if (level == 'any') return;
|
||||
else return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the spell uses of a specific spell for a token
|
||||
* @param {Token} token Token instance to get the spell uses from
|
||||
* @param {string} level Spell level
|
||||
* @param {Item} item Spell instance to get the uses from
|
||||
* @returns {object} Spell uses left: {available: ###, maximum: ###}
|
||||
*/
|
||||
getSpellUses(token,level,item) {
|
||||
return {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll an item
|
||||
* @param {Token} item Item instance to roll
|
||||
* @param {object} settings Settings of the action
|
||||
* @param {object} rollOption Roll options
|
||||
*/
|
||||
rollItem(item, settings, rollOption) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a color to display proficiency for skills
|
||||
* @param {Token} token Token instance to get the proficiency from
|
||||
* @param {string} skill Skill name
|
||||
* @returns {string} Hex color string from proficiencyColors array
|
||||
*/
|
||||
getSkillRingColor(token, skill) {
|
||||
const profLevel = ;
|
||||
if (profLevel == undefined) return;
|
||||
return proficiencyColors?.[profLevel];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a color to display proficiency for saves
|
||||
* @param {Token} token Token instance to get the proficiency from
|
||||
* @param {string} save Save name
|
||||
* @returns {string} Hex color string from proficiencyColors array
|
||||
*/
|
||||
getSaveRingColor(token, save) {
|
||||
const profLevel = ;
|
||||
if (profLevel == undefined) return;
|
||||
return proficiencyColors?.[profLevel];
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ export class TokenHelper{
|
||||
|
||||
moveToken(token,dir){
|
||||
if (dir == undefined) dir = 'up';
|
||||
const gridSize = canvas.scene.data.grid;
|
||||
const gridSize = compatibleCore('10.0') ? canvas.scene.grid.size : canvas.scene.data.grid;
|
||||
let x = token.x;
|
||||
let y = token.y;
|
||||
|
||||
@@ -88,8 +88,10 @@ export class TokenHelper{
|
||||
}
|
||||
if (game.user.isGM == false && game.paused) return;
|
||||
if (game.user.isGM == false && (token.can(game.user,"control") == false || token.checkCollision(token.getCenter(x, y)))) return;
|
||||
if (compatibleCore("0.8.1")) token.document.update({x:x,y:y});
|
||||
else token.update({x:x,y:y});
|
||||
let coords = canvas.grid.getCenter(x,y);
|
||||
coords[0] -= canvas.grid.size/2;
|
||||
coords[1] -= canvas.grid.size/2;
|
||||
token.document.update({x:coords[0],y:coords[1]});
|
||||
};
|
||||
|
||||
rotateToken(token,move,value) {
|
||||
@@ -97,11 +99,10 @@ export class TokenHelper{
|
||||
value = isNaN(parseInt(value)) ? 0 : parseInt(value);
|
||||
|
||||
let rotationVal;
|
||||
if (move == 'by') rotationVal = token.data.rotation + value;
|
||||
if (move == 'by') rotationVal = compatibleCore('10.0') ? token.document.rotation + value : token.data.rotation + value;
|
||||
else rotationVal = value;
|
||||
|
||||
if (compatibleCore("0.8.1")) token.document.update({rotation: rotationVal});
|
||||
else token.update({rotation: rotationVal});
|
||||
token.document.update({rotation: rotationVal});
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
@@ -127,11 +128,11 @@ export class TokenHelper{
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
getTokenIcon(token) {
|
||||
return token.data.img;
|
||||
return compatibleCore('10.0') ? token.document.texture.src : token.data.img;
|
||||
}
|
||||
|
||||
getActorIcon(token) {
|
||||
return token.actor.data.img;
|
||||
return compatibleCore('10.0') ? token.actor.img : token.actor.data.img;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -328,8 +329,8 @@ export class TokenHelper{
|
||||
return this.system.getSpellUses(token,level,item);
|
||||
}
|
||||
|
||||
rollItem(item, settings) {
|
||||
return this.system.rollItem(item, settings);
|
||||
rollItem(item, settings, rollOption) {
|
||||
return this.system.rollItem(item, settings, rollOption);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,20 +2,27 @@ import {compatibleCore} from "../misc.js";
|
||||
|
||||
export class wfrp4e {
|
||||
constructor(){
|
||||
console.log("Material Deck: Using system 'Warhammer Fantasy Roleplaying 4e'");
|
||||
}
|
||||
|
||||
getActorData(token) {
|
||||
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
|
||||
}
|
||||
|
||||
getItemData(item) {
|
||||
return compatibleCore('10.0') ? item.system : item.data.data;
|
||||
}
|
||||
|
||||
getFate(token) {
|
||||
return token.actor.data.data.status.fate.value
|
||||
return this.getActorData(token).status.fate.value
|
||||
}
|
||||
|
||||
getFortune(token) {
|
||||
return token.actor.data.data.status.fortune.value
|
||||
return this.getActorData(token).status.fortune.value
|
||||
}
|
||||
|
||||
|
||||
getWounds(token) {
|
||||
const wounds = token.actor.data.data.status.wounds
|
||||
const wounds = this.getActorData(token).status.wounds
|
||||
return {
|
||||
value: wounds.value,
|
||||
max: wounds.max
|
||||
@@ -24,7 +31,7 @@ export class wfrp4e {
|
||||
}
|
||||
|
||||
getCriticalWounds(token) {
|
||||
const criticalWounds = token.actor.data.data.status.criticalWounds
|
||||
const criticalWounds = this.getActorData(token).status.criticalWounds
|
||||
return {
|
||||
value: criticalWounds.value,
|
||||
max: criticalWounds.max
|
||||
@@ -32,19 +39,19 @@ export class wfrp4e {
|
||||
}
|
||||
|
||||
getCorruption(token) {
|
||||
return token.actor.data.data.status.corruption.value
|
||||
return this.getActorData(token).status.corruption.value
|
||||
}
|
||||
|
||||
getAdvantage(token) {
|
||||
return token.actor.data.data.status.advantage.value
|
||||
return this.getActorData(token).status.advantage.value
|
||||
}
|
||||
|
||||
getResolve(token) {
|
||||
return token.actor.data.data.status.resolve.value
|
||||
return this.getActorData(token).status.resolve.value
|
||||
}
|
||||
|
||||
getResilience(token) {
|
||||
return token.actor.data.data.status.resilience.value
|
||||
return this.getActorData(token).status.resilience.value
|
||||
}
|
||||
|
||||
getAbility(token, abilityName) {
|
||||
@@ -53,7 +60,7 @@ export class wfrp4e {
|
||||
|
||||
getCharacteristics(token, characteristicName) {
|
||||
if (characteristicName == undefined ) characteristicName = `AG`;
|
||||
const characteristic = token.actor.data.data.characteristics[characteristicName.toLowerCase()]
|
||||
const characteristic = this.getActorData(token).characteristics[characteristicName.toLowerCase()]
|
||||
const val = characteristic.value;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
@@ -74,7 +81,7 @@ export class wfrp4e {
|
||||
}
|
||||
|
||||
getFeatureUses(item) {
|
||||
return {available: `+${item.data.data.total.value}`};
|
||||
return {available: `+${this.getItemData(item).total.value}`};
|
||||
}
|
||||
|
||||
getHP(token) {
|
||||
@@ -86,7 +93,7 @@ export class wfrp4e {
|
||||
}
|
||||
|
||||
getSpeed(token) {
|
||||
return token.actor.data.data.details.move.value;
|
||||
return this.getActorData(token).details.move.value;
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +132,7 @@ export class wfrp4e {
|
||||
|
||||
getItemUses(item) {
|
||||
if ( item.type == 'ammunition') {
|
||||
return {available: item.data.data.quantity.value};
|
||||
return {available: this.getItemData(item).quantity.value};
|
||||
}
|
||||
else {
|
||||
return;
|
||||
|
||||
@@ -1,41 +1,18 @@
|
||||
<form autocomplete="off" onsubmit="event.preventDefault()">
|
||||
|
||||
<style>
|
||||
.columnLabel {
|
||||
max-width:30%;
|
||||
min-width:30%;
|
||||
text-align: left;
|
||||
}
|
||||
.columnId {
|
||||
max-width:25%;
|
||||
min-width:25%;
|
||||
text-align: left;
|
||||
text-overflow: hidden;
|
||||
}
|
||||
.columnCB {
|
||||
width:10%;
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
<table style="width:100%; min-width:400px">
|
||||
<tr>
|
||||
<th class='columnLabel'>{{localize "MaterialDeck.Name"}}</th>
|
||||
<th class='columnLabel'>{{localize "MaterialDeck.Type"}}</th>
|
||||
<th class='columnId'>{{localize "MaterialDeck.Id"}}</th>
|
||||
<th class='columnCB'>{{localize "MaterialDeck.Perm.ENABLE.ENABLE.label"}}</th>
|
||||
<th class='materialDeck_devConf_columnLabel'>{{localize "MaterialDeck.Name"}}</th>
|
||||
<th class='materialDeck_devConf_columnLabel'>{{localize "MaterialDeck.Type"}}</th>
|
||||
<th class='materialDeck_devConf_columnId'>{{localize "MaterialDeck.Id"}}</th>
|
||||
<th class='materialDeck_devConf_columnCB'>{{localize "MaterialDeck.Perm.ENABLE.ENABLE.label"}}</th>
|
||||
</tr>
|
||||
{{#each devices as |d|}}
|
||||
<tr>
|
||||
<td class='columnLabel'>{{d.name}}</td>
|
||||
<td class='columnLabel'>{{d.type}}</td>
|
||||
<td class='columnId'><input type="text" value={{d.id}} disabled></td>
|
||||
<td class='columnCB'><input type="checkbox" name="enable" id={{d.id}} {{checked d.en}}></td>
|
||||
<td class='materialDeck_devConf_columnLabel'>{{d.name}}</td>
|
||||
<td class='materialDeck_devConf_columnLabel'>{{d.type}}</td>
|
||||
<td class='materialDeck_devConf_columnId'><input type="text" value={{d.id}} disabled></td>
|
||||
<td class='materialDeck_devConf_columnCB'><input type="checkbox" name="enable" id="materialDeck_devConf_{{d.id}}" {{checked d.en}}></td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
</form>
|
||||
@@ -1,64 +1,45 @@
|
||||
<form autocomplete="off" onsubmit="event.preventDefault()">
|
||||
<style>
|
||||
.columnLabel {
|
||||
width:25%;
|
||||
text-align: left;
|
||||
}
|
||||
.columnVersion {
|
||||
width:15%;
|
||||
text-align: left;
|
||||
}
|
||||
.columnOS {
|
||||
width:15%;
|
||||
}
|
||||
.columnButton {
|
||||
width:15%;
|
||||
}
|
||||
.btn {
|
||||
width:100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h2>{{localize "MaterialDeck.DownloadUtility.Plugin"}}</h2>
|
||||
|
||||
<table style="width:100%; min-width:400px">
|
||||
<tr>
|
||||
<th class='columnLabel'></th>
|
||||
<th class='columnVersion'>{{localize "MaterialDeck.DownloadUtility.Current"}}</th>
|
||||
<th class='columnVersion'>{{localize "MaterialDeck.DownloadUtility.Minimum"}}</th>
|
||||
<th class='columnVersion'>{{localize "MaterialDeck.DownloadUtility.Latest"}}</th>
|
||||
<th class='columnOS'>{{localize "MaterialDeck.DownloadUtility.OS"}}</th>
|
||||
<th class='columnButton'>{{localize "MaterialDeck.DownloadUtility.Download"}}</th>
|
||||
<th class='materialDeck_dlUtil_columnLabel'></th>
|
||||
<th class='materialDeck_dlUtil_columnVersion'>{{localize "MaterialDeck.DownloadUtility.Current"}}</th>
|
||||
<th class='materialDeck_dlUtil_columnVersion'>{{localize "MaterialDeck.DownloadUtility.Minimum"}}</th>
|
||||
<th class='materialDeck_dlUtil_columnVersion'>{{localize "MaterialDeck.DownloadUtility.Latest"}}</th>
|
||||
<th class='materialDeck_dlUtil_columnOS'>{{localize "MaterialDeck.DownloadUtility.OS"}}</th>
|
||||
<th class='materialDeck_dlUtil_columnButton'>{{localize "MaterialDeck.DownloadUtility.Download"}}</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class='columnLabel'>{{localize "MaterialDeck.DownloadUtility.SDplugin"}}</td>
|
||||
<td class='columnVersion'>{{localSdVersion}}</td>
|
||||
<td class='columnVersion'>{{minimumSdVersion}}</td>
|
||||
<td class='columnVersion' id='masterSdVersion'>{{masterSdVersion}}</td>
|
||||
<td class='columnOS'></td>
|
||||
<td class='columnButton'>
|
||||
<button type="button" class='btn' id='downloadSd' {{#if sdDlDisable}}disabled{{/if}}>
|
||||
<td class='materialDeck_dlUtil_columnLabel'>{{localize "MaterialDeck.DownloadUtility.SDplugin"}}</td>
|
||||
<td class='materialDeck_dlUtil_columnVersion'>{{localSdVersion}}</td>
|
||||
<td class='materialDeck_dlUtil_columnVersion'>{{minimumSdVersion}}</td>
|
||||
<td class='materialDeck_dlUtil_columnVersion' id='materialDeck_dlUtil_masterSdVersion'>{{masterSdVersion}}</td>
|
||||
<td class='materialDeck_dlUtil_columnOS'></td>
|
||||
<td class='materialDeck_dlUtil_columnButton'>
|
||||
<button type="button" class='materialDeck_dlUtil_button' id='materialDeck_dlUtil_downloadSd' {{#if sdDlDisable}}disabled{{/if}}>
|
||||
<i class="fas fa-download"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class='columnLabel'>{{localize "MaterialDeck.DownloadUtility.MSserver"}}</td>
|
||||
<td class='columnVersion'>{{localMsVersion}}</td>
|
||||
<td class='columnVersion'>{{minimumMsVersion}}</td>
|
||||
<td class='columnVersion' id='masterMsVersion'>{{masterMsVersion}}</td>
|
||||
<td class='columnOS'>
|
||||
<select id="os" default="" {{#if msDlDisable}}disabled{{/if}}>
|
||||
<option value="win">{{localize "MaterialDeck.DownloadUtility.Windows"}}</option>
|
||||
<option value="macos">{{localize "MaterialDeck.DownloadUtility.Macos"}}</option>
|
||||
<option value="linux">{{localize "MaterialDeck.DownloadUtility.Linux"}}</option>
|
||||
<td class='materialDeck_dlUtil_columnLabel'>{{localize "MaterialDeck.DownloadUtility.MSserver"}}</td>
|
||||
<td class='materialDeck_dlUtil_columnVersion'>{{localMsVersion}}</td>
|
||||
<td class='materialDeck_dlUtil_columnVersion'>{{minimumMsVersion}}</td>
|
||||
<td class='materialDeck_dlUtil_columnVersion' id='materialDeck_dlUtil_masterMsVersion'>{{masterMsVersion}}</td>
|
||||
<td class='materialDeck_dlUtil_columnOS'>
|
||||
<select id="materialDeck_dlUtil_os" default="" {{#if msDlDisable}}disabled{{/if}}>
|
||||
<option value="win32-x64">{{localize "MaterialDeck.DownloadUtility.Windows"}}</option>
|
||||
<option value="macos-x64">{{localize "MaterialDeck.DownloadUtility.MacosIntel"}}</option>
|
||||
<option value="macos-arm64">{{localize "MaterialDeck.DownloadUtility.MacosM1"}}</option>
|
||||
<option value="linux-x64">{{localize "MaterialDeck.DownloadUtility.Linux"}}</option>
|
||||
<option value="source">{{localize "MaterialDeck.DownloadUtility.Source"}}</option>
|
||||
</select>
|
||||
</td>
|
||||
<td class='columnButton'>
|
||||
<button type="button" class='btn' id='downloadMs' {{#if msDlDisable}}disabled{{/if}}>
|
||||
<td class='materialDeck_dlUtil_columnButton'>
|
||||
<button type="button" class='materialDeck_dlUtil_button' id='materialDeck_dlUtil_downloadMs' {{#if msDlDisable}}disabled{{/if}}>
|
||||
<i class="fas fa-download"></i>
|
||||
</button>
|
||||
</td>
|
||||
@@ -70,14 +51,14 @@
|
||||
<table style="width:100%; min-width:400px">
|
||||
<tr>
|
||||
<th style='text-align: left;'>{{localize "MaterialDeck.DownloadUtility.Name"}}</th>
|
||||
<th class='columnButton'>{{localize "MaterialDeck.DownloadUtility.Download"}}</th>
|
||||
<th class='materialDeck_dlUtil_columnButton'>{{localize "MaterialDeck.DownloadUtility.Download"}}</th>
|
||||
</tr>
|
||||
<div id='profileContents'>
|
||||
{{#each profiles as |p|}}
|
||||
<tr>
|
||||
<td>{{p.label}}</td>
|
||||
<td class='columnButton'>
|
||||
<button type="button" class='btn' id='dlProfile-{{p.id}}' name='downloadProfile' {{#if ../profileDlDisable}}disabled{{/if}}>
|
||||
<td class='materialDeck_dlUtil_columnButton'>
|
||||
<button type="button" class='materialDeck_dlUtil_button' id='materialDeck_dlUtil_dlProfile-{{p.id}}' name='downloadProfile' {{#if ../profileDlDisable}}disabled{{/if}}>
|
||||
<i class="fas fa-download"></i>
|
||||
</button>
|
||||
</td>
|
||||
@@ -86,7 +67,7 @@
|
||||
</div>
|
||||
</table>
|
||||
|
||||
<button type="button" id='refresh'>
|
||||
<button type="button" id='materialDeck_dlUtil_refresh'>
|
||||
<i class="fas fa-redo"></i>
|
||||
{{localize "MaterialDeck.DownloadUtility.Refresh"}}
|
||||
</button>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<div class="form-group">
|
||||
<label>{{localize "MaterialDeck.Filename"}}: </label>
|
||||
<input type="text" name="name" value="{{name}}" id="name" style="width:100%;" >
|
||||
<input type="text" name="name" value="{{name}}" style="width:100%;" >
|
||||
</div>
|
||||
|
||||
<button type="submit" name="submit">
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
<form autocomplete="off" onsubmit="event.preventDefault()">
|
||||
<script>
|
||||
for (let element of document.getElementsByClassName("materialDeck_helpMenu_expandable")) {
|
||||
element.addEventListener("click",(event) => {
|
||||
let thisElement = event.target;
|
||||
if (event.target.className == "materialDeck_helpMenu_expandableIcon") thisElement = event.target.parentElement;
|
||||
let nextElement = thisElement.nextElementSibling;
|
||||
const collapse = nextElement.className == "materialDeck_helpMenu_collapsed" ? false : true;
|
||||
nextElement.className = collapse ? "materialDeck_helpMenu_collapsed" : "";
|
||||
thisElement.children[0].src = collapse ? "modules/MaterialDeck/img/right.png" : "modules/MaterialDeck/img/down.png";
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<div style="width:1200px">
|
||||
|
||||
<h1>Introduction</h1>
|
||||
<h1 class="materialDeck_helpMenu_expandable"><img src="modules/MaterialDeck/img/down.png" class="materialDeck_helpMenu_expandableIcon" style="width:20px">Introduction</h1>
|
||||
<div class="">
|
||||
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>
|
||||
@@ -12,18 +25,25 @@
|
||||
<br>
|
||||
Material Deck is a very large module with tons of features and ways of customizing your experience. This menu will only cover the basics to get you started,
|
||||
the full documentation can be found on <a href="https://github.com/CDeenen/MaterialDeck/wiki">Github</a>. Please also check the <a href="https://github.com/CDeenen/MaterialDeck/wiki/FAQ">FAQ</a> which answers some common questions, including some basic troubleshooting.<br>
|
||||
</div>
|
||||
|
||||
<h1>Latest Releases</h1>
|
||||
<h1 class="materialDeck_helpMenu_expandable"><img src="modules/MaterialDeck/img/right.png" class="materialDeck_helpMenu_expandableIcon" style="width:20px">Latest Releases</h1>
|
||||
<div class="materialDeck_helpMenu_collapsed">
|
||||
<a href="https://github.com/CDeenen/MaterialDeck/releases">Module</a><br>
|
||||
<a href="https://github.com/CDeenen/MaterialDeck_SD/releases">Stream Deck</a><br>
|
||||
<a href="https://github.com/CDeenen/MaterialServer/releases">Server</a><br>
|
||||
You can use the download utility in the module settings to download the Stream Deck plugin, Stream Deck profiles and Material Server.
|
||||
</div>
|
||||
|
||||
<h1>Getting Started</h1>
|
||||
Besides installing this module, you also need to install and run some other things.
|
||||
<h1 class="materialDeck_helpMenu_expandable"><img src="modules/MaterialDeck/img/right.png" class="materialDeck_helpMenu_expandableIcon" style="width:20px">Getting Started</h1>
|
||||
<div class="materialDeck_helpMenu_collapsed">
|
||||
Besides installing this module, you also need to install and run some other things.<br>
|
||||
After setting up the module settings I suggest you just play around with one of the profiles to see that happens when you press buttons and do things in Foundry.
|
||||
Most things should be pretty self explanatory. After that you could look into customizing your experience, as you can read about below.
|
||||
|
||||
<h2>Installing the Stream Deck Software and Plugin</h2>
|
||||
YOu have to download and install the <a href="https://www.elgato.com/en/gaming/downloads">Stream Deck software</a>.
|
||||
<h2 class="materialDeck_helpMenu_expandable"><img src="modules/MaterialDeck/img/right.png" class="materialDeck_helpMenu_expandableIcon" style="width:15px">Installing the Stream Deck Software and Plugin</h2>
|
||||
<div class="materialDeck_helpMenu_collapsed">
|
||||
You have to download and install the <a href="https://www.elgato.com/en/gaming/downloads">Stream Deck software</a>.
|
||||
You then need to install the plugin. There is a delay between when the plugin get's updated and the update being pushed in the store.
|
||||
If you try to install the plugin right after an update, you might not have the latest version. Manual installation is better in that case.
|
||||
<br>
|
||||
@@ -41,29 +61,33 @@
|
||||
<li>Double-click the file, this should open the Stream Deck software</li>
|
||||
<li>Press 'Install' in the pop-up</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<h2>Installing a Stream Deck Profile (optional)</h2>
|
||||
<h2 class="materialDeck_helpMenu_expandable"><img src="modules/MaterialDeck/img/right.png" class="materialDeck_helpMenu_expandableIcon" style="width:15px">Installing a Stream Deck Profile (optional)</h2>
|
||||
<div class="materialDeck_helpMenu_collapsed">
|
||||
You can create your own profile, but it is recommended to start with one of the pre-made profiles. Currently, there is a profile for the normal and XL Stream Deck variants.
|
||||
<ol>
|
||||
<li>Download the latest plugin file using the download utility in the module settings, or download one (ending with .streamDeckProfile) from <a href="https://github.com/CDeenen/MaterialDeck_SD/releases">here</a></li>
|
||||
<li>Double-click the file, this should load the profile into the Stream Deck software</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<h2>Downloading and Starting Material Server</h2>
|
||||
<h2 class="materialDeck_helpMenu_expandable"><img src="modules/MaterialDeck/img/right.png" class="materialDeck_helpMenu_expandableIcon" style="width:15px">Downloading and Starting Material Server</h2>
|
||||
<div class="materialDeck_helpMenu_collapsed">
|
||||
Material Server acts as a bridge application, bridging the communication between the Stream Deck and Material Deck.
|
||||
<ol>
|
||||
<li>Download the latest version for your operating system <a href="https://github.com/CDeenen/MaterialServer/releases">here</a></li>
|
||||
<li>Download and install the <a href="https://github.com/CDeenen/MaterialServer/blob/master/README.md#prerequisites">prerequisites</a></li>
|
||||
<li>Download the latest version for your operating system <a href="https://github.com/CDeenen/MaterialServer/releases">here</a> or through the download utility</li>
|
||||
<li>Extract the archive</li>
|
||||
<li>Double-click the file to start the server</li>
|
||||
<li>Run 'materialserver.exe' (Windows) or 'materialserver' (MacOS and Linux)</li>
|
||||
</ol>
|
||||
<b>You need to always have Material Server running when you want to use Material Deck</b>
|
||||
<b>You need to always have Material Server running when you want to use Material Deck</b><br>
|
||||
<br>
|
||||
<br>
|
||||
After setting up the module settings I suggest you just play around with one of the profiles to see that happens when you press buttons and do things in Foundry.
|
||||
Most things should be pretty self explanatory. After that you could look into customizing your experience, as you can read about below.
|
||||
<a href="https://github.com/CDeenen/MaterialServer/wiki">Material Server documentation</a>
|
||||
</div>
|
||||
|
||||
<h1>Module Setup</h1>
|
||||
</div>
|
||||
<h1 class="materialDeck_helpMenu_expandable"><img src="modules/MaterialDeck/img/right.png" class="materialDeck_helpMenu_expandableIcon" style="width:20px">Module Setup</h1>
|
||||
<div class="materialDeck_helpMenu_collapsed">
|
||||
<img src="modules/MaterialDeck/wiki/img/ModuleSettings.png" align="right" HSPACE="5" width="450">
|
||||
There are four buttons at the top:
|
||||
<ul>
|
||||
@@ -92,7 +116,8 @@
|
||||
|
||||
<BR CLEAR="right" />
|
||||
|
||||
<h2>User Permission Configuration</h2>
|
||||
<h2 class="materialDeck_helpMenu_expandable"><img src="modules/MaterialDeck/img/right.png" class="materialDeck_helpMenu_expandableIcon" style="width:15px">User Permission Configuration</h2>
|
||||
<div class="materialDeck_helpMenu_collapsed">
|
||||
<img src="modules/MaterialDeck/wiki/img/PermissionConfig.png" align="right" HSPACE="5" width="450">
|
||||
Using the 'User Permission Configuration' screen, the GM can configure what Material Deck functions users have access to.<br>
|
||||
Each action has various settings, and these settings can be set for each user role.<br>
|
||||
@@ -101,8 +126,10 @@
|
||||
<br>
|
||||
|
||||
<BR CLEAR="right" />
|
||||
</div>
|
||||
|
||||
<h2>Download Utility</h2>
|
||||
<h2 class="materialDeck_helpMenu_expandable"><img src="modules/MaterialDeck/img/right.png" class="materialDeck_helpMenu_expandableIcon" style="width:15px">Download Utility</h2>
|
||||
<div class="materialDeck_helpMenu_collapsed">
|
||||
<img src="modules/MaterialDeck/wiki/img/DownloadUtility.png" align="right" HSPACE="5" width="350">
|
||||
The download utility allows you to easily check the current version of the Stream Deck plugin and Material Server, and gives you the option to download the latest version.<br>
|
||||
Please note that the current version of Material Server is at the moment not supported.<br>
|
||||
@@ -112,8 +139,10 @@
|
||||
The refresh button at the bottom refreshes the page in case there was a connection issue.
|
||||
|
||||
<BR CLEAR="right" />
|
||||
</div>
|
||||
|
||||
<h2>Playlist Configuration</h2>
|
||||
<h2 class="materialDeck_helpMenu_expandable"><img src="modules/MaterialDeck/img/right.png" class="materialDeck_helpMenu_expandableIcon" style="width:15px">Playlist Configuration</h2>
|
||||
<div class="materialDeck_helpMenu_collapsed">
|
||||
<img src="modules/MaterialDeck/wiki/img/PlaylistConfig.png" align="right" HSPACE="5" width="350">
|
||||
The playlist configuration screen configures the playlists that you control using the <a href="https://github.com/CDeenen/MaterialDeck/wiki/Playlist-Action">Playlist action</a>.<br>
|
||||
There are 2 sections: 'Settings', and 'Playlists'.
|
||||
@@ -141,8 +170,10 @@
|
||||
For each playlist you can set the play mode, which overrides the default play mode for that specific playlist.<br>
|
||||
<br>
|
||||
<b>Note:</b> While you can assign the same playlist to multiple playlists in this configuration screen, only the play method of the first instance will be applied.
|
||||
</div>
|
||||
|
||||
<h2>Macro Configuration</h2>
|
||||
<h2 class="materialDeck_helpMenu_expandable"><img src="modules/MaterialDeck/img/right.png" class="materialDeck_helpMenu_expandableIcon" style="width:15px">Macro Configuration</h2>
|
||||
<div class="materialDeck_helpMenu_collapsed">
|
||||
The Macro Configuration screen is to configure the macroboard for the <a href="https://github.com/CDeenen/MaterialDeck/wiki/Macro-Action">Macro action</a>.<br>
|
||||
<br>
|
||||
The screen is divided into 32 boxes, each labeled 'Macro #', where each represents a single macro and its settings. This screen will be refered to as a page.
|
||||
@@ -171,8 +202,10 @@
|
||||
or you might run into issues.
|
||||
|
||||
<img src="modules/MaterialDeck/wiki/img/MacroConfig.png" align="center" HSPACE="5" width="100%">
|
||||
</div>
|
||||
|
||||
<h2>Soundboard Configuration</h2>
|
||||
<h2 class="materialDeck_helpMenu_expandable"><img src="modules/MaterialDeck/img/right.png" class="materialDeck_helpMenu_expandableIcon" style="width:15px">Soundboard Configuration</h2>
|
||||
<div class="materialDeck_helpMenu_collapsed">
|
||||
The Soundboard Configuration screen is used to configure the soundboard for the <a href="https://github.com/CDeenen/MaterialDeck/wiki/Soundboard-Action">Soundboard action</a>.<br>
|
||||
<br>
|
||||
Similar to the Macro Configuration screen, the screen is divided into boxes, each labeled 'Sound #', where each represents a single sound and its settings. This screen will be refered to as a page.
|
||||
@@ -215,8 +248,11 @@
|
||||
or you might run into issues.
|
||||
|
||||
<img src="modules/MaterialDeck/wiki/img/SoundboardConfig.png" align="center" HSPACE="5" width="100%">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>Customization</h1>
|
||||
<h1 class="materialDeck_helpMenu_expandable"><img src="modules/MaterialDeck/img/right.png" class="materialDeck_helpMenu_expandableIcon" style="width:20px">Customization</h1>
|
||||
<div class="materialDeck_helpMenu_collapsed">
|
||||
Material Deck is extremely flexible, but most of this flexibility must be performed in the Stream Deck software.<br>
|
||||
Some basic instructions on using the software can be found <a href="https://github.com/CDeenen/MaterialDeck/wiki/Getting-Started#basic-stream-deck-setup-instructions">here</a>.<br>
|
||||
<br>
|
||||
@@ -237,15 +273,18 @@
|
||||
<li><a href="https://github.com/CDeenen/MaterialDeck/wiki/Soundboard-Action">Soundboard Action</a></li>
|
||||
<li><a href="https://github.com/CDeenen/MaterialDeck/wiki/Token-Action">Token Action</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h1>Feedback</h1>
|
||||
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.
|
||||
|
||||
<h1>Credits</h1>
|
||||
<h1 class="materialDeck_helpMenu_expandable"><img src="modules/MaterialDeck/img/right.png" class="materialDeck_helpMenu_expandableIcon" style="width:20px">Feedback & Credits</h1>
|
||||
<div class="materialDeck_helpMenu_collapsed">
|
||||
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.<br>
|
||||
<br>
|
||||
<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
|
||||
<br>
|
||||
Please consider supporting me on <a href="https://www.patreon.com/materialfoundry">Patreon</a>, and feel free to join the Material Foundry <a href="https://discord.gg/3hd4G6TkmA">Discord</a> server.
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<div class="form-group upload-file">
|
||||
<label><i class="fas fa-upload fa-fw"></i> {{ localize "FILES.Upload" }}</label>
|
||||
<input type="file" name="upload" id="uploadJson">
|
||||
<input type="file" name="upload" id="materialDeck_import_uploadJson">
|
||||
</div>
|
||||
|
||||
<button type="submit" name="submit">
|
||||
|
||||
@@ -1,25 +1,12 @@
|
||||
<form autocomplete="off" onsubmit="event.preventDefault()">
|
||||
<style>
|
||||
.boxed {
|
||||
border: 1px solid black ;
|
||||
border-radius: 5px ;
|
||||
max-width: 166px;
|
||||
height: {{height}}px;
|
||||
}
|
||||
.navigation {
|
||||
flex:1;
|
||||
max-width: 8%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="navigationDiv" style="width:100%; display:flex; flex-direction:row;">
|
||||
<button type="button" class="navigation" id="navPrev" {{prevDisabled}}>
|
||||
<div class="materialDeck_macroConfig_navigationDiv">
|
||||
<button type="button" class="materialDeck_macroConfig_navigation" name="navPrev" {{prevDisabled}}>
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</button>
|
||||
<p style="width:84%; text-align:center; padding: 0px 0; font-size: 20px"><b>
|
||||
<p class="materialDeck_macroConfig_p"><b>
|
||||
{{localize "MaterialDeck.Perm.MACRO.label"}}: {{macroRange}} {{localize "MaterialDeck.Of"}} {{totalMacros}}
|
||||
</b></p>
|
||||
<button type="button" class="navigation" id="navNext">
|
||||
<button type="button" class="materialDeck_macroConfig_navigation" name="navNext">
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
@@ -28,12 +15,12 @@
|
||||
{{#each macroData}}
|
||||
<div class="form-group" style="width:100%">
|
||||
{{#each this.dataThis}}
|
||||
<div class="boxed" style="padding: 5px; margin:2px; width:10%">
|
||||
<div class="materialDeck_macroConfig_boxed">
|
||||
<div style="text-align:center;">
|
||||
{{localize "MaterialDeck.Macro"}} {{this.iteration}}
|
||||
</div>
|
||||
<div>
|
||||
<select name="macros" class="macros-select" id="macros{{this.iteration}}" default="" style="width:100%;">
|
||||
<select name="macros" class="macros-select" id="materialDeck_macroConfig_macros{{this.iteration}}" default="" style="width:100%;">
|
||||
{{#select this.macro}}
|
||||
<option value="">{{localize "MaterialDeck.None"}}</option>
|
||||
{{#each ../../macros}}
|
||||
@@ -44,30 +31,30 @@
|
||||
</div>
|
||||
{{#if ../../furnace}}
|
||||
<label>{{localize "MaterialDeck.FurnaceArgs"}}</label>
|
||||
<input type="text" name="args" id="args{{this.iteration}}" value="{{this.args}}">
|
||||
<input type="text" name="args" id="materialDeck_macroConfig_args{{this.iteration}}" value="{{this.args}}">
|
||||
{{/if}}
|
||||
|
||||
<div class="flex-container" style="display:flex;flex-direction:row;padding-top:10px">
|
||||
<div class="flex-container materialDeck_macroConfig_background">
|
||||
<label style="flex:1">{{localize "MaterialDeck.Background"}}</label>
|
||||
<input style="flex:1" type="color" name="colorPicker" id="colorpicker{{this.iteration}}" data-dtype="String" value="{{this.color}}">
|
||||
<input style="flex:1" type="color" name="colorPicker" id="materialDeck_macroConfig_colorpicker{{this.iteration}}" data-dtype="String" value="{{this.color}}">
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/each}}
|
||||
<hr>
|
||||
<div class="navigationDiv" style="width:100%; display:flex; flex-direction:row;">
|
||||
<button type="button" class="navigation" id="clearPage">
|
||||
<div class="materialDeck_macroConfig_navigationDiv">
|
||||
<button type="button" class="materialDeck_macroConfig_navigation" name="clearPage">
|
||||
<i></i>{{localize "MaterialDeck.ClearPage"}}
|
||||
</button>
|
||||
<button type="button" class="navigation" id="clearAll">
|
||||
<button type="button" class="materialDeck_macroConfig_navigation" name="clearAll">
|
||||
<i></i>{{localize "MaterialDeck.ClearAll"}}
|
||||
</button>
|
||||
<p style="width:68%;"></p>
|
||||
<button type="button" class="navigation" id="import">
|
||||
<button type="button" class="materialDeck_macroConfig_navigation" name="import">
|
||||
<i></i>{{localize "MaterialDeck.Import"}}
|
||||
</button>
|
||||
<button type="button" class="navigation" id="export">
|
||||
<button type="button" class="materialDeck_macroConfig_navigation" name="export">
|
||||
<i></i>{{localize "MaterialDeck.Export"}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize "MaterialDeck.PL.Mode"}}</label>
|
||||
<select name="playMode" class="playMode" default="">
|
||||
<select name="playMode" class="materialDeck_plConfig_select" default="">
|
||||
{{#select playMode}}
|
||||
<option value="0">{{localize "MaterialDeck.PL.Unrestricted"}}</option>
|
||||
<option value="1">{{localize "MaterialDeck.PL.OneTrackPlaylist"}}</option>
|
||||
@@ -14,7 +14,7 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>{{localize "MaterialDeck.PL.Nr"}}</label>
|
||||
<input type="number" id="numberOfPlaylists" name="plNum" min="0" max="127" value={{numberOfPlaylists}}>
|
||||
<input type="number" class="materialDeck_plConfig_select" id="numberOfPlaylists" name="plNum" min="0" max="127" value={{numberOfPlaylists}}>
|
||||
</div>
|
||||
<div>
|
||||
<h2>{{localize "MaterialDeck.Playlists"}}</h2>
|
||||
@@ -22,7 +22,7 @@
|
||||
{{#each playlistData}}
|
||||
<div class="form-group">
|
||||
<label>{{localize "MaterialDeck.Playlist"}} {{this.iteration}}</label>
|
||||
<select name="selectedPlaylist" class="playlist-select" id="playlist{{this.iteration}}" default="">
|
||||
<select name="selectedPlaylist" class="materialDeck_plConfig_select" id="playlist{{this.iteration}}" default="">
|
||||
{{#select this.playlist}}
|
||||
<option value="">{{localize "MaterialDeck.None"}}</option>
|
||||
{{#each ../playlists}}
|
||||
@@ -31,7 +31,7 @@
|
||||
{{/select}}
|
||||
</select>
|
||||
|
||||
<select name="playlistMode" class="playlistMode" id="playlistMode{{this.iteration}}" default="">
|
||||
<select name="playlistMode" class="materialDeck_plConfig_select" id="playlistMode{{this.iteration}}" default="">
|
||||
{{#select this.playlistMode}}
|
||||
<option value="0">{{localize "MaterialDeck.PL.Mode"}}</option>
|
||||
<option value="1">{{localize "MaterialDeck.PL.Unrestricted"}}</option>
|
||||
|
||||
@@ -1,25 +1,13 @@
|
||||
<form autocomplete="off" onsubmit="event.preventDefault()">
|
||||
<style>
|
||||
.boxed {
|
||||
border: 1px solid black ;
|
||||
border-radius: 5px ;
|
||||
max-width: 166px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.navigation {
|
||||
flex:1;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="navigation" style="width:100%; display:flex; flex-direction:row;">
|
||||
<button type="button" class="navigation" id="navPrev" {{prevDisabled}}>
|
||||
<div class="materialDeck_sbConfig_navigationDiv">
|
||||
<button type="button" class="materialDeck_sbConfig_navigation" name="navPrev" {{prevDisabled}}>
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</button>
|
||||
<p style="flex:15; text-align:center; padding: 0px 0; font-size: 20px"><b>
|
||||
<p class="materialDeck_sbConfig_p"><b>
|
||||
{{localize "MaterialDeck.Sounds"}}: {{soundRange}} {{localize "MaterialDeck.Of"}} {{totalSounds}}
|
||||
</b></p>
|
||||
<button type="button" class="navigation" id="navNext">
|
||||
<button type="button" class="materialDeck_sbConfig_navigation" name="navNext">
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
@@ -28,20 +16,20 @@
|
||||
{{#each soundData}}
|
||||
<div class="form-group" style="width:100%">
|
||||
{{#each this.dataThis}}
|
||||
<div class="boxed" style="padding: 5px; margin:2px; width:10%">
|
||||
<div class="materialDeck_sbConfig_boxed">
|
||||
<div style="text-align:center;">
|
||||
{{localize "MaterialDeck.Sound"}} {{this.iteration}}
|
||||
</div>
|
||||
<div style="text-align:center;">
|
||||
{{localize "MaterialDeck.Name"}}
|
||||
</div>
|
||||
<input type="text" name="namebox" value="{{this.name}}" id="name{{this.iteration}}" style="width:100%;" >
|
||||
<input type="text" name="namebox" value="{{this.name}}" id="materialDeck_sbConfig_name{{this.iteration}}" style="width:100%;" >
|
||||
|
||||
<div style="text-align:center;">
|
||||
{{localize "MaterialDeck.Playlist"}}
|
||||
</div>
|
||||
<div>
|
||||
<select name="playlist" class="playlist-select" default="" style="width:100%;" id="playlists{{this.iteration}}">
|
||||
<select name="playlist" class="playlist-select" default="" style="width:100%;" id="materialDeck_sbConfig_playlists{{this.iteration}}">
|
||||
{{#select this.selectedPlaylist}}
|
||||
{{#each ../../playlists}}
|
||||
<option value="{{this.id}}">{{this.name}}</option>
|
||||
@@ -53,8 +41,8 @@
|
||||
<div style="text-align:center;">
|
||||
{{localize "MaterialDeck.Sound"}}
|
||||
</div>
|
||||
<div class="form-fields" id="ss{{this.iteration}}" style="{{this.styleSS}}">
|
||||
<select name="sounds" class="sounds-select" default="" style="width:100%;" id="soundSelect{{this.iteration}}">
|
||||
<div class="form-fields" id="materialDeck_sbConfig_ss{{this.iteration}}" style="{{this.styleSS}}">
|
||||
<select name="sounds" class="sounds-select" default="" style="width:100%;" id="materialDeck_sbConfig_soundSelect{{this.iteration}}">
|
||||
{{#select this.sound}}
|
||||
<option value="">{{localize "MaterialDeck.None"}}</option>
|
||||
{{#each sounds}}
|
||||
@@ -63,11 +51,11 @@
|
||||
{{/select}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-fields" id="fp{{this.iteration}}" style="{{this.styleFP}}">
|
||||
<div class="form-fields" id="materialDeck_sbConfig_fp{{this.iteration}}" style="{{this.styleFP}}">
|
||||
<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>
|
||||
</button>
|
||||
<input class="image" type="text" name="src{{this.iteration}}" name2="soundSrc" id="srcPath{{this.iteration}}" placeholder="path/audio.mp3" value={{this.srcPath}}>
|
||||
<input class="image" type="text" name="src{{this.iteration}}" name2="soundSrc" id="materialDeck_sbConfig_srcPath{{this.iteration}}" placeholder="path/audio.mp3" value={{this.srcPath}}>
|
||||
</div>
|
||||
<div style="text-align:center;">
|
||||
{{localize "MaterialDeck.Icon"}}
|
||||
@@ -76,18 +64,18 @@
|
||||
<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>
|
||||
</button>
|
||||
<input class="image" type="text" name="img{{this.iteration}}" name2="imgSrc" id="imgPath{{this.iteration}}" placeholder="path/image.png" value={{this.imgPath}}>
|
||||
<input class="image" type="text" name="img{{this.iteration}}" name2="imgSrc" id="materialDeck_sbConfig_imgPath{{this.iteration}}" placeholder="path/image.png" value={{this.imgPath}}>
|
||||
</div>
|
||||
<div class="flex-container" style="display:flex;flex-direction:row;padding-top:5px">
|
||||
<label style="flex:1">{{localize "MaterialDeck.On"}} </label>
|
||||
<input style="flex:1" type="color" id="colorOn{{this.iteration}}" name="colorOn" style="flex:4" data-dtype="String" value="{{this.colorOn}}">
|
||||
<input style="flex:1" type="color" id="materialDeck_sbConfig_colorOn{{this.iteration}}" name="colorOn" style="flex:4" data-dtype="String" value="{{this.colorOn}}">
|
||||
<label style="flex:1"> {{localize "MaterialDeck.Off"}} </label>
|
||||
<input style="flex:1" type="color" id="colorOff{{this.iteration}}" name="colorOff" style="flex:4" data-dtype="String" value="{{this.colorOff}}">
|
||||
<input style="flex:1" type="color" id="materialDeck_sbConfig_colorOff{{this.iteration}}" name="colorOff" style="flex:4" data-dtype="String" value="{{this.colorOff}}">
|
||||
</div>
|
||||
|
||||
<div class="form-group options">
|
||||
<label>{{localize "MaterialDeck.Playback"}}</label>
|
||||
<select name="mode" id="playmode{{this.iteration}}" style="flex:1">
|
||||
<select name="mode" id="materialDeck_sbConfig_playmode{{this.iteration}}" style="flex:1">
|
||||
{{#select this.mode}}
|
||||
<option value="0">{{localize "MaterialDeck.Once"}}</option>
|
||||
<option value="1">{{localize "MaterialDeck.Repeat"}}</option>
|
||||
@@ -97,7 +85,7 @@
|
||||
</div>
|
||||
<div class="form-group options">
|
||||
<label>{{localize "MaterialDeck.Volume"}}</label>
|
||||
<input type="range" min="0" max="100" value={{this.volume}} class="slider" name="volume" id="volume{{this.iteration}}">
|
||||
<input type="range" min="0" max="100" value={{this.volume}} class="slider" name="volume" id="materialDeck_sbConfig_volume{{this.iteration}}">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -105,18 +93,18 @@
|
||||
</div>
|
||||
{{/each}}
|
||||
<hr>
|
||||
<div class="navigation" style="width:100%; display:flex; flex-direction:row;">
|
||||
<button type="button" class="navigation" id="clearPage">
|
||||
<div class="materialDeck_sbConfig_navigationDiv">
|
||||
<button type="button" class="materialDeck_sbConfig_navigation" name="clearPage">
|
||||
<i></i>{{localize "MaterialDeck.ClearPage"}}
|
||||
</button>
|
||||
<button type="button" class="navigation" id="clearAll">
|
||||
<button type="button" class="materialDeck_sbConfig_navigation" name="clearAll">
|
||||
<i></i>{{localize "MaterialDeck.ClearAll"}}
|
||||
</button>
|
||||
<p style="flex:15;"></p>
|
||||
<button type="button" class="navigation" id="import">
|
||||
<button type="button" class="materialDeck_sbConfig_navigation" name="import">
|
||||
<i></i>{{localize "MaterialDeck.Import"}}
|
||||
</button>
|
||||
<button type="button" class="navigation" id="export">
|
||||
<button type="button" class="materialDeck_sbConfig_navigation" name="export">
|
||||
<i></i>{{localize "MaterialDeck.Export"}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,98 +1,49 @@
|
||||
<form autocomplete="off" onsubmit="event.preventDefault();">
|
||||
|
||||
<style>
|
||||
header.table-header {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
padding: 5px;
|
||||
border: 1px solid #191813;
|
||||
text-align: center;
|
||||
color: #f0f0e0;
|
||||
font-weight: bold;
|
||||
text-shadow: 1px 1px #000;
|
||||
}
|
||||
ul.permissions-list {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
overflow: hidden auto;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
li.permission {
|
||||
padding: 5px;
|
||||
border-bottom: 1px solid #7a7971;
|
||||
}
|
||||
li.permission .form-fields {
|
||||
justify-content: space-around;
|
||||
}
|
||||
li.permission input[type="checkbox"] {
|
||||
margin: 0;
|
||||
}
|
||||
.index {
|
||||
flex: 0 0 200px;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
}
|
||||
.hint {
|
||||
flex: 0 0 100%;
|
||||
color: #4b4a44;
|
||||
font-size: 13px;
|
||||
margin: 5px 0 0;
|
||||
}
|
||||
|
||||
.form-fields {
|
||||
justify-content: space-around;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<p class="notes">{{localize "MaterialDeck.Perm.Instructions"}}</p>
|
||||
<hr>
|
||||
|
||||
<div class="form-group">
|
||||
<h2>{{ localize "MaterialDeck.Perm.ENABLE.label" }}</h2>
|
||||
</div>
|
||||
<header class="table-header flexrow">
|
||||
<label class="index">{{ localize "PERMISSION.Permission" }}</label>
|
||||
<header class="materialDeck_uPerm_table-header flexrow">
|
||||
<label class="materialDeck_uPerm_index">{{ localize "PERMISSION.Permission" }}</label>
|
||||
{{#each roles as |rl r|}}
|
||||
<label>{{ localize rl}}</label>
|
||||
{{/each}}
|
||||
</header>
|
||||
|
||||
|
||||
<li class="permission form-group">
|
||||
<label class="index">{{ localize "MaterialDeck.Perm.ENABLE.ENABLE.label" }}</label>
|
||||
<li class="materialDeck_uPerm_permission form-group">
|
||||
<label class="materialDeck_uPerm_index">{{ localize "MaterialDeck.Perm.ENABLE.ENABLE.label" }}</label>
|
||||
<div class="form-fields">
|
||||
{{#each enable as |r|}}
|
||||
<input type="checkbox" name="ENABLE" {{checked r}}>
|
||||
<input type="checkbox" name="ENABLE.{{r.role}}" {{checked r.en}}>
|
||||
{{/each}}
|
||||
</div>
|
||||
<p class="hint">{{ localize "MaterialDeck.Perm.ENABLE.ENABLE.hint" }}</p>
|
||||
<p class="hint materialDeck_uPerm_hint">{{ localize "MaterialDeck.Perm.ENABLE.ENABLE.hint" }}</p>
|
||||
</li>
|
||||
|
||||
|
||||
{{#each actions as |a|}}
|
||||
|
||||
<div class="form-group">
|
||||
<h2>{{ localize a.label }}</h2>
|
||||
</div>
|
||||
<header class="table-header flexrow">
|
||||
<label class="index">{{ localize "PERMISSION.Permission" }}</label>
|
||||
<header class="materialDeck_uPerm_table-header flexrow">
|
||||
<label class="materialDeck_uPerm_index">{{ localize "PERMISSION.Permission" }}</label>
|
||||
{{#each ../roles as |rl r|}}
|
||||
<label>{{ localize rl}}</label>
|
||||
{{/each}}
|
||||
</header>
|
||||
|
||||
<ul class="permissions-list">
|
||||
<ul class="materialDeck_uPerm_permissions-list">
|
||||
{{#each a.permissions as |p|}}
|
||||
<li class="permission form-group">
|
||||
<label class="index">{{ localize p.label }}</label>
|
||||
<li class="materialDeck_uPerm_permission form-group">
|
||||
<label class="materialDeck_uPerm_index">{{ localize p.label }}</label>
|
||||
<div class="form-fields">
|
||||
{{#each p.roles as |r|}}
|
||||
<input type="checkbox" id="{{p.id}}" name="{{a.id}}.{{p.id}}" {{checked r}}>
|
||||
<input type="checkbox" name="{{a.id}}.{{p.id}}.{{r.role}}" {{checked r.en}}>
|
||||
{{/each}}
|
||||
</div>
|
||||
<p class="hint">{{ localize p.hint }}</p>
|
||||
<p class="hint materialDeck_uPerm_hint">{{ localize p.hint }}</p>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user