v1.4.4
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import * as MODULE from "../MaterialDeck.js";
|
||||
import {streamDeck} from "../MaterialDeck.js";
|
||||
|
||||
export class ExternalModules{
|
||||
|
||||
693
src/misc.js
693
src/misc.js
@@ -1,4 +1,4 @@
|
||||
import * as MODULE from "../MaterialDeck.js";
|
||||
import {sdVersion, msVersion, moduleName, getPermission, enableModule} from "../MaterialDeck.js";
|
||||
import {macroControl,soundboard,playlistControl} from "../MaterialDeck.js";
|
||||
|
||||
export function compatibleCore(compatibleVersion){
|
||||
@@ -36,12 +36,12 @@ export class playlistConfigForm extends FormApplication {
|
||||
* Provide data to the template
|
||||
*/
|
||||
getData() {
|
||||
if (MODULE.getPermission('PLAYLIST','CONFIGURE') == false ) {
|
||||
if (getPermission('PLAYLIST','CONFIGURE') == false ) {
|
||||
ui.notifications.warn(game.i18n.localize("MaterialDeck.Notifications.Playlist.NoPermission"));
|
||||
return;
|
||||
}
|
||||
//Get the playlist settings
|
||||
let settings = game.settings.get(MODULE.moduleName,'playlists');
|
||||
let settings = game.settings.get(moduleName,'playlists');
|
||||
|
||||
//Get values from the settings, and check if they are defined
|
||||
let selectedPlaylists = settings.selectedPlaylist;
|
||||
@@ -125,8 +125,8 @@ export class playlistConfigForm extends FormApplication {
|
||||
|
||||
async updateSettings(settings,render){
|
||||
if (game.user.isGM) {
|
||||
await game.settings.set(MODULE.moduleName,'playlists', settings);
|
||||
if (MODULE.enableModule) playlistControl.updateAll();
|
||||
await game.settings.set(moduleName,'playlists', settings);
|
||||
if (enableModule) playlistControl.updateAll();
|
||||
if (render) this.render();
|
||||
}
|
||||
else {
|
||||
@@ -146,6 +146,7 @@ export class macroConfigForm extends FormApplication {
|
||||
constructor(data, options) {
|
||||
super(data, options);
|
||||
this.data = data;
|
||||
this.page = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,14 +165,14 @@ export class macroConfigForm extends FormApplication {
|
||||
* Provide data to the template
|
||||
*/
|
||||
getData() {
|
||||
if (MODULE.getPermission('MACRO','MACROBOARD_CONFIGURE') == false ) {
|
||||
if (getPermission('MACRO','MACROBOARD_CONFIGURE') == false ) {
|
||||
ui.notifications.warn(game.i18n.localize("MaterialDeck.Notifications.Macroboard.NoPermission"));
|
||||
return;
|
||||
}
|
||||
//Get the settings
|
||||
var selectedMacros = game.settings.get(MODULE.moduleName,'macroSettings').macros;
|
||||
var color = game.settings.get(MODULE.moduleName,'macroSettings').color;
|
||||
var args = game.settings.get(MODULE.moduleName,'macroSettings').args;
|
||||
var selectedMacros = game.settings.get(moduleName,'macroSettings').macros;
|
||||
var color = game.settings.get(moduleName,'macroSettings').color;
|
||||
var args = game.settings.get(moduleName,'macroSettings').args;
|
||||
|
||||
//Check if the settings are defined
|
||||
if (selectedMacros == undefined) selectedMacros = [];
|
||||
@@ -187,28 +188,12 @@ export class macroConfigForm extends FormApplication {
|
||||
height += 50;
|
||||
}
|
||||
|
||||
//Check what SD model the user is using, and set the number of rows and columns to correspond
|
||||
let streamDeckModel = game.settings.get(MODULE.moduleName,'streamDeckModel');
|
||||
let iMax,jMax;
|
||||
if (streamDeckModel == 0){
|
||||
jMax = 6;
|
||||
iMax = 3;
|
||||
}
|
||||
else if (streamDeckModel == 1){
|
||||
jMax = 6;
|
||||
iMax = 5;
|
||||
}
|
||||
else {
|
||||
jMax = 8;
|
||||
iMax = 8;
|
||||
}
|
||||
|
||||
let iteration = 0;
|
||||
let iteration = this.page*32;
|
||||
let macroData = [];
|
||||
for (let j=0; j<jMax; j++){
|
||||
for (let j=0; j<4; j++){
|
||||
let macroThis = [];
|
||||
|
||||
for (let i=0; i<iMax; i++){
|
||||
for (let i=0; i<8; i++){
|
||||
let colorData = color[iteration];
|
||||
if (colorData != undefined){
|
||||
let colorCorrect = true;
|
||||
@@ -233,13 +218,15 @@ export class macroConfigForm extends FormApplication {
|
||||
}
|
||||
macroData.push({dataThis: macroThis});
|
||||
}
|
||||
|
||||
return {
|
||||
height: height,
|
||||
macros: game.macros,
|
||||
selectedMacros: selectedMacros,
|
||||
macroData: macroData,
|
||||
furnace: furnaceEnabled
|
||||
furnace: furnaceEnabled,
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,27 +241,118 @@ 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 macro = html.find("select[name='macros']");
|
||||
const args = html.find("input[name='args']");
|
||||
const color = html.find("input[name='colorPicker']");
|
||||
|
||||
importBtn.on('click', async(event) => {
|
||||
let importDialog = new importConfigForm();
|
||||
importDialog.setData('macroboard',this)
|
||||
importDialog.render(true);
|
||||
});
|
||||
|
||||
exportBtn.on('click', async(event) => {
|
||||
const settings = game.settings.get(moduleName,'macroSettings');
|
||||
let exportDialog = new exportConfigForm();
|
||||
exportDialog.setData(settings,'macroboard')
|
||||
exportDialog.render(true);
|
||||
});
|
||||
|
||||
navNext.on('click',async (event) => {
|
||||
this.page++;
|
||||
this.render(true);
|
||||
});
|
||||
|
||||
navPrev.on('click',async (event) => {
|
||||
const settings = game.settings.get(moduleName,'macroSettings');
|
||||
this.page--;
|
||||
if (this.page < 0) this.page = 0;
|
||||
else {
|
||||
const totalMacros = Math.ceil(settings.macros.length/32)*32;
|
||||
if ((this.page + 2)*32 == totalMacros) {
|
||||
let pageEmpty = this.getPageEmpty(totalMacros-32);
|
||||
if (pageEmpty) {
|
||||
await this.clearPage(totalMacros-32,true)
|
||||
}
|
||||
}
|
||||
}
|
||||
this.render(true);
|
||||
});
|
||||
|
||||
clearAll.on('click',async (event) => {
|
||||
const parent = this;
|
||||
|
||||
let d = new Dialog({
|
||||
title: game.i18n.localize("MaterialDeck.ClearAll"),
|
||||
content: game.i18n.localize("MaterialDeck.ClearAll_Content"),
|
||||
buttons: {
|
||||
continue: {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: game.i18n.localize("MaterialDeck.Continue"),
|
||||
callback: async () => {
|
||||
this.page = 0;
|
||||
await parent.clearAllSettings();
|
||||
parent.render(true);
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
label: game.i18n.localize("MaterialDeck.Cancel")
|
||||
}
|
||||
},
|
||||
default: "cancel"
|
||||
});
|
||||
d.render(true);
|
||||
})
|
||||
|
||||
clearPage.on('click',(event) => {
|
||||
const parent = this;
|
||||
|
||||
let d = new Dialog({
|
||||
title: game.i18n.localize("MaterialDeck.ClearPage"),
|
||||
content: game.i18n.localize("MaterialDeck.ClearPage_Content"),
|
||||
buttons: {
|
||||
continue: {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: game.i18n.localize("MaterialDeck.Continue"),
|
||||
callback: async () => {
|
||||
await parent.clearPage(parent.page*32)
|
||||
parent.render(true);
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
label: game.i18n.localize("MaterialDeck.Cancel")
|
||||
}
|
||||
},
|
||||
default: "cancel"
|
||||
});
|
||||
d.render(true);
|
||||
})
|
||||
|
||||
macro.on("change", event => {
|
||||
let id = event.target.id.replace('macros','');
|
||||
let settings = game.settings.get(MODULE.moduleName,'macroSettings');
|
||||
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 settings = game.settings.get(MODULE.moduleName,'macroSettings');
|
||||
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 settings = game.settings.get(MODULE.moduleName,'macroSettings');
|
||||
let settings = game.settings.get(moduleName,'macroSettings');
|
||||
settings.color[id-1]=event.target.value;
|
||||
this.updateSettings(settings);
|
||||
});
|
||||
@@ -282,8 +360,8 @@ export class macroConfigForm extends FormApplication {
|
||||
|
||||
async updateSettings(settings){
|
||||
if (game.user.isGM) {
|
||||
await game.settings.set(MODULE.moduleName,'macroSettings',settings);
|
||||
if (MODULE.enableModule) macroControl.updateAll();
|
||||
await game.settings.set(moduleName,'macroSettings',settings);
|
||||
if (enableModule) macroControl.updateAll();
|
||||
}
|
||||
else {
|
||||
const payload = {
|
||||
@@ -293,6 +371,49 @@ export class macroConfigForm extends FormApplication {
|
||||
game.socket.emit(`module.MaterialDeck`, payload);
|
||||
}
|
||||
}
|
||||
|
||||
getPageEmpty(pageStart) {
|
||||
const settings = game.settings.get(moduleName,'macroSettings');
|
||||
let pageEmpty = true;
|
||||
for (let i=pageStart; i<pageStart+32; i++) {
|
||||
if (settings.macros[i] != undefined && settings.macros[i] != null && settings.macros[i] != "") {
|
||||
pageEmpty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pageEmpty;
|
||||
}
|
||||
|
||||
async clearPage(pageStart,remove=false) {
|
||||
const settings = game.settings.get(moduleName,'macroSettings');
|
||||
if (remove) {
|
||||
await settings.macros.splice(pageStart,32);
|
||||
await settings.color.splice(pageStart,32);
|
||||
if (settings.args != undefined) await settings.args.splice(pageStart,32);
|
||||
}
|
||||
else {
|
||||
for (let i=pageStart; i<pageStart+32; i++) {
|
||||
settings.macros[i] = null;
|
||||
settings.color[i] = "0";
|
||||
if (settings.args != undefined) settings.args[i] = null;
|
||||
}
|
||||
}
|
||||
await this.updateSettings(settings);
|
||||
}
|
||||
|
||||
async clearAllSettings() {
|
||||
let settings = {
|
||||
macros: [],
|
||||
color: [],
|
||||
args: []
|
||||
};
|
||||
for (let i=0; i<32; i++) {
|
||||
settings.macros[i] = null;
|
||||
settings.color[i] = "0";
|
||||
settings.args[i] = null;
|
||||
}
|
||||
await this.updateSettings(settings);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -301,9 +422,8 @@ export class soundboardConfigForm extends FormApplication {
|
||||
constructor(data, options) {
|
||||
super(data, options);
|
||||
this.playlists = [];
|
||||
this.iMax;
|
||||
this.jMax;
|
||||
this.settings = {};
|
||||
this.page = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,7 +435,7 @@ export class soundboardConfigForm extends FormApplication {
|
||||
title: "Material Deck: "+game.i18n.localize("MaterialDeck.Sett.SoundboardConfig"),
|
||||
template: "./modules/MaterialDeck/templates/soundboardConfig.html",
|
||||
classes: ["sheet"],
|
||||
height: 720
|
||||
height: "auto"
|
||||
});
|
||||
}
|
||||
|
||||
@@ -323,13 +443,13 @@ export class soundboardConfigForm extends FormApplication {
|
||||
* Provide data to the template
|
||||
*/
|
||||
getData() {
|
||||
if (MODULE.getPermission('SOUNDBOARD','CONFIGURE') == false ) {
|
||||
if (getPermission('SOUNDBOARD','CONFIGURE') == false ) {
|
||||
ui.notifications.warn(game.i18n.localize("MaterialDeck.Notifications.Soundboard.NoPermission"));
|
||||
return;
|
||||
}
|
||||
|
||||
//Get the settings
|
||||
this.settings = game.settings.get(MODULE.moduleName,'soundboardSettings');
|
||||
this.settings = game.settings.get(moduleName,'soundboardSettings');
|
||||
|
||||
//Check if all settings are defined
|
||||
if (this.settings.sounds == undefined) this.settings.sounds = [];
|
||||
@@ -353,29 +473,13 @@ export class soundboardConfigForm extends FormApplication {
|
||||
|
||||
this.playlists = playlists;
|
||||
|
||||
//Check what SD model the user is using, and set the number of rows and columns to correspond
|
||||
let streamDeckModel = game.settings.get(MODULE.moduleName,'streamDeckModel');
|
||||
|
||||
if (streamDeckModel == 0){
|
||||
this.jMax = 6;
|
||||
this.iMax = 3;
|
||||
}
|
||||
else if (streamDeckModel == 1){
|
||||
this.jMax = 6;
|
||||
this.iMax = 5;
|
||||
}
|
||||
else {
|
||||
this.jMax = 8;
|
||||
this.iMax = 8;
|
||||
}
|
||||
|
||||
let iteration = 0; //Sound number
|
||||
let iteration = this.page*16; //Sound number
|
||||
let soundData = []; //Stores all the data for each sound
|
||||
|
||||
//Fill soundData. soundData is an array the size of jMax (nr of rows), with each array element containing an array the size of iMax (nr of columns)
|
||||
for (let j=0; j<this.jMax; j++){
|
||||
//Fill soundData
|
||||
for (let j=0; j<2; j++){
|
||||
let soundsThis = []; //Stores row data
|
||||
for (let i=0; i<this.iMax; i++){
|
||||
for (let i=0; i<8; i++){
|
||||
//Each iteration gets the data for each sound
|
||||
|
||||
//If the volume is undefined for this sound, define it and set it to its default value
|
||||
@@ -453,7 +557,10 @@ export class soundboardConfigForm extends FormApplication {
|
||||
|
||||
return {
|
||||
soundData: soundData,
|
||||
playlists
|
||||
playlists,
|
||||
soundRange: `${this.page*16 + 1} - ${this.page*16 + 16}`,
|
||||
prevDisabled: this.page == 0 ? 'disabled' : '',
|
||||
totalSounds: this.settings.volume.length
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,6 +575,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 nameField = html.find("input[name='namebox']");
|
||||
const playlistSelect = html.find("select[name='playlist']");
|
||||
const soundSelect = html.find("select[name='sounds']");
|
||||
@@ -478,6 +591,89 @@ export class soundboardConfigForm extends FormApplication {
|
||||
const playMode = html.find("select[name='mode']");
|
||||
const volume = html.find("input[name='volume']");
|
||||
|
||||
importBtn.on('click', async(event) => {
|
||||
let importDialog = new importConfigForm();
|
||||
importDialog.setData('soundboard',this)
|
||||
importDialog.render(true);
|
||||
});
|
||||
|
||||
exportBtn.on('click', async(event) => {
|
||||
const settings = game.settings.get(moduleName,'soundboardSettings');
|
||||
let exportDialog = new exportConfigForm();
|
||||
exportDialog.setData(settings,'soundboard')
|
||||
exportDialog.render(true);
|
||||
});
|
||||
|
||||
navNext.on('click',async (event) => {
|
||||
this.page++;
|
||||
this.render(true);
|
||||
});
|
||||
navPrev.on('click',async (event) => {
|
||||
this.page--;
|
||||
if (this.page < 0) this.page = 0;
|
||||
else {
|
||||
const totalSounds = this.settings.volume.length;
|
||||
if ((this.page + 2)*16 == totalSounds) {
|
||||
let pageEmpty = this.getPageEmpty(totalSounds-16);
|
||||
if (pageEmpty) {
|
||||
await this.clearPage(totalSounds-16,true)
|
||||
}
|
||||
}
|
||||
}
|
||||
this.render(true);
|
||||
});
|
||||
|
||||
clearAll.on('click',async (event) => {
|
||||
const parent = this;
|
||||
|
||||
let d = new Dialog({
|
||||
title: game.i18n.localize("MaterialDeck.ClearAll"),
|
||||
content: game.i18n.localize("MaterialDeck.ClearAll_Content"),
|
||||
buttons: {
|
||||
continue: {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: game.i18n.localize("MaterialDeck.Continue"),
|
||||
callback: async () => {
|
||||
this.page = 0;
|
||||
await parent.clearAllSettings();
|
||||
parent.render(true);
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
label: game.i18n.localize("MaterialDeck.Cancel")
|
||||
}
|
||||
},
|
||||
default: "cancel"
|
||||
});
|
||||
d.render(true);
|
||||
})
|
||||
|
||||
clearPage.on('click',(event) => {
|
||||
const parent = this;
|
||||
|
||||
let d = new Dialog({
|
||||
title: game.i18n.localize("MaterialDeck.ClearPage"),
|
||||
content: game.i18n.localize("MaterialDeck.ClearPage_Content"),
|
||||
buttons: {
|
||||
continue: {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: game.i18n.localize("MaterialDeck.Continue"),
|
||||
callback: async () => {
|
||||
await parent.clearPage(parent.page*16)
|
||||
parent.render(true);
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
label: game.i18n.localize("MaterialDeck.Cancel")
|
||||
}
|
||||
},
|
||||
default: "cancel"
|
||||
});
|
||||
d.render(true);
|
||||
})
|
||||
|
||||
nameField.on("change",event => {
|
||||
let id = event.target.id.replace('name','')-1;
|
||||
this.settings.name[id]=event.target.value;
|
||||
@@ -595,8 +791,8 @@ export class soundboardConfigForm extends FormApplication {
|
||||
|
||||
async updateSettings(settings){
|
||||
if (game.user.isGM) {
|
||||
await game.settings.set(MODULE.moduleName,'soundboardSettings',settings);
|
||||
if (MODULE.enableModule) soundboard.updateAll();
|
||||
await game.settings.set(moduleName,'soundboardSettings',settings);
|
||||
if (enableModule) soundboard.updateAll();
|
||||
}
|
||||
else {
|
||||
const payload = {
|
||||
@@ -606,4 +802,375 @@ export class soundboardConfigForm extends FormApplication {
|
||||
game.socket.emit(`module.MaterialDeck`, payload);
|
||||
}
|
||||
}
|
||||
|
||||
getPageEmpty(pageStart) {
|
||||
let pageEmpty = true;
|
||||
for (let i=pageStart; i<pageStart+16; i++) {
|
||||
const name = this.settings.name[i];
|
||||
const playlist = this.settings.selectedPlaylists[i];
|
||||
const sound = this.settings.sounds[i];
|
||||
if ((name != "" && name != null) || playlist != undefined || sound != undefined) {
|
||||
pageEmpty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pageEmpty;
|
||||
}
|
||||
|
||||
async clearPage(pageStart,remove=false) {
|
||||
if (remove) {
|
||||
await this.settings.sounds.splice(pageStart,16);
|
||||
await this.settings.colorOn.splice(pageStart,16);
|
||||
await this.settings.colorOff.splice(pageStart,16);
|
||||
await this.settings.mode.splice(pageStart,16);
|
||||
await this.settings.img.splice(pageStart,16);
|
||||
await this.settings.volume.splice(pageStart,16);
|
||||
await this.settings.name.splice(pageStart,16);
|
||||
await this.settings.selectedPlaylists.splice(pageStart,16);
|
||||
await this.settings.src.splice(pageStart,16);
|
||||
await this.settings.sounds.splice(pageStart,16);
|
||||
}
|
||||
else {
|
||||
for (let i=pageStart; i<pageStart+16; i++) {
|
||||
this.settings.sounds[i] = null;
|
||||
this.settings.colorOn[i] = null;
|
||||
this.settings.colorOff[i] = null;
|
||||
this.settings.mode[i] = null;
|
||||
this.settings.img[i] = null;
|
||||
this.settings.volume[i] = null;
|
||||
this.settings.name[i] = null;
|
||||
this.settings.selectedPlaylists[i] = null;
|
||||
this.settings.src[i] = null;
|
||||
this.settings.sounds[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
await this.updateSettings(this.settings);
|
||||
}
|
||||
|
||||
async clearAllSettings() {
|
||||
let array = [];
|
||||
for (let i=0; i<16; i++) array[i] = "";
|
||||
let arrayVolume = [];
|
||||
for (let i=0; i<16; i++) arrayVolume[i] = "50";
|
||||
let arrayZero = [];
|
||||
for (let i=0; i<16; i++) arrayZero[i] = "0";
|
||||
|
||||
const settings = {
|
||||
playlist: "",
|
||||
sounds: array,
|
||||
colorOn: arrayZero,
|
||||
colorOff: arrayZero,
|
||||
mode: arrayZero,
|
||||
toggle: arrayZero,
|
||||
volume: arrayVolume
|
||||
};
|
||||
await this.updateSettings(settings);
|
||||
}
|
||||
}
|
||||
|
||||
export class exportConfigForm extends FormApplication {
|
||||
constructor(data, options) {
|
||||
super(data, options);
|
||||
this.data = {};
|
||||
this.name = "";
|
||||
this.source = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Default Options for this FormApplication
|
||||
*/
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
id: "MD_Export",
|
||||
title: "Material Deck: " + game.i18n.localize("MaterialDeck.ExportDialog.Title"),
|
||||
template: "./modules/MaterialDeck/templates/exportDialog.html",
|
||||
width: 500,
|
||||
height: "auto"
|
||||
});
|
||||
}
|
||||
|
||||
setData(data,source) {
|
||||
this.data = data;
|
||||
this.source = source;
|
||||
this.name = source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide data to the template
|
||||
*/
|
||||
getData() {
|
||||
return {
|
||||
source: this.source,
|
||||
name: this.name,
|
||||
content: this.source == "soundboard" ? game.i18n.localize("MaterialDeck.ExportDialog.SoundboardContent") : game.i18n.localize("MaterialDeck.ExportDialog.MacroboardContent")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update on form submit
|
||||
* @param {*} event
|
||||
* @param {*} formData
|
||||
*/
|
||||
async _updateObject(event, formData) {
|
||||
this.download(this.data,formData.name)
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
}
|
||||
|
||||
download(data,name) {
|
||||
let dataStr = JSON.stringify(data);
|
||||
let dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr);
|
||||
let exportFileDefaultName = `${name}.json`;
|
||||
let linkElement = document.createElement('a');
|
||||
linkElement.setAttribute('href', dataUri);
|
||||
linkElement.setAttribute('download', exportFileDefaultName);
|
||||
linkElement.click();
|
||||
}
|
||||
}
|
||||
|
||||
export class importConfigForm extends FormApplication {
|
||||
constructor(data, options) {
|
||||
super(data, options);
|
||||
this.data = {};
|
||||
this.name = "";
|
||||
this.source = "";
|
||||
this.parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default Options for this FormApplication
|
||||
*/
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
id: "MD_Import",
|
||||
title: "Material Deck: " + game.i18n.localize("MaterialDeck.ImportDialog.Title"),
|
||||
template: "./modules/MaterialDeck/templates/importDialog.html",
|
||||
width: 500,
|
||||
height: "auto"
|
||||
});
|
||||
}
|
||||
|
||||
setData(source,parent) {
|
||||
this.source = source;
|
||||
this.name = source;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide data to the template
|
||||
*/
|
||||
getData() {
|
||||
return {
|
||||
source: this.source,
|
||||
name: this.name,
|
||||
content: this.source == "soundboard" ? game.i18n.localize("MaterialDeck.ImportDialog.SoundboardContent") : game.i18n.localize("MaterialDeck.ImportDialog.MacroboardContent")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update on form submit
|
||||
* @param {*} event
|
||||
* @param {*} formData
|
||||
*/
|
||||
async _updateObject(event, formData) {
|
||||
await this.parent.updateSettings(this.data);
|
||||
this.parent.render(true);
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
const upload = html.find("input[id='uploadJson']");
|
||||
|
||||
upload.on('change',(event) => {
|
||||
event.preventDefault();
|
||||
this.readJsonFile(event.target.files[0]);
|
||||
})
|
||||
}
|
||||
|
||||
readJsonFile(jsonFile) {
|
||||
var reader = new FileReader();
|
||||
reader.addEventListener('load', (loadEvent) => {
|
||||
try {
|
||||
let json = JSON.parse(loadEvent.target.result);
|
||||
this.data = json;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
reader.readAsText(jsonFile);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export class downloadUtility extends FormApplication {
|
||||
constructor(data, options) {
|
||||
super(data, options);
|
||||
this.localSDversion = sdVersion;
|
||||
this.masterSDversion;
|
||||
this.localMSversion = msVersion;
|
||||
this.masterMSversion;
|
||||
this.releaseAssets = [];
|
||||
this.profiles = [];
|
||||
|
||||
let parent = this;
|
||||
setTimeout(function(){
|
||||
parent.checkForUpdate('SD');
|
||||
parent.checkForUpdate('MS');
|
||||
parent.getReleaseData();
|
||||
},100)
|
||||
}
|
||||
|
||||
/**
|
||||
* Default Options for this FormApplication
|
||||
*/
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
id: "MD_DownloadUtility",
|
||||
title: "Material Deck: " + game.i18n.localize("MaterialDeck.DownloadUtility.Title"),
|
||||
template: "./modules/MaterialDeck/templates/downloadUtility.html",
|
||||
width: 500,
|
||||
height: "auto"
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide data to the template
|
||||
*/
|
||||
getData() {
|
||||
let dlDisabled = true;
|
||||
|
||||
this.profiles = [];
|
||||
let iteration = 0;
|
||||
for (let asset of this.releaseAssets) {
|
||||
let split = asset.name.split('.');
|
||||
if (split[split.length-1] == 'streamDeckProfile') {
|
||||
this.profiles.push({id: iteration, label:split[0], url:asset.browser_download_url});
|
||||
iteration++;
|
||||
dlDisabled = false;
|
||||
}
|
||||
}
|
||||
if (this.localMSversion == undefined) this.localMSversion = 'unknown';
|
||||
|
||||
return {
|
||||
minimumSdVersion: game.modules.get("MaterialDeck").data.minimumSDversion.replace('v',''),
|
||||
localSdVersion: this.localSDversion,
|
||||
masterSdVersion: this.masterSDversion,
|
||||
sdDlDisable: this.masterSDversion == undefined,
|
||||
minimumMsVersion: game.modules.get("MaterialDeck").data.minimumMSversion.replace('v',''),
|
||||
localMsVersion: this.localMSversion,
|
||||
masterMsVersion: this.masterMSversion,
|
||||
msDlDisable: this.masterMSversion == undefined,
|
||||
profiles: this.profiles,
|
||||
profileDlDisable: dlDisabled
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update on form submit
|
||||
* @param {*} event
|
||||
* @param {*} formData
|
||||
*/
|
||||
async _updateObject(event, formData) {
|
||||
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
const downloadSd = html.find("button[id='downloadSd']");
|
||||
const downloadMs = html.find("button[id='downloadMs']");
|
||||
const downloadProfile = html.find("button[name='downloadProfile']")
|
||||
const refresh = html.find("button[id='refresh']");
|
||||
|
||||
downloadSd.on('click', () => {
|
||||
const version = document.getElementById('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;
|
||||
if (version == '' || version == undefined || version == 'Error') return;
|
||||
let name = `MaterialServer-${os}.zip`;
|
||||
let url;
|
||||
if (os == 'source') url = `https://github.com/CDeenen/MaterialServer/archive/refs/tags/v${version}.zip`;
|
||||
else url = `https://github.com/CDeenen/MaterialServer/releases/download/v${version}/${name}`;
|
||||
this.downloadURI(url,name)
|
||||
})
|
||||
downloadProfile.on('click',(event) => {
|
||||
let id = event.currentTarget.id.replace('dlProfile-','');
|
||||
this.downloadURI(this.profiles[id].url,`${this.profiles[id].label}.streamDeckProfile`);
|
||||
})
|
||||
refresh.on('click', () => {
|
||||
document.getElementById('masterSdVersion').value = 'Getting data';
|
||||
this.checkForUpdate('SD');
|
||||
document.getElementById('masterMsVersion').value = 'Getting data';
|
||||
this.checkForUpdate('MS');
|
||||
this.getReleaseData();
|
||||
})
|
||||
}
|
||||
|
||||
downloadURI(uri, name) {
|
||||
var link = document.createElement("a");
|
||||
link.download = name;
|
||||
link.href = uri;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
}
|
||||
|
||||
getReleaseData() {
|
||||
let parent = this;
|
||||
const url = 'https://api.github.com/repos/CDeenen/MaterialDeck_SD/releases/latest';
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('GET', url, true);
|
||||
request.send(null);
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4 && request.status === 200) {
|
||||
var type = request.getResponseHeader('Content-Type');
|
||||
const data = JSON.parse(request.responseText);
|
||||
parent.releaseAssets = data.assets;
|
||||
parent.render(true);
|
||||
if (type.indexOf("text") !== 1) {
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
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';
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('GET', url, true);
|
||||
request.send(null);
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState === 4 && request.status === 200) {
|
||||
var type = request.getResponseHeader('Content-Type');
|
||||
if (type.indexOf("text") !== 1) {
|
||||
if (reqType == 'SD') parent.masterSDversion = JSON.parse(request.responseText).Version;
|
||||
else if (reqType == 'MS') parent.masterMSversion = JSON.parse(request.responseText).version;
|
||||
parent.render(true);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
request.onerror = function () {
|
||||
document.getElementById(elementId).innerHTML = 'Error';
|
||||
}
|
||||
}
|
||||
}
|
||||
181
src/move.js
181
src/move.js
@@ -1,181 +0,0 @@
|
||||
import * as MODULE from "../MaterialDeck.js";
|
||||
import {streamDeck} from "../MaterialDeck.js";
|
||||
import {compatibleCore} from "./misc.js";
|
||||
|
||||
export class Move{
|
||||
constructor(){
|
||||
this.active = false;
|
||||
}
|
||||
|
||||
update(settings,context,device){
|
||||
const background = settings.background ? settings.background : '#000000';
|
||||
const mode = settings.mode ? settings.mode : 'canvas';
|
||||
const type = settings.type ? settings.type : 'move';
|
||||
|
||||
if ((MODULE.getPermission('MOVE','TOKEN') == false && mode == 'selectedToken') || (MODULE.getPermission('MOVE','CANVAS') == false && mode == 'canvas')) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
|
||||
let url = '';
|
||||
if (mode == 'canvas' || (mode == 'selectedToken' && type == 'move')){
|
||||
const dir = settings.dir ? settings.dir : 'center';
|
||||
if (dir == 'center') //center
|
||||
url = "modules/MaterialDeck/img/move/center.png";
|
||||
else if (dir == 'up') //up
|
||||
url = "modules/MaterialDeck/img/move/up.png";
|
||||
else if (dir == 'down') //down
|
||||
url = "modules/MaterialDeck/img/move/down.png";
|
||||
else if (dir == 'right') //right
|
||||
url = "modules/MaterialDeck/img/move/right.png";
|
||||
else if (dir == 'left') //left
|
||||
url = "modules/MaterialDeck/img/move/left.png";
|
||||
else if (dir == 'upRight')
|
||||
url = "modules/MaterialDeck/img/move/upright.png";
|
||||
else if (dir == 'upLeft')
|
||||
url = "modules/MaterialDeck/img/move/upleft.png";
|
||||
else if (dir == 'downRight')
|
||||
url = "modules/MaterialDeck/img/move/downright.png";
|
||||
else if (dir == 'downLeft')
|
||||
url = "modules/MaterialDeck/img/move/downleft.png";
|
||||
else if (dir == 'zoomIn')
|
||||
url = "modules/MaterialDeck/img/move/zoomin.png";
|
||||
else if (dir == 'zoomOut')
|
||||
url = "modules/MaterialDeck/img/move/zoomout.png";
|
||||
}
|
||||
else if (mode == 'selectedToken' && type == 'rotate'){
|
||||
const value = isNaN(parseInt(settings.rotValue)) ? 0 : parseInt(settings.rotValue);
|
||||
if (value >= 0)
|
||||
url = "modules/MaterialDeck/img/move/rotatecw.png";
|
||||
else
|
||||
url = "modules/MaterialDeck/img/move/rotateccw.png";
|
||||
}
|
||||
streamDeck.setIcon(context,device,url,{background:background,overlay:true});
|
||||
streamDeck.setTitle('',context);
|
||||
}
|
||||
|
||||
keyPress(settings){
|
||||
if (canvas.scene == null) return;
|
||||
if ((MODULE.getPermission('MOVE','TOKEN') == false && mode == 'selectedToken') || (MODULE.getPermission('MOVE','CANVAS') == false && mode == 'canvas')) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
|
||||
const dir = settings.dir ? settings.dir : 'center';
|
||||
const mode = settings.mode ? settings.mode : 'canvas';
|
||||
const type = settings.type ? settings.type : 'move';
|
||||
|
||||
let token;
|
||||
if (mode == 'selectedToken') {
|
||||
const selection = settings.selection ? settings.selection : 'selected';
|
||||
const tokenIdentifier = settings.tokenName ? settings.tokenName : '';
|
||||
|
||||
if (selection == 'selected') token = canvas.tokens.controlled[0];
|
||||
else if (selection != 'selected' && tokenIdentifier == '') {}
|
||||
else if (selection == 'tokenName') token = canvas.tokens.children[0].children.find(p => p.name == tokenIdentifier);
|
||||
else if (selection == 'actorName') token = canvas.tokens.children[0].children.find(p => p.actor.name == tokenIdentifier);
|
||||
else if (selection == 'tokenId') token = canvas.tokens.children[0].children.find(p => p.id == tokenIdentifier);
|
||||
else if (selection == 'actorId') token = canvas.tokens.children[0].children.find(p => p.actor.id == tokenIdentifier);
|
||||
if (token == undefined) return;
|
||||
}
|
||||
|
||||
if (type == 'move'){
|
||||
if (dir == 'zoomIn') {//zoom in
|
||||
let viewPosition = canvas.scene._viewPosition;
|
||||
viewPosition.scale = viewPosition.scale*1.05;
|
||||
viewPosition.duration = 100;
|
||||
canvas.animatePan(viewPosition);
|
||||
}
|
||||
else if (dir == 'zoomOut') {//zoom out
|
||||
let viewPosition = canvas.scene._viewPosition;
|
||||
viewPosition.scale = viewPosition.scale*0.95;
|
||||
viewPosition.duration = 100;
|
||||
canvas.animatePan(viewPosition);
|
||||
}
|
||||
else {
|
||||
if (settings.mode == 'selectedToken')
|
||||
this.moveToken(token,dir);
|
||||
else
|
||||
this.moveCanvas(dir);
|
||||
}
|
||||
}
|
||||
else if (type == 'rotate' && mode == 'selectedToken'){
|
||||
const rotType = settings.rot ? settings.rot : 'to';
|
||||
const value = isNaN(parseInt(settings.rotValue)) ? 0 : parseInt(settings.rotValue);
|
||||
|
||||
let rotationVal;
|
||||
if (rotType == 'by') rotationVal = token.data.rotation + value;
|
||||
else if (rotType == 'to') rotationVal = value;
|
||||
|
||||
if (compatibleCore("0.8.1")) token.document.update({rotation: rotationVal});
|
||||
else token.update({rotation: rotationVal});
|
||||
//token.rotate(rotationVal,false)
|
||||
}
|
||||
}
|
||||
|
||||
async moveToken(token,dir){
|
||||
const gridSize = canvas.scene.data.grid;
|
||||
let x = token.x;
|
||||
let y = token.y;
|
||||
|
||||
if (dir == 'up') y -= gridSize;
|
||||
else if (dir == 'down') y += gridSize;
|
||||
else if (dir == 'right') x += gridSize;
|
||||
else if (dir == 'left') x -= gridSize;
|
||||
else if (dir == 'upRight') {
|
||||
x += gridSize;
|
||||
y -= gridSize;
|
||||
}
|
||||
else if (dir == 'upLeft') {
|
||||
x -= gridSize;
|
||||
y -= gridSize;
|
||||
}
|
||||
else if (dir == 'downRight') {
|
||||
x += gridSize;
|
||||
y += gridSize;
|
||||
}
|
||||
else if (dir == 'downLeft') {
|
||||
x -= gridSize;
|
||||
y += gridSize;
|
||||
}
|
||||
else if (dir == 'center') {
|
||||
let location = token.getCenter(x,y);
|
||||
canvas.animatePan(location);
|
||||
}
|
||||
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});
|
||||
};
|
||||
|
||||
moveCanvas(dir){
|
||||
let viewPosition = canvas.scene._viewPosition;
|
||||
const gridSize = canvas.scene.data.grid;
|
||||
viewPosition.duration = 100;
|
||||
|
||||
if (dir == 'up') viewPosition.y -= gridSize;
|
||||
else if (dir == 'down') viewPosition.y += gridSize;
|
||||
else if (dir == 'right') viewPosition.x += gridSize;
|
||||
else if (dir == 'left') viewPosition.x -= gridSize;
|
||||
else if (dir == 'upRight') {
|
||||
viewPosition.x += gridSize;
|
||||
viewPosition.y -= gridSize;
|
||||
}
|
||||
else if (dir == 'upLeft') {
|
||||
viewPosition.x -= gridSize;
|
||||
viewPosition.y -= gridSize;
|
||||
}
|
||||
else if (dir == 'downRight') {
|
||||
viewPosition.x += gridSize;
|
||||
viewPosition.y += gridSize;
|
||||
}
|
||||
else if (dir == 'downLeft') {
|
||||
viewPosition.x -= gridSize;
|
||||
viewPosition.y += gridSize;
|
||||
}
|
||||
else if (dir == 'center') {
|
||||
viewPosition.x = (canvas.dimensions.sceneWidth+window.innerWidth)/2;
|
||||
viewPosition.y = (canvas.dimensions.sceneHeight+window.innerHeight)/2;
|
||||
}
|
||||
canvas.animatePan(viewPosition);
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,8 @@ export class OtherControls{
|
||||
|
||||
if (mode == 'pause') //pause
|
||||
this.updatePause(settings,context,device,options);
|
||||
else if (mode == 'move') //move canvas
|
||||
this.updateMove(settings,context,device,options);
|
||||
else if (mode == 'controlButtons') //control buttons
|
||||
this.updateControl(settings,context,device,options);
|
||||
else if (mode == 'darkness') //darkness
|
||||
@@ -59,6 +61,8 @@ export class OtherControls{
|
||||
|
||||
if (mode == 'pause') //pause
|
||||
this.keyPressPause(settings);
|
||||
else if (mode == 'move') //move canvas
|
||||
this.keyPressMove(settings);
|
||||
else if (mode == 'controlButtons') //control buttons
|
||||
this.keyPressControl(settings);
|
||||
else if (mode == 'darkness') //darkness controll
|
||||
@@ -126,6 +130,87 @@ export class OtherControls{
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
updateMove(settings,context,device,options={}){
|
||||
let url = '';
|
||||
const dir = settings.dir ? settings.dir : 'center';
|
||||
const background = settings.background ? settings.background : '#000000';
|
||||
if (dir == 'center') //center
|
||||
url = "modules/MaterialDeck/img/move/center.png";
|
||||
else if (dir == 'up') //up
|
||||
url = "modules/MaterialDeck/img/move/up.png";
|
||||
else if (dir == 'down') //down
|
||||
url = "modules/MaterialDeck/img/move/down.png";
|
||||
else if (dir == 'right') //right
|
||||
url = "modules/MaterialDeck/img/move/right.png";
|
||||
else if (dir == 'left') //left
|
||||
url = "modules/MaterialDeck/img/move/left.png";
|
||||
else if (dir == 'upRight')
|
||||
url = "modules/MaterialDeck/img/move/upright.png";
|
||||
else if (dir == 'upLeft')
|
||||
url = "modules/MaterialDeck/img/move/upleft.png";
|
||||
else if (dir == 'downRight')
|
||||
url = "modules/MaterialDeck/img/move/downright.png";
|
||||
else if (dir == 'downLeft')
|
||||
url = "modules/MaterialDeck/img/move/downleft.png";
|
||||
else if (dir == 'zoomIn')
|
||||
url = "modules/MaterialDeck/img/move/zoomin.png";
|
||||
else if (dir == 'zoomOut')
|
||||
url = "modules/MaterialDeck/img/move/zoomout.png";
|
||||
|
||||
streamDeck.setIcon(context,device,url,{background:background,overlay:true});
|
||||
streamDeck.setTitle('',context);
|
||||
}
|
||||
|
||||
keyPressMove(settings){
|
||||
if (canvas.scene == null) return;
|
||||
const dir = settings.dir ? settings.dir : 'center';
|
||||
if (dir == 'zoomIn') {//zoom in
|
||||
let viewPosition = canvas.scene._viewPosition;
|
||||
viewPosition.scale = viewPosition.scale*1.05;
|
||||
viewPosition.duration = 100;
|
||||
canvas.animatePan(viewPosition);
|
||||
}
|
||||
else if (dir == 'zoomOut') {//zoom out
|
||||
let viewPosition = canvas.scene._viewPosition;
|
||||
viewPosition.scale = viewPosition.scale*0.95;
|
||||
viewPosition.duration = 100;
|
||||
canvas.animatePan(viewPosition);
|
||||
}
|
||||
else {
|
||||
let viewPosition = canvas.scene._viewPosition;
|
||||
const gridSize = canvas.scene.data.grid;
|
||||
viewPosition.duration = 100;
|
||||
|
||||
if (dir == 'up') viewPosition.y -= gridSize;
|
||||
else if (dir == 'down') viewPosition.y += gridSize;
|
||||
else if (dir == 'right') viewPosition.x += gridSize;
|
||||
else if (dir == 'left') viewPosition.x -= gridSize;
|
||||
else if (dir == 'upRight') {
|
||||
viewPosition.x += gridSize;
|
||||
viewPosition.y -= gridSize;
|
||||
}
|
||||
else if (dir == 'upLeft') {
|
||||
viewPosition.x -= gridSize;
|
||||
viewPosition.y -= gridSize;
|
||||
}
|
||||
else if (dir == 'downRight') {
|
||||
viewPosition.x += gridSize;
|
||||
viewPosition.y += gridSize;
|
||||
}
|
||||
else if (dir == 'downLeft') {
|
||||
viewPosition.x -= gridSize;
|
||||
viewPosition.y += gridSize;
|
||||
}
|
||||
else if (dir == 'center') {
|
||||
viewPosition.x = (canvas.dimensions.sceneWidth+window.innerWidth)/2;
|
||||
viewPosition.y = (canvas.dimensions.sceneHeight+window.innerHeight)/2;
|
||||
}
|
||||
canvas.animatePan(viewPosition);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
updateControl(settings,context,device,options={}){
|
||||
@@ -603,18 +688,17 @@ export class OtherControls{
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
let compendium;
|
||||
if (compatibleCore("0.8.1")) compendium = game.packs.contents.find(p=>p.metadata.label == name)?.apps[0];
|
||||
else compendium = game.packs.entries.find(p=>p.metadata.label == name);
|
||||
const compendium = game.packs.find(p=>p.metadata.label == name);
|
||||
if (compendium == undefined) return;
|
||||
if (compendium.private && MODULE.getPermission('OTHER','COMPENDIUM_ALL') == false) {
|
||||
streamDeck.noPermission(context,device);
|
||||
return;
|
||||
}
|
||||
const rendered = compatibleCore("0.8.5") ? compendium.apps[0].rendered : compendium.rendered;
|
||||
const background = settings.background ? settings.background : '#000000';
|
||||
const ringOffColor = settings.offRing ? settings.offRing : '#000000';
|
||||
const ringOnColor = settings.onRing ? settings.onRing : '#00FF00';
|
||||
const ringColor = compendium.rendered ? ringOnColor : ringOffColor;
|
||||
const ringColor = rendered ? ringOnColor : ringOffColor;
|
||||
const txt = settings.displayCompendiumName ? name : '';
|
||||
|
||||
streamDeck.setTitle(txt,context);
|
||||
@@ -626,12 +710,11 @@ export class OtherControls{
|
||||
if (name == undefined) return;
|
||||
if (MODULE.getPermission('OTHER','COMPENDIUM') == false ) return;
|
||||
|
||||
let compendium;
|
||||
if (compatibleCore("0.8.1")) compendium = game.packs.contents.find(p=>p.metadata.label == name)?.apps[0];
|
||||
else compendium = game.packs.entries.find(p=>p.metadata.label == name);
|
||||
const compendium = game.packs.find(p=>p.metadata.label == name);
|
||||
const rendered = compatibleCore("0.8.5") ? compendium.apps[0].rendered : compendium.rendered;
|
||||
if (compendium == undefined) return;
|
||||
if (compendium.private && MODULE.getPermission('OTHER','COMPENDIUM_ALL') == false) return;
|
||||
else if (compendium.rendered) compendium.close();
|
||||
else if (rendered) compatibleCore("0.8.5") ? compendium.apps[0].close() : compendium.close();
|
||||
else compendium.render(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ export class PlaylistControl{
|
||||
playlistNr += this.playlistOffset;
|
||||
|
||||
let playlist = this.getPlaylist(playlistNr);
|
||||
|
||||
if (playlist != undefined){
|
||||
if (playlist.playing)
|
||||
ringColor = ringOnColor;
|
||||
@@ -115,10 +116,7 @@ export class PlaylistControl{
|
||||
|
||||
let playlist = this.getPlaylist(playlistNr);
|
||||
if (playlist != undefined){
|
||||
let track;
|
||||
if (compatibleCore("0.8.1")) track = playlist.sounds.contents[trackNr];
|
||||
else track = playlist.data.sounds[trackNr];
|
||||
|
||||
const track = compatibleCore("0.8.1") ? playlist.sounds.contents[trackNr] : playlist.sounds[trackNr];
|
||||
if (track != undefined){
|
||||
if (track.playing)
|
||||
ringColor = ringOnColor;
|
||||
@@ -200,9 +198,7 @@ export class PlaylistControl{
|
||||
if (playlistMode == 'playlist')
|
||||
this.playPlaylist(playlist,playlistNr);
|
||||
else {
|
||||
let track;
|
||||
if (compatibleCore("0.8.1")) track = playlist.sounds.contents[trackNr];
|
||||
else track = playlist.data.sounds[trackNr];
|
||||
const track = compatibleCore("0.8.1") ? playlist.sounds.contents[trackNr] : playlist.sounds[trackNr];
|
||||
if (track != undefined){
|
||||
this.playTrack(track,playlist,playlistNr);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as MODULE from "../MaterialDeck.js";
|
||||
import { playlistConfigForm, macroConfigForm, soundboardConfigForm } from "./misc.js";
|
||||
import { playlistConfigForm, macroConfigForm, soundboardConfigForm, downloadUtility } from "./misc.js";
|
||||
|
||||
let userPermissions = {};
|
||||
const defaultEnable = [true,true,true,true];
|
||||
@@ -22,10 +22,6 @@ const defaultUserPermissions = {
|
||||
MACROBOARD: [false,false,true,true],
|
||||
MACROBOARD_CONFIGURE: [false,false,true,true]
|
||||
},
|
||||
MOVE: {
|
||||
TOKEN: [true,true,true,true],
|
||||
CANVAS: [true,true,true,true]
|
||||
},
|
||||
OTHER: {
|
||||
PAUSE: [false,false,true,true],
|
||||
CONTROL: [true,true,true,true],
|
||||
@@ -83,16 +79,6 @@ export const registerSettings = async function() {
|
||||
onChange: x => window.location.reload()
|
||||
});
|
||||
|
||||
game.settings.register(MODULE.moduleName,'streamDeckModel', {
|
||||
name: "MaterialDeck.Sett.Model",
|
||||
hint: "MaterialDeck.Sett.Model_Hint",
|
||||
scope: "client",
|
||||
config: true,
|
||||
type:Number,
|
||||
default:1,
|
||||
choices:["MaterialDeck.Sett.Model_Mini","MaterialDeck.Sett.Model_Normal","MaterialDeck.Sett.Model_XL"],
|
||||
});
|
||||
|
||||
/**
|
||||
* Sets the ip address of the server
|
||||
*/
|
||||
@@ -128,6 +114,17 @@ export const registerSettings = async function() {
|
||||
|
||||
});
|
||||
|
||||
game.settings.register(MODULE.moduleName, 'nrOfConnMessages', {
|
||||
name: "MaterialDeck.Sett.NrOfConnMessages",
|
||||
hint: "MaterialDeck.Sett.NrOfConnMessagesHint",
|
||||
default: 5,
|
||||
type: Number,
|
||||
scope: 'client',
|
||||
range: { min: 0, max: 100, step: 1 },
|
||||
config: true
|
||||
|
||||
});
|
||||
|
||||
//Create the Help button
|
||||
game.settings.registerMenu(MODULE.moduleName, 'helpMenu',{
|
||||
name: "MaterialDeck.Sett.Help",
|
||||
@@ -150,6 +147,13 @@ export const registerSettings = async function() {
|
||||
config: false
|
||||
});
|
||||
|
||||
game.settings.registerMenu(MODULE.moduleName, 'downloadUtility',{
|
||||
name: "MaterialDeck.DownloadUtility.Title",
|
||||
label: "MaterialDeck.DownloadUtility.Title",
|
||||
type: downloadUtility,
|
||||
restricted: false
|
||||
});
|
||||
|
||||
/**
|
||||
* Playlist soundboard
|
||||
*/
|
||||
@@ -223,11 +227,11 @@ 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(MODULE.moduleName,'userPermission',permissionSettings);
|
||||
}
|
||||
|
||||
|
||||
|
||||
export class helpMenu extends FormApplication {
|
||||
constructor(data, options) {
|
||||
super(data, options);
|
||||
@@ -302,11 +306,7 @@ export class helpMenu extends FormApplication {
|
||||
}
|
||||
|
||||
const actions = Object.entries(duplicate(settings.permissions)).reduce((arr, e) => {
|
||||
//const perm = e[1];
|
||||
|
||||
const perms = Object.entries(duplicate(e[1])).reduce((arr, p) => {
|
||||
//const perm = e[1];
|
||||
|
||||
let perm = {};
|
||||
perm.roles = [p[1][0],p[1][1],p[1][2],p[1][3]]
|
||||
perm.id = p[0];
|
||||
@@ -324,8 +324,10 @@ export class helpMenu extends FormApplication {
|
||||
arr.push(cat);
|
||||
return arr;
|
||||
}, []);
|
||||
|
||||
const current = await game.settings.get("core", "permissions");
|
||||
for (let i=0; i<actions.length; i++) {
|
||||
if (actions[i].id == 'MOVE')
|
||||
actions.splice(i,1);
|
||||
}
|
||||
return {
|
||||
roles: Object.keys(CONST.USER_ROLES).reduce((obj, r) => {
|
||||
if ( r === "NONE" ) return obj;
|
||||
@@ -348,7 +350,7 @@ export class helpMenu extends FormApplication {
|
||||
settings.enable = permissions.ENABLE;
|
||||
delete permissions.ENABLE;
|
||||
settings.permissions = permissions;
|
||||
game.settings.set(MODULE.moduleName,'userPermission',settings);
|
||||
// game.settings.set(MODULE.moduleName,'userPermission',settings);
|
||||
}
|
||||
|
||||
async activateListeners(html) {
|
||||
|
||||
@@ -7,8 +7,6 @@ export class SoundboardControl{
|
||||
this.active = false;
|
||||
this.offset = 0;
|
||||
this.activeSounds = [];
|
||||
for (let i=0; i<64; i++)
|
||||
this.activeSounds[i] = false;
|
||||
}
|
||||
|
||||
async updateAll(){
|
||||
@@ -43,7 +41,7 @@ export class SoundboardControl{
|
||||
soundNr += this.offset;
|
||||
|
||||
let soundboardSettings = game.settings.get(MODULE.moduleName, 'soundboardSettings');
|
||||
ringColor = (this.activeSounds[soundNr]==false) ? soundboardSettings.colorOff[soundNr] : soundboardSettings.colorOn[soundNr];
|
||||
ringColor = (this.activeSounds[soundNr]==undefined) ? soundboardSettings.colorOff[soundNr] : soundboardSettings.colorOn[soundNr];
|
||||
|
||||
if (settings.displayName && soundboardSettings.name != undefined) txt = soundboardSettings.name[soundNr];
|
||||
if (settings.displayIcon && soundboardSettings.img != undefined) src = soundboardSettings.img[soundNr];
|
||||
@@ -89,7 +87,7 @@ export class SoundboardControl{
|
||||
|
||||
const playMode = game.settings.get(MODULE.moduleName,'soundboardSettings').mode[soundNr];
|
||||
const repeat = (playMode > 0) ? true : false;
|
||||
const play = (this.activeSounds[soundNr] == false) ? true : false;
|
||||
const play = (this.activeSounds[soundNr] == undefined) ? true : false;
|
||||
|
||||
this.prePlaySound(soundNr,repeat,play);
|
||||
}
|
||||
@@ -100,8 +98,8 @@ export class SoundboardControl{
|
||||
this.updateAll();
|
||||
}
|
||||
else if (mode == 'stopAll') { //Stop All Sounds
|
||||
for (let i=0; i<64; i++) {
|
||||
if (this.activeSounds[i] != false){
|
||||
for (let i=0; i<this.activeSounds.length; i++) {
|
||||
if (this.activeSounds[i] != undefined){
|
||||
this.prePlaySound(i,false,false);
|
||||
}
|
||||
}
|
||||
@@ -176,7 +174,7 @@ export class SoundboardControl{
|
||||
if(newSound.loaded == false) await newSound.load({autoplay:true});
|
||||
newSound.on('end', ()=>{
|
||||
if (repeat == false) {
|
||||
this.activeSounds[soundNr] = false;
|
||||
this.activeSounds[soundNr] = undefined;
|
||||
this.updateAll();
|
||||
}
|
||||
});
|
||||
@@ -186,12 +184,12 @@ export class SoundboardControl{
|
||||
else {
|
||||
let howl = new Howl({src, volume, loop: repeat, onend: (id)=>{
|
||||
if (repeat == false){
|
||||
this.activeSounds[soundNr] = false;
|
||||
this.activeSounds[soundNr] = undefined;
|
||||
this.updateAll();
|
||||
}
|
||||
},
|
||||
onstop: ()=>{
|
||||
this.activeSounds[soundNr] = false;
|
||||
this.activeSounds[soundNr] = undefined;
|
||||
this.updateAll();
|
||||
}});
|
||||
howl.play();
|
||||
@@ -199,28 +197,9 @@ export class SoundboardControl{
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.activeSounds[soundNr].stop();
|
||||
this.activeSounds[soundNr] = false;
|
||||
if (this.activeSounds[soundNr] != undefined) this.activeSounds[soundNr].stop();
|
||||
this.activeSounds[soundNr] = undefined;
|
||||
}
|
||||
this.updateAll();
|
||||
}
|
||||
|
||||
/*
|
||||
volumeChange(soundNr){
|
||||
|
||||
let volume = game.settings.get("core", "globalAmbientVolume");
|
||||
|
||||
if (soundNr == 'all') {
|
||||
for (let i=0; this.activeSounds.length; i++) {
|
||||
volume * game.settings.get(MODULE.moduleName,'soundboardSettings').volume[i]/100;
|
||||
volume = AudioHelper.inputToVolume(volume);
|
||||
this.activeSounds[i].volume = volume;
|
||||
}
|
||||
}
|
||||
else {
|
||||
volume * game.settings.get(MODULE.moduleName,'soundboardSettings').volume[soundNr]/100;
|
||||
volume = AudioHelper.inputToVolume(volume);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -389,7 +389,7 @@ export class StreamDeck{
|
||||
else {
|
||||
|
||||
}
|
||||
if (uses != undefined && uses.heart != false && (uses.available > 0 || uses.maximum != undefined)) {
|
||||
if (uses != undefined && uses.heart != undefined && (uses.available > 0 || uses.maximum != undefined)) {
|
||||
const percentage = 102*uses.available/uses.maximum;
|
||||
ctx.fillStyle = uses.heart;
|
||||
ctx.fillRect(0, 121,144,-percentage);
|
||||
@@ -411,7 +411,7 @@ export class StreamDeck{
|
||||
ctx.fillText(content[1], horOffset, vertOffset);
|
||||
}
|
||||
|
||||
if (format != 'jpg' && format != 'jpeg' && format != 'png' && format != 'webm' && format != 'webp' && format != 'gif' && format != 'svg') url = "modules/MaterialDeck/img/transparant.png";
|
||||
if (format != 'jpg' && format != 'jpeg' && format != 'png' && format != 'PNG' && format != 'webm' && format != 'webp' && format != 'gif' && format != 'svg') url = "modules/MaterialDeck/img/transparant.png";
|
||||
//if (url == "") url = "modules/MaterialDeck/img/transparant.png"
|
||||
let resImageURL = url;
|
||||
let img = new Image();
|
||||
@@ -451,10 +451,13 @@ export class StreamDeck{
|
||||
yStart = 0;
|
||||
}
|
||||
ctx.drawImage(img, xStart+margin, yStart+margin, renderableWidth - 2*margin, renderableHeight - 2*margin);
|
||||
if (uses != undefined && uses.heart == false && (uses.available > 0 || uses.maximum != undefined)) {
|
||||
let txt = uses.available;
|
||||
if (uses.maximum != undefined) txt = uses.available + '/' + uses.maximum;
|
||||
if (uses.maximum == undefined ) uses.maximum = 1;
|
||||
if (uses != undefined && uses.heart == undefined) {
|
||||
let txt = '';
|
||||
if (uses.available != undefined) {
|
||||
txt = uses.available;
|
||||
if (uses.maximum != undefined) txt = uses.available + '/' + uses.maximum;
|
||||
if (uses.maximum == undefined ) uses.maximum = 1;
|
||||
}
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = 4;
|
||||
let green = Math.ceil(255*(uses.available/uses.maximum));
|
||||
|
||||
133
src/systems/demonlord.js
Normal file
133
src/systems/demonlord.js
Normal file
@@ -0,0 +1,133 @@
|
||||
import {compatibleCore} from "../misc.js";
|
||||
|
||||
export class demonlord{
|
||||
constructor(){
|
||||
|
||||
}
|
||||
|
||||
getHP(token) {
|
||||
const hp = token.actor.data.data.characteristics.health;
|
||||
return {
|
||||
value: hp.value,
|
||||
max: hp.max
|
||||
}
|
||||
}
|
||||
|
||||
getTempHP(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getAC(token) {
|
||||
return token.actor.data.data.characteristics.defense;
|
||||
}
|
||||
|
||||
getShieldHP(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getSpeed(token) {
|
||||
return token.actor.data.data.characteristics.speed;
|
||||
}
|
||||
|
||||
getInitiative(token) {
|
||||
return token.actor.data.data.fastturn ? "FAST" : "SLOW";
|
||||
}
|
||||
|
||||
toggleInitiative(token) {
|
||||
token.actor.update({
|
||||
'data.fastturn': !token.actor.data?.data?.fastturn
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
getPassivePerception(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getPassiveInvestigation(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getAbility(token, ability) {
|
||||
if (ability == undefined) ability = 'strength';
|
||||
return token.actor.data.data.attributes?.[ability].value;
|
||||
}
|
||||
|
||||
getAbilityModifier(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
let val = token.actor.data.data.attributes?.[ability].modifier;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getAbilitySave(token, ability) {
|
||||
return;
|
||||
}
|
||||
|
||||
getSkill(token, skill) {
|
||||
if (skill == undefined) skill = 'acr';
|
||||
const val = token.actor.data.data.skills?.[skill].total;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getProficiency(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getConditionIcon(condition) {
|
||||
if (condition == undefined) condition = 'removeAll';
|
||||
if (condition == 'removeAll') return window.CONFIG.controlIcons.effects;
|
||||
else return CONFIG.statusEffects.find(e => e.id === condition).icon;
|
||||
}
|
||||
|
||||
getConditionActive(token,condition) {
|
||||
if (condition == undefined) condition = 'removeAll';
|
||||
return token.actor.effects.find(e => e.isTemporary === condition) != undefined;
|
||||
}
|
||||
|
||||
async toggleCondition(token,condition) {
|
||||
if (condition == undefined) condition = 'removeAll';
|
||||
if (condition == 'removeAll'){
|
||||
for( let effect of token.actor.effects)
|
||||
await effect.delete();
|
||||
}
|
||||
else {
|
||||
const effect = CONFIG.statusEffects.find(e => e.id === condition);
|
||||
await token.toggleEffect(effect);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll
|
||||
*/
|
||||
roll(token,roll,options,ability,skill,save) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Items
|
||||
*/
|
||||
getItems(token,itemType) {
|
||||
if (itemType == undefined) itemType = 'any';
|
||||
const allItems = token.actor.items;
|
||||
if (itemType == 'any') return allItems.filter(i => i.type == 'item');
|
||||
}
|
||||
|
||||
getItemUses(item) {
|
||||
return {available: item.data.data.quantity};
|
||||
}
|
||||
|
||||
/**
|
||||
* Spells
|
||||
*/
|
||||
getSpells(token,level) {
|
||||
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)
|
||||
}
|
||||
|
||||
getSpellUses(token,level,item) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
198
src/systems/dnd35e.js
Normal file
198
src/systems/dnd35e.js
Normal file
@@ -0,0 +1,198 @@
|
||||
import {compatibleCore} from "../misc.js";
|
||||
|
||||
export class dnd35e{
|
||||
constructor(){
|
||||
|
||||
}
|
||||
|
||||
getHP(token) {
|
||||
const hp = token.actor.data.data.attributes.hp;
|
||||
return {
|
||||
value: hp.value,
|
||||
max: hp.max
|
||||
}
|
||||
}
|
||||
|
||||
getTempHP(token) {
|
||||
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) {
|
||||
return token.actor.data.data.attributes.ac.normal.total;
|
||||
}
|
||||
|
||||
getShieldHP(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getSpeed(token) {
|
||||
const movement = token.actor.data.data.attributes.speed;
|
||||
let speed = "";
|
||||
if (movement.burrow.total > 0) speed += `Burrow: ${movement.burrow.total}Ft`;
|
||||
if (movement.climb.total > 0) {
|
||||
if (speed.length > 0) speed += '\n';
|
||||
speed += `Climb: ${movement.climb.total}Ft`;
|
||||
}
|
||||
if (movement.fly.total > 0) {
|
||||
if (speed.length > 0) speed += '\n';
|
||||
speed += `Fly: ${movement.fly.total}Ft`;
|
||||
}
|
||||
if (movement.land.total > 0) {
|
||||
if (speed.length > 0) speed += '\n';
|
||||
speed += `Land: ${movement.land.total}Ft`;
|
||||
}
|
||||
if (movement.swim.total > 0) {
|
||||
if (speed.length > 0) speed += '\n';
|
||||
speed += `Swim: ${movement.swim.total}Ft`;
|
||||
}
|
||||
return speed;
|
||||
}
|
||||
|
||||
getInitiative(token) {
|
||||
let initiative = token.actor.data.data.attributes.init.total;
|
||||
return (initiative >= 0) ? `+${initiative}` : initiative;
|
||||
}
|
||||
|
||||
toggleInitiative(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getPassivePerception(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getPassiveInvestigation(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getAbility(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
return token.actor.data.data.abilities?.[ability].value;
|
||||
}
|
||||
|
||||
getAbilityModifier(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
let val = token.actor.data.data.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;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getSkill(token, skill) {
|
||||
if (skill == undefined) skill = 'apr';
|
||||
const val = token.actor.data.data.skills?.[skill].mod;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getProficiency(token) {
|
||||
const val = token.actor.data.data.attributes.prof;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getConditionIcon(condition) {
|
||||
if (condition == undefined) condition = 'removeAll';
|
||||
if (condition == 'removeAll') return window.CONFIG.controlIcons.effects;
|
||||
else return CONFIG.statusEffects.find(e => e.id === condition).icon;
|
||||
}
|
||||
|
||||
getConditionActive(token,condition) {
|
||||
if (condition == undefined) condition = 'removeAll';
|
||||
return token.actor.effects.find(e => e.isTemporary === condition) != undefined;
|
||||
}
|
||||
|
||||
async toggleCondition(token,condition) {
|
||||
if (condition == undefined) condition = 'removeAll';
|
||||
if (condition == 'removeAll'){
|
||||
for( let effect of token.actor.effects)
|
||||
await effect.delete();
|
||||
}
|
||||
else {
|
||||
const effect = CONFIG.statusEffects.find(e => e.id === condition);
|
||||
await token.toggleEffect(effect);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll
|
||||
*/
|
||||
roll(token,roll,options,ability,skill,save) {
|
||||
if (roll == undefined) roll = 'ability';
|
||||
if (ability == undefined) ability = 'str';
|
||||
if (skill == undefined) skill = 'apr';
|
||||
if (save == undefined) save = 'fort';
|
||||
|
||||
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 == 'grapple') token.actor.rollGrapple(options);
|
||||
else if (roll == 'bab') token.actor.rollBAB(options);
|
||||
else if (roll == 'melee') token.actor.rollMelee(options);
|
||||
else if (roll == 'ranged') token.actor.rollRanged(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Items
|
||||
*/
|
||||
getItems(token,itemType) {
|
||||
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 (itemType == 'gear' || itemType == 'ammo' || itemType == 'misc' || itemType == 'tradeGoods')
|
||||
return allItems.filter(i => i.type == 'loot' && i.data.data.subType == itemType);
|
||||
else return allItems.filter(i => i.type == itemType);
|
||||
}
|
||||
}
|
||||
|
||||
getItemUses(item) {
|
||||
return {available: item.data.data.quantity};
|
||||
}
|
||||
|
||||
/**
|
||||
* Features
|
||||
*/
|
||||
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 return allItems.filter(i => i.type == featureType)
|
||||
}
|
||||
|
||||
getFeatureUses(item) {
|
||||
if (item.data.type == 'class') return {available: item.data.data.levels};
|
||||
else return {
|
||||
available: item.data.data.uses.value,
|
||||
maximum: item.data.data.uses.max
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Spells
|
||||
*/
|
||||
getSpells(token,level) {
|
||||
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)
|
||||
}
|
||||
|
||||
getSpellUses(token,level,item) {
|
||||
if (level == undefined) level = 'any';
|
||||
if (item.data.data.level == 0) return;
|
||||
return {
|
||||
available: item.charges,
|
||||
maximum: item.maxCharges
|
||||
}
|
||||
}
|
||||
}
|
||||
201
src/systems/dnd5e.js
Normal file
201
src/systems/dnd5e.js
Normal file
@@ -0,0 +1,201 @@
|
||||
import {compatibleCore} from "../misc.js";
|
||||
|
||||
export class dnd5e{
|
||||
constructor(){
|
||||
|
||||
}
|
||||
|
||||
getHP(token) {
|
||||
const hp = token.actor.data.data.attributes.hp;
|
||||
return {
|
||||
value: hp.value,
|
||||
max: hp.max
|
||||
}
|
||||
}
|
||||
|
||||
getTempHP(token) {
|
||||
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) {
|
||||
return token.actor.data.data.attributes.ac.value;
|
||||
}
|
||||
|
||||
getShieldHP(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getSpeed(token) {
|
||||
const movement = token.actor.data.data.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';
|
||||
speed += `${game.i18n.localize("DND5E.MovementClimb")}: ${movement.climb + movement.units}`;
|
||||
}
|
||||
if (movement.fly > 0) {
|
||||
if (speed.length > 0) speed += '\n';
|
||||
speed += `${game.i18n.localize("DND5E.MovementFly")}: ${movement.fly + movement.units}`;
|
||||
}
|
||||
if (movement.hover > 0) {
|
||||
if (speed.length > 0) speed += '\n';
|
||||
speed += `${game.i18n.localize("DND5E.MovementHover")}: ${movement.hover + movement.units}`;
|
||||
}
|
||||
if (movement.swim > 0) {
|
||||
if (speed.length > 0) speed += '\n';
|
||||
speed += `${game.i18n.localize("DND5E.MovementSwim")}: ${movement.swim + movement.units}`;
|
||||
}
|
||||
if (movement.walk > 0) {
|
||||
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;
|
||||
return (initiative >= 0) ? `+${initiative}` : initiative;
|
||||
}
|
||||
|
||||
toggleInitiative(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getPassivePerception(token) {
|
||||
return token.actor.data.data.skills.prc.passive;
|
||||
}
|
||||
|
||||
getPassiveInvestigation(token) {
|
||||
return token.actor.data.data.skills.inv.passive;
|
||||
}
|
||||
|
||||
getAbility(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
return token.actor.data.data.abilities?.[ability].value;
|
||||
}
|
||||
|
||||
getAbilityModifier(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
let val = token.actor.data.data.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;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getSkill(token, skill) {
|
||||
if (skill == undefined) skill = 'acr';
|
||||
const val = token.actor.data.data.skills?.[skill].total;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getProficiency(token) {
|
||||
const val = token.actor.data.data.attributes.prof;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getConditionIcon(condition) {
|
||||
if (condition == undefined) condition = 'removeAll';
|
||||
if (condition == 'removeAll') return window.CONFIG.controlIcons.effects;
|
||||
else return CONFIG.statusEffects.find(e => e.id === condition).icon;
|
||||
}
|
||||
|
||||
getConditionActive(token,condition) {
|
||||
if (condition == undefined) condition = 'removeAll';
|
||||
return token.actor.effects.find(e => e.isTemporary === condition) != undefined;
|
||||
}
|
||||
|
||||
async toggleCondition(token,condition) {
|
||||
if (condition == undefined) condition = 'removeAll';
|
||||
if (condition == 'removeAll'){
|
||||
for( let effect of token.actor.effects)
|
||||
await effect.delete();
|
||||
}
|
||||
else {
|
||||
const effect = CONFIG.statusEffects.find(e => e.id === condition);
|
||||
await token.toggleEffect(effect);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll
|
||||
*/
|
||||
roll(token,roll,options,ability,skill,save) {
|
||||
if (roll == undefined) roll = 'ability';
|
||||
if (ability == undefined) ability = 'str';
|
||||
if (skill == undefined) skill = 'acr';
|
||||
if (save == undefined) save = 'str';
|
||||
|
||||
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 == 'deathSave') token.actor.rollDeathSave(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Items
|
||||
*/
|
||||
getItems(token,itemType) {
|
||||
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 return allItems.filter(i => i.type == itemType);
|
||||
}
|
||||
|
||||
getItemUses(item) {
|
||||
return {available: item.data.data.quantity};
|
||||
}
|
||||
|
||||
/**
|
||||
* Features
|
||||
*/
|
||||
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 return allItems.filter(i => i.type == featureType)
|
||||
}
|
||||
|
||||
getFeatureUses(item) {
|
||||
if (item.data.type == 'class') return {available: item.data.data.levels};
|
||||
else return {
|
||||
available: item.data.data.uses.value,
|
||||
maximum: item.data.data.uses.max
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Spells
|
||||
*/
|
||||
getSpells(token,level) {
|
||||
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)
|
||||
}
|
||||
|
||||
getSpellUses(token,level,item) {
|
||||
if (level == undefined) level = 'any';
|
||||
if (item.data.data.level == 0) return;
|
||||
return {
|
||||
available: token.actor.data.data.spells?.[`spell${level}`].value,
|
||||
maximum: token.actor.data.data.spells?.[`spell${level}`].max
|
||||
}
|
||||
}
|
||||
}
|
||||
195
src/systems/pf2e.js
Normal file
195
src/systems/pf2e.js
Normal file
@@ -0,0 +1,195 @@
|
||||
import {compatibleCore} from "../misc.js";
|
||||
|
||||
export class pf2e{
|
||||
constructor(){
|
||||
|
||||
}
|
||||
|
||||
getHP(token) {
|
||||
const hp = token.actor.data.data.attributes.hp;
|
||||
return {
|
||||
value: hp.value,
|
||||
max: hp.max
|
||||
}
|
||||
}
|
||||
|
||||
getTempHP(token) {
|
||||
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) {
|
||||
return token.actor.data.data.attributes.ac.value;
|
||||
}
|
||||
|
||||
getShieldHP(token) {
|
||||
return token.actor.data.data.attributes.shield.value;
|
||||
}
|
||||
|
||||
getSpeed(token) {
|
||||
let speed = token.actor.data.data.attributes.speed.breakdown;
|
||||
const otherSpeeds = token.actor.data.data.attributes.speed.otherSpeeds;
|
||||
if (otherSpeeds.length > 0)
|
||||
for (let i=0; i<otherSpeeds.length; i++)
|
||||
speed += `\n${otherSpeeds[i].type}: ${otherSpeeds[i].value}`;
|
||||
return speed;
|
||||
}
|
||||
|
||||
getInitiative(token) {
|
||||
let initiative = token.actor.data.data.attributes.init.value;
|
||||
return (initiative >= 0) ? `+${initiative}` : initiative;
|
||||
}
|
||||
|
||||
toggleInitiative(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getPassivePerception(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getPassiveInvestigation(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getAbility(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
return token.actor.data.data.abilities?.[ability].value;
|
||||
}
|
||||
|
||||
getAbilityModifier(token, ability) {
|
||||
if (ability == undefined) ability = 'str';
|
||||
let val = token.actor.data.data.abilities?.[ability].mod;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getAbilitySave(token, ability) {
|
||||
if (ability == undefined) ability = 'fortitude';
|
||||
else if (ability == 'fort') ability = 'fortitude';
|
||||
else if (ability == 'ref') ability = 'reflex';
|
||||
else if (ability == 'will') ability = 'will';
|
||||
let val = token.actor.data.data.saves?.[ability].value;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getSkill(token, skill) {
|
||||
if (skill == undefined) skill = 'acr';
|
||||
const val = token.actor.data.data.skills?.[skill].totalModifier;
|
||||
return (val >= 0) ? `+${val}` : val;
|
||||
}
|
||||
|
||||
getProficiency(token) {
|
||||
return;
|
||||
}
|
||||
|
||||
getCondition(token,condition) {
|
||||
if (condition == undefined || condition == 'removeAll') return undefined;
|
||||
const Condition = condition.charAt(0).toUpperCase() + condition.slice(1);
|
||||
const effects = token.actor.items.filter(i => i.type == 'condition');
|
||||
return effects.find(e => e.name === Condition);
|
||||
}
|
||||
|
||||
getConditionIcon(condition) {
|
||||
if (condition == undefined) condition = 'removeAll';
|
||||
if (condition == 'removeAll') return window.CONFIG.controlIcons.effects;
|
||||
else return `${CONFIG.PF2E.statusEffects.effectsIconFolder}${condition}.webp`;
|
||||
}
|
||||
|
||||
getConditionActive(token,condition) {
|
||||
return this.getCondition(token,condition) != undefined;
|
||||
}
|
||||
|
||||
async toggleCondition(token,condition) {
|
||||
if (condition == undefined) condition = 'removeAll';
|
||||
if (condition == 'removeAll'){
|
||||
for( let effect of token.actor.items.filter(i => i.type == 'condition'))
|
||||
await effect.delete();
|
||||
}
|
||||
else {
|
||||
const effect = this.getCondition(token,condition);
|
||||
if (effect == undefined) {
|
||||
const Condition = condition.charAt(0).toUpperCase() + condition.slice(1);
|
||||
const newCondition = game.pf2e.ConditionManager.getCondition(Condition);
|
||||
newCondition.data.sources.hud = !0,
|
||||
await game.pf2e.ConditionManager.addConditionToToken(newCondition, token);
|
||||
}
|
||||
else {
|
||||
effect.delete();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll
|
||||
*/
|
||||
roll(token,roll,options,ability,skill,save) {
|
||||
if (roll == undefined) roll = 'ability';
|
||||
if (ability == undefined) ability = 'str';
|
||||
if (skill == undefined) skill = 'acr';
|
||||
if (save == undefined) save = 'fort';
|
||||
|
||||
if (roll == 'ability') token.actor.data.data.abilities?.[ability].roll(options);
|
||||
else if (roll == 'save') {
|
||||
let ability = save;
|
||||
if (ability == 'fort') ability = 'fortitude';
|
||||
else if (ability == 'ref') ability = 'reflex';
|
||||
else if (ability == 'will') ability = 'will';
|
||||
token.actor.data.data.saves?.[ability].roll(options);
|
||||
}
|
||||
else if (roll == 'skill') token.actor.data.data.skills?.[skill].roll(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Items
|
||||
*/
|
||||
getItems(token,itemType) {
|
||||
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 return allItems.filter(i => i.type == itemType);
|
||||
}
|
||||
|
||||
getItemUses(item) {
|
||||
return {available: item.data.data.quantity.value};
|
||||
}
|
||||
|
||||
/**
|
||||
* Features
|
||||
*/
|
||||
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 return allItems.filter(i => i.type == featureType)
|
||||
}
|
||||
|
||||
getFeatureUses(item) {
|
||||
if (item.data.type == 'class') return {available: item.actor.data.data.details.level.value};
|
||||
else return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Spells
|
||||
*/
|
||||
getSpells(token,level) {
|
||||
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.value == level)
|
||||
}
|
||||
|
||||
getSpellUses(token,level,item) {
|
||||
if (level == undefined) level = 'any';
|
||||
if (item.data.data.level.value == 0) return;
|
||||
const spellbook = token.actor.items.filter(i => i.data.type === 'spellcastingEntry')[0];
|
||||
if (spellbook == undefined) return;
|
||||
return {
|
||||
available: spellbook.data.data.slots?.[`slot${level}`].value,
|
||||
maximum: spellbook.data.data.slots?.[`slot${level}`].max
|
||||
}
|
||||
}
|
||||
}
|
||||
241
src/systems/tokenHelper.js
Normal file
241
src/systems/tokenHelper.js
Normal file
@@ -0,0 +1,241 @@
|
||||
import {dnd5e} from "./dnd5e.js"
|
||||
import {dnd35e} from "./dnd35e.js"
|
||||
import {pf2e} from "./pf2e.js"
|
||||
import {demonlord} from "./demonlord.js";
|
||||
import {compatibleCore} from "../misc.js";
|
||||
|
||||
export class TokenHelper{
|
||||
constructor(){
|
||||
this.system;
|
||||
this.setSystem();
|
||||
}
|
||||
|
||||
setSystem() {
|
||||
if (game.system.id == 'D35E' || game.system.id == 'pf1') this.system = new dnd35e();
|
||||
else if (game.system.id == 'pf2e') this.system = new pf2e();
|
||||
else if (game.system.id == 'demonlord') this.system = new demonlord();
|
||||
else this.system = new dnd5e(); //default to dnd5e
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* System agnostic functions
|
||||
***********************************************************************/
|
||||
getToken(type,identifier) {
|
||||
if (type == 'selected') return this.getSelectedToken();
|
||||
else if (type != 'selected' && identifier == '') return;
|
||||
else if (type == 'tokenName') return this.getTokenFromTokenName(identifier);
|
||||
else if (type == 'actorName') return this.getTokenFromActorName(identifier);
|
||||
else if (type == 'tokenId') return this.getTokenFromTokenId(identifier);
|
||||
else if (type == 'actorId') return this.getTokenFromActorId(identifier);
|
||||
}
|
||||
getTokenFromTokenId(id) {
|
||||
return canvas.tokens.children[0].children.find(p => p.id == id);
|
||||
}
|
||||
|
||||
getTokenFromTokenName(name) {
|
||||
return canvas.tokens.children[0].children.find(p => p.name == name);
|
||||
}
|
||||
|
||||
getTokenFromActorId(id) {
|
||||
return canvas.tokens.children[0].children.find(p => p.actor.id == id);
|
||||
}
|
||||
|
||||
getTokenFromActorName(name) {
|
||||
return canvas.tokens.children[0].children.find(p => p.actor.name == name);
|
||||
}
|
||||
|
||||
getSelectedToken() {
|
||||
return canvas.tokens.controlled[0];
|
||||
}
|
||||
|
||||
moveToken(token,dir){
|
||||
if (dir == undefined) dir = 'up';
|
||||
const gridSize = canvas.scene.data.grid;
|
||||
let x = token.x;
|
||||
let y = token.y;
|
||||
|
||||
if (dir == 'up') y -= gridSize;
|
||||
else if (dir == 'down') y += gridSize;
|
||||
else if (dir == 'right') x += gridSize;
|
||||
else if (dir == 'left') x -= gridSize;
|
||||
else if (dir == 'upRight') {
|
||||
x += gridSize;
|
||||
y -= gridSize;
|
||||
}
|
||||
else if (dir == 'upLeft') {
|
||||
x -= gridSize;
|
||||
y -= gridSize;
|
||||
}
|
||||
else if (dir == 'downRight') {
|
||||
x += gridSize;
|
||||
y += gridSize;
|
||||
}
|
||||
else if (dir == 'downLeft') {
|
||||
x -= gridSize;
|
||||
y += gridSize;
|
||||
}
|
||||
else if (dir == 'center') {
|
||||
let location = token.getCenter(x,y);
|
||||
canvas.animatePan(location);
|
||||
}
|
||||
if (game.user.isGM == false && game.paused == true && (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});
|
||||
};
|
||||
|
||||
rotateToken(token,move,value) {
|
||||
if (move == undefined) move = 'to';
|
||||
value = isNaN(parseInt(value)) ? 0 : parseInt(value);
|
||||
|
||||
let rotationVal;
|
||||
if (move == 'by') rotationVal = token.data.rotation + value;
|
||||
else rotationVal = value;
|
||||
|
||||
if (compatibleCore("0.8.1")) token.document.update({rotation: rotationVal});
|
||||
else token.update({rotation: rotationVal});
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Get name/id
|
||||
*/
|
||||
getTokenName(token) {
|
||||
return token.name;
|
||||
}
|
||||
|
||||
getTokenId(token) {
|
||||
return token.id;
|
||||
}
|
||||
|
||||
getActorName(token) {
|
||||
return token.actor.name;
|
||||
}
|
||||
|
||||
getActorId(token) {
|
||||
return token.actor.id;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
getTokenIcon(token) {
|
||||
return token.data.img;
|
||||
}
|
||||
|
||||
getActorIcon(token) {
|
||||
return token.actor.data.img;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* System agnostic functions
|
||||
***********************************************************************/
|
||||
getHP(token) {
|
||||
return this.system.getHP(token);
|
||||
}
|
||||
|
||||
getTempHP(token) {
|
||||
return this.system.getTempHP(token);
|
||||
}
|
||||
|
||||
getAC(token) {
|
||||
return this.system.getAC(token);
|
||||
}
|
||||
|
||||
getShieldHP(token) {
|
||||
return this.system.getShieldHP(token);
|
||||
}
|
||||
|
||||
getSpeed(token) {
|
||||
return this.system.getSpeed(token);
|
||||
}
|
||||
|
||||
getInitiative(token) {
|
||||
return this.system.getInitiative(token);
|
||||
}
|
||||
|
||||
toggleInitiative(token) {
|
||||
return this.system.toggleInitiative(token);
|
||||
}
|
||||
|
||||
getPassivePerception(token) {
|
||||
return this.system.getPassivePerception(token);
|
||||
}
|
||||
|
||||
getPassiveInvestigation(token) {
|
||||
return this.system.getPassiveInvestigation(token);
|
||||
}
|
||||
|
||||
getAbility(token, ability) {
|
||||
return this.system.getAbility(token, ability);
|
||||
}
|
||||
|
||||
getAbilityModifier(token, ability) {
|
||||
return this.system.getAbilityModifier(token, ability);
|
||||
}
|
||||
|
||||
getAbilitySave(token, ability) {
|
||||
return this.system.getAbilitySave(token, ability);
|
||||
}
|
||||
|
||||
getSkill(token, skill) {
|
||||
return this.system.getSkill(token, skill);
|
||||
}
|
||||
|
||||
getProficiency(token) {
|
||||
return this.system.getProficiency(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Conditions
|
||||
*/
|
||||
getConditionIcon(condition) {
|
||||
return this.system.getConditionIcon(condition);
|
||||
}
|
||||
|
||||
getConditionActive(token,condition) {
|
||||
return this.system.getConditionActive(token,condition);
|
||||
}
|
||||
|
||||
toggleCondition(token,condition) {
|
||||
return this.system.toggleCondition(token,condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Roll
|
||||
*/
|
||||
roll(token,roll,options,ability,skill,save) {
|
||||
return this.system.roll(token,roll,options,ability,skill,save);
|
||||
}
|
||||
|
||||
/**
|
||||
* Items
|
||||
*/
|
||||
getItems(token,itemType) {
|
||||
return this.system.getItems(token,itemType);
|
||||
}
|
||||
|
||||
getItemUses(item) {
|
||||
return this.system.getItemUses(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Features
|
||||
*/
|
||||
getFeatures(token,featureType) {
|
||||
return this.system.getFeatures(token,featureType);
|
||||
}
|
||||
|
||||
getFeatureUses(item) {
|
||||
return this.system.getFeatureUses(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spells
|
||||
*/
|
||||
getSpells(token,level) {
|
||||
return this.system.getSpells(token,level);
|
||||
}
|
||||
|
||||
getSpellUses(token,level,item) {
|
||||
return this.system.getSpellUses(token,level,item);
|
||||
}
|
||||
}
|
||||
1432
src/token.js
1432
src/token.js
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user