This commit is contained in:
Cristian Deenen
2023-05-28 13:50:41 +02:00
parent 631fdbcccb
commit b07f0a6454
33 changed files with 1838 additions and 661 deletions

View File

@@ -1,4 +1,5 @@
import { streamDeck, tokenControl, getPermission } from "../../MaterialDeck.js";
import { } from "../misc.js";
export class CombatTracker{
constructor(){
@@ -18,40 +19,70 @@ export class CombatTracker{
}
}
applyFilter(combatant, settings) {
let conf = {
forceIcon: undefined,
hideName: false
}
const disposition = combatant.token.disposition;
const hidden = combatant.token.hidden;
const visibilityMode = settings.visibilityMode ? settings.visibilityMode : 'remove';
const dispositionMode = settings.dispositionMode ? settings.dispositionMode : 'remove';
if (hidden && (settings.visibilityFilter == 'all' || (settings.visibilityFilter == 'hostileNeutral' && disposition != 1) || (settings.visibilityFilter == 'hostile' && disposition == -1))) {
if (visibilityMode == 'black' || visibilityMode == 'remove') conf.forceIcon = "modules/MaterialDeck/img/black.png";
else if (visibilityMode == 'mysteryMan') conf.forceIcon = "modules/MaterialDeck/img/token/mystery-man.png";
else if (visibilityMode == 'hideName') conf.hideName = true;
}
if ((settings.dispositionFilter == 'friendlyNeutral' && disposition == -1) || (settings.dispositionFilter == 'friendly' && disposition != 1)) {
if (conf.forceIcon == undefined && (dispositionMode == 'black' || dispositionMode == 'remove')) conf.forceIcon = "modules/MaterialDeck/img/black.png";
else if (conf.forceIcon == undefined && dispositionMode == 'mysteryMan') conf.forceIcon = "modules/MaterialDeck/img/token/mystery-man.png";
else if (dispositionMode == 'hideName') conf.hideName = true;
}
return conf;
}
update(settings,context,device){
this.active = true;
const ctFunction = settings.combatTrackerFunction ? settings.combatTrackerFunction : 'startStop';
const mode = settings.combatTrackerMode ? settings.combatTrackerMode : 'combatants';
settings.combatTrackerMode = mode;
const combat = game.combat;
let src = "modules/MaterialDeck/img/black.png";
let txt = "";
let background = "#000000";
settings.combat = true;
settings.icon = settings.displayIcon ? 'tokenIcon' : 'none';
if (mode == 'combatants'){
if (getPermission('COMBAT','DISPLAY_COMBATANTS') == false) {
streamDeck.noPermission(context,device,device,false,"combat tracker");
return;
}
if (combat != null && combat != undefined && combat.turns.length != 0){
const initiativeOrder = combat.turns;
let nr = settings.combatantNr - 1;
if (nr == undefined || nr < 1) nr = 0;
const combatantState = (nr == combat.turn) ? 2 : 1;
let initiativeOrder = combat.turns;
const dispositionMode = settings.dispositionMode ? settings.dispositionMode : 'remove';
if (dispositionMode == 'remove' && settings.dispositionFilter == 'friendly') initiativeOrder = initiativeOrder.filter(c => c.token.disposition == 1);
else if (dispositionMode == 'remove' && settings.dispositionFilter == 'friendlyNeutral') initiativeOrder = initiativeOrder.filter(c => c.token.disposition != -1);
const visibilityMode = settings.visibilityMode ? settings.visibilityMode : 'none';
if (visibilityMode == 'remove' && settings.visibilityFilter == 'hostile') initiativeOrder = initiativeOrder.filter(c => c.token.disposition != -1 && c.token.hidden == false)
else if (visibilityMode == 'remove' && settings.visibilityFilter == 'hostileNeutral') initiativeOrder = initiativeOrder.filter(c => c.token.disposition == 1 && c.token.hidden == false)
else if (visibilityMode == 'remove' && settings.visibilityFilter == 'all') initiativeOrder = initiativeOrder.filter(c => c.token.hidden == false)
const nr = settings.combatantNr ? settings.combatantNr - 1 : 0;
const combatant = initiativeOrder[nr]
const combatantState = (combatant?.token.id == combat.current.tokenId) ? 2 : 1;
if (combatant != undefined){
const tokenId = combatant.data.tokenId;
tokenControl.pushData(tokenId,settings,context,device,combatantState,'#cccc00');
const filterConfig = this.applyFilter(combatant, settings);
const tokenId = combatant.token.id;
tokenControl.pushData(tokenId,settings,context,device,combatantState,'#cccc00', filterConfig.forceIcon, filterConfig.hideName);
return;
}
else {
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background});
streamDeck.setTitle(txt,context);
}
}
else {
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background});
streamDeck.setTitle(txt,context);
}
@@ -62,10 +93,12 @@ export class CombatTracker{
return;
}
if (combat != null && combat != undefined && combat.started){
const tokenId = combat.combatant.data.tokenId;
tokenControl.pushData(tokenId,settings,context,device);
const filterConfig = this.applyFilter(combat.combatant, settings);
const tokenId = combat.combatant.token.id;
tokenControl.pushData(tokenId,settings,context,device,undefined,undefined, filterConfig.forceIcon, filterConfig.hideName);
}
else {
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background});
streamDeck.setTitle(txt,context);
}
@@ -131,6 +164,11 @@ export class CombatTracker{
else if (ctFunction == 'rollInitiative' || ctFunction == 'rollInitiativeNPC')
src = "modules/MaterialDeck/img/token/init.png";
if (settings.iconOverride != '' && settings.iconOverride != undefined) {
src = settings.iconOverride;
background = settings.background ? settings.background : '#000000'
}
streamDeck.setIcon(context,device,src,{background:background});
streamDeck.setTitle(txt,context);
}
@@ -193,12 +231,12 @@ export class CombatTracker{
if (nr == undefined || nr < 1) nr = 0;
const combatant = initiativeOrder[nr]
if (combatant == undefined) return;
tokenId = combatant.data.tokenId;
tokenId = combatant.token.id;
}
}
else if (mode == 'currentCombatant')
if (combat != null && combat != undefined && combat.started)
tokenId = combat.combatant.data.tokenId;
tokenId = combat.combatant.token.id;
let token = (canvas.tokens.children[0] != undefined) ? canvas.tokens.children[0].children.find(p => p.id == tokenId) : undefined;
if (token == undefined) return;

View File

@@ -1,5 +1,5 @@
import { streamDeck } from "../../MaterialDeck.js";
import { compatibleCore } from "../misc.js";
import { } from "../misc.js";
export class ExternalModules{
soundscapeSettings = {
@@ -60,15 +60,13 @@ export class ExternalModules{
update(settings,context,device){
this.active = true;
const module = settings.module ? settings.module : 'fxmaster';
if (module == 'fxmaster') this.updateFxMaster(settings,context,device);
else if (module == 'gmscreen') this.updateGMScreen(settings,context,device);
else if (module == 'triggerHappy') this.updateTriggerHappy(settings,context,device);
else if (module == 'sharedVision') this.updateSharedVision(settings,context,device);
else if (module == 'mookAI') this.updateMookAI(settings,context,device);
else if (module == 'notYourTurn') this.updateNotYourTurn(settings,context,device);
else if (module == 'lockView') this.updateLockView(settings,context,device);
else if (module == 'aboutTime') this.updateAboutTime(settings,context,device);
else if (module == 'simpleCalendar') this.updateSimpleCalendar(settings,context,device);
else if (module == 'soundscape') this.updateSoundscape(settings,context,device);
else if (module == 'monksActiveTiles') this.updateMonksActiveTiles(settings,context,device);
}
@@ -81,10 +79,9 @@ export class ExternalModules{
else if (module == 'gmscreen') this.keyPressGMScreen(settings,context,device);
else if (module == 'triggerHappy') this.keyPressTriggerHappy(settings,context,device);
else if (module == 'sharedVision') this.keyPressSharedVision(settings,context,device);
else if (module == 'mookAI') this.keyPressMookAI(settings,context,device);
else if (module == 'notYourTurn') this.keyPressNotYourTurn(settings,context,device);
else if (module == 'lockView') this.keyPressLockView(settings,context,device);
else if (module == 'aboutTime') this.keyPressAboutTime(settings,context,device);
else if (module == 'simpleCalendar') this.keyPressSimpleCalendar(settings,context,device);
else if (module == 'soundscape') this.keyPressSoundscape(settings,context,device);
else if (module == 'monksActiveTiles') this.keyPressMonksActiveTiles(settings,context,device);
}
@@ -114,14 +111,14 @@ export class ExternalModules{
let name = '';
if (type == 'weatherControls') {
const effect = (settings.weatherEffect == undefined) ? 'leaves' : settings.weatherEffect;
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;
name =game.i18n.localize(CONFIG.fxmaster.particleEffects[effect].label);
icon = CONFIG.fxmaster.particleEffects[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 = compatibleCore('10.0') ? game.i18n.localize(CONFIG.fxmaster.filterEffects[filter].label) : CONFIG.fxmaster.filters[filter].label;
name = game.i18n.localize(CONFIG.fxmaster.filterEffects[filter].label);
background = "#340057";
if (displayIcon){
if (filter == 'lightning') icon = "fas fa-bolt";
@@ -150,6 +147,7 @@ export class ExternalModules{
name = game.i18n.localize("MaterialDeck.FxMaster.Clear");
}
if (settings.iconOverride != '' && settings.iconOverride != undefined) icon = settings.iconOverride;
if (displayIcon) streamDeck.setIcon(context,device,icon,{background:background,ring:ring,ringColor:ringColor});
else streamDeck.setIcon(context,device, "", {background:background,ring:ring,ringColor:ringColor});
if (displayName == 0) name = "";
@@ -175,7 +173,7 @@ export class ExternalModules{
applyColor: (settings.fxWeatherEnColor == undefined) ? false : settings.fxWeatherEnColor
}
Hooks.call(compatibleCore('10.0') ? "fxmaster.switchParticleEffect" : "fxmaster.switchWeather", {
Hooks.call("fxmaster.switchParticleEffect", {
name: `core_${effect}`,
type: effect,
options,
@@ -236,7 +234,6 @@ export class ExternalModules{
updateGMScreen(settings,context,device){
if (this.getModuleEnable("gm-screen") == false) return;
if (game.user.isGM == false) return;
const background = settings.gmScreenBackground ? settings.gmScreenBackground : '#000000';
let ring = 1;
const ringColor = '#00FF00'
@@ -246,6 +243,7 @@ export class ExternalModules{
if (this.gmScreenOpen) ring = 2;
if (settings.displayGmScreenIcon) src = "fas fa-book-reader";
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background,ring:ring,ringColor:ringColor});
if (settings.displayGmScreenName) txt = game.i18n.localize(`GMSCR.gmScreen.Open`);
streamDeck.setTitle(txt,context);
@@ -272,7 +270,9 @@ export class ExternalModules{
const ringColor = game.settings.get("trigger-happy", "enableTriggers") ? "#A600FF" : "#340057";
let txt = '';
if (displayIcon) streamDeck.setIcon(context,device,"fas fa-grin-squint-tears",{background:background,ring:2,ringColor:ringColor});
let src = "fas fa-grin-squint-tears";
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
if (displayIcon) streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor});
else streamDeck.setIcon(context,device,'',{background:'#000000'});
if (displayName) txt = 'Trigger Happy';
@@ -313,7 +313,9 @@ export class ExternalModules{
const ringColor = game.settings.get("SharedVision", "enable") ? "#A600FF" : "#340057";
let txt = '';
if (displayIcon) streamDeck.setIcon(context,device,"fas fa-eye",{background:background,ring:2,ringColor:ringColor});
let src = "fas fa-eye";
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
if (displayIcon) streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor});
else streamDeck.setIcon(context,device,'',{background:'#000000'});
if (displayName) txt = 'Shared Vision';
streamDeck.setTitle(txt,context);
@@ -330,34 +332,6 @@ export class ExternalModules{
else if (mode == 'disable') Hooks.call("setShareVision",{enable:false});
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Mook AI
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
updateMookAI(settings,context,device) {
if (this.getModuleEnable("mookAI") == false) return;
if (game.user.isGM == false) return;
const displayName = settings.mookName ? settings.mookName : false;
const displayIcon = settings.mookIcon ? settings.mookIcon : false;
const background = "#000000";
let txt = '';
if (displayIcon) streamDeck.setIcon(context,device,"fas fa-brain",{background:'#000000'});
else streamDeck.setIcon(context,device,'',{background:'#000000'});
if (displayName) txt = 'Mook AI';
streamDeck.setTitle(txt,context);
}
async keyPressMookAI(settings,context,device) {
if (this.getModuleEnable("mookAI") == false) return;
if (game.user.isGM == false) return;
let mook = await import('../../mookAI/scripts/mookAI.js');
let mookAI = new mook.MookAI ();
mookAI.takeNextTurn();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Not Your Turn!
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -385,6 +359,7 @@ export class ExternalModules{
txt = "Block Non-Combat Movement";
ringColor = game.settings.get('NotYourTurn','nonCombat') ? "#A600FF": "#340057" ;
}
if (settings.iconOverride != '' && settings.iconOverride != undefined) icon = settings.iconOverride;
if (displayIcon) streamDeck.setIcon(context,device,icon,{background:background,ring:2,ringColor:ringColor});
else streamDeck.setIcon(context,device,'',{background:'#000000'});
if (displayName == false) txt = '';
@@ -439,6 +414,7 @@ export class ExternalModules{
ringColor = canvas.scene.getFlag('LockView', 'boundingBox') ? "#A600FF": "#340057" ;
}
if (settings.iconOverride != '' && settings.iconOverride != undefined) icon = settings.iconOverride;
if (displayIcon) streamDeck.setIcon(context,device,icon,{background:background,ring:2,ringColor:ringColor});
else streamDeck.setIcon(context,device,'',{background:'#000000'});
if (displayName == false) txt = '';
@@ -465,20 +441,20 @@ export class ExternalModules{
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//About Time
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
updateAboutTime(settings,context,device) {
if (this.getModuleEnable("about-time") == false) return;
updateSimpleCalendar(settings,context,device) {
if (this.getModuleEnable("foundryvtt-simple-calendar") == false) return;
if (game.user.isGM == false) return;
const displayTime = settings.aboutTimeDisplayTime ? settings.aboutTimeDisplayTime : 'none';
const displayDate = settings.aboutTimeDisplayDate ? settings.aboutTimeDisplayDate : 'none';
const background = settings.aboutTimeBackground ? settings.aboutTimeBackground : '#000000';
const ringOffColor = settings.aboutTimeOffRing ? settings.aboutTimeOffRing : '#000000';
const ringOnColor = settings.aboutTimeOnRing ? settings.aboutTimeOnRing : '#00FF00';
const displayTime = settings.simpleCalendarDisplayTime ? settings.simpleCalendarDisplayTime : 'none';
const displayDate = settings.simpleCalendarDisplayDate ? settings.simpleCalendarDisplayDate : 'none';
const background = settings.simpleCalendarBackground ? settings.simpleCalendarBackground : '#000000';
const ringOffColor = settings.simpleCalendarOffRing ? settings.simpleCalendarOffRing : '#000000';
const ringOnColor = settings.simpleCalendarOnRing ? settings.simpleCalendarOnRing : '#00FF00';
let ring = 0;
let ringColor = '#000000';
let txt = '';
let currentTime = game.Gametime.DTNow().longDateExtended();
let currentTime = SimpleCalendar.api.currentDateTime();
let clock = 'none';
if (displayTime == 'clock') {
@@ -504,172 +480,112 @@ export class ExternalModules{
}
if (displayTime == 'hours24h' || displayTime == 'hours12h') txt = hours;
else if (displayTime == 'minutes') txt = currentTime.minute;
else if (displayTime == 'seconds') txt = currentTime.second;
else if (displayTime == 'seconds') txt = currentTime.seconds;
else {
if (currentTime.minute < 10) currentTime.minute = '0' + currentTime.minute;
if (currentTime.second < 10) currentTime.second = '0' + currentTime.second;
if (currentTime.seconds < 10) currentTime.seconds = '0' + currentTime.seconds;
txt += hours + ':' + currentTime.minute;
if (displayTime == 'full24h' || displayTime == 'full12h') txt += ':' + currentTime.second;
if (displayTime == 'full24h' || displayTime == 'full12h') txt += ':' + currentTime.seconds;
}
if (displayTime == 'compact12h' || displayTime == 'full12h' || displayTime == 'hours12h') txt += AMPM;
}
if (displayTime != 'none' && displayTime != 'clock' && displayDate != 'none') txt += '\n';
if (displayDate == 'day') txt += currentTime.day;
else if (displayDate == 'dayName') txt += currentTime.dowString;
else if (displayDate == 'dayName') txt += SimpleCalendar.api.getCurrentWeekday().name;
else if (displayDate == 'month') txt += currentTime.month;
else if (displayDate == 'monthName') txt += currentTime.monthString;
else if (displayDate == 'monthName') txt += SimpleCalendar.api.getCurrentMonth().name;
else if (displayDate == 'year') txt += currentTime.year;
else if (displayDate == 'small') txt += currentTime.day + '-' + currentTime.month;
else if (displayDate == 'smallInv') txt += currentTime.month + '-' + currentTime.day;
else if (displayDate == 'full') txt += currentTime.day + '-' + currentTime.month + '-' + currentTime.year;
else if (displayDate == 'fullInv') txt += currentTime.month + '-' + currentTime.day + '-' + currentTime.year;
else if (displayDate == 'text' || displayDate == 'textDay') {
if (displayDate == 'textDay') txt += currentTime.dowString + ' ';
else if (displayDate == 'text' || displayDate == 'textDay' || displayDate == 'textAbbr' || displayDate == 'textDayAbbr') {
if (displayDate == 'textDay') txt += SimpleCalendar.api.getCurrentWeekday().name + ' ';
else if (displayDate == 'textDayAbbr') txt += SimpleCalendar.api.getCurrentWeekday().abbreviation + ' ';
txt += currentTime.day;
if (currentTime.day % 10 == 1 && currentTime != 11) txt += game.i18n.localize("MaterialDeck.AboutTime.First");
else if (currentTime.day % 10 == 2 && currentTime != 12) txt += game.i18n.localize("MaterialDeck.AboutTime.Second");
else if (currentTime.day % 10 == 3 && currentTime != 13) txt += game.i18n.localize("MaterialDeck.AboutTime.Third");
else txt += game.i18n.localize("MaterialDeck.AboutTime.Fourth");
txt += ' ' + game.i18n.localize("MaterialDeck.AboutTime.Of") + ' ' + currentTime.monthString + ', ' + currentTime.year;
if (currentTime.day % 10 == 1 && currentTime != 11) txt += game.i18n.localize("MaterialDeck.SimpleCalendar.First");
else if (currentTime.day % 10 == 2 && currentTime != 12) txt += game.i18n.localize("MaterialDeck.SimpleCalendar.Second");
else if (currentTime.day % 10 == 3 && currentTime != 13) txt += game.i18n.localize("MaterialDeck.SimpleCalendar.Third");
else txt += game.i18n.localize("MaterialDeck.SimpleCalendar.Fourth");
txt += ' ' + game.i18n.localize("MaterialDeck.SimpleCalendar.Of") + ' '
if (displayDate == 'textAbbr' || displayDate == 'textDayAbbr') txt += SimpleCalendar.api.getCurrentMonth().abbreviation
else txt += SimpleCalendar.api.getCurrentMonth().name
txt += ', ' + currentTime.year;
}
if (settings.aboutTimeActive) {
const clockRunning = game.Gametime.isRunning();
if (settings.simpleCalendarActive) {
const clockRunning = SimpleCalendar.api.clockStatus().started;
ringColor = clockRunning ? ringOnColor : ringOffColor;
ring = 2;
}
streamDeck.setTitle(txt,context);
streamDeck.setTitle(txt.toString(),context);
streamDeck.setIcon(context,device,'',{background:background,ring:ring,ringColor:ringColor, clock:clock});
}
keyPressAboutTime(settings,context,device) {
if (this.getModuleEnable("about-time") == false) return;
keyPressSimpleCalendar(settings,context,device) {
if (this.getModuleEnable("foundryvtt-simple-calendar") == false) return;
if (game.user.isGM == false) return;
const onClick = settings.aboutTimeOnClick ? settings.aboutTimeOnClick : 'none';
const onClick = settings.simpleCalendarOnClick ? settings.simpleCalendarOnClick : 'none';
if (onClick == 'none') return;
else if (onClick == 'startStop') {
const clockRunning = game.Gametime.isRunning();
const startMode = settings.aboutTimeStartStopMode ? settings.aboutTimeStartStopMode : 'toggle';
if ((startMode == 'toggle' && clockRunning) || startMode == 'stop') game.Gametime.stopRunning();
else if ((startMode == 'toggle' && !clockRunning) || startMode == 'start') game.Gametime.startRunning();
const clockRunning = SimpleCalendar.api.clockStatus().started;
const startMode = settings.simpleCalendarStartStopMode ? settings.simpleCalendarStartStopMode : 'toggle';
if (clockRunning && (startMode == 'toggle' || startMode == 'stop')) SimpleCalendar.api.stopClock();
else if (!clockRunning && (startMode == 'toggle' || startMode == 'start')) SimpleCalendar.api.startClock();
}
else if (onClick == 'advance') {
const advanceMode = settings.aboutTimeAdvanceMode ? settings.aboutTimeAdvanceMode : 'dawn';
let now = Gametime.DTNow();
if (advanceMode == 'dawn') {
let newDT = now.add({
days: now.hours < 7 ? 0 : 1
}).setAbsolute({
hours: 7,
minutes: 0,
seconds: 0
});
Gametime.setAbsolute(newDT);
}
else if (advanceMode == 'noon') {
let newDT = now.add({
days: now.hours < 12 ? 0 : 1
}).setAbsolute({
hours: 12,
minutes: 0,
seconds: 0
});
Gametime.setAbsolute(newDT);
}
else if (advanceMode == 'dusk') {
let newDT = now.add({
days: now.hours < 20 ? 0 : 1
}).setAbsolute({
hours: 20,
minutes: 0,
seconds: 0
});
Gametime.setAbsolute(newDT);
}
else if (advanceMode == 'midnight') {
let newDT = Gametime.DTNow().add({
days: 1
}).setAbsolute({
hours: 0,
minutes: 0,
seconds: 0
});
Gametime.setAbsolute(newDT);
}
else if (advanceMode == '1s')
game.Gametime.advanceClock(1);
else if (advanceMode == '30s')
game.Gametime.advanceClock(30);
else if (advanceMode == '1m')
game.Gametime.advanceTime({ minutes: 1 });
else if (advanceMode == '5m')
game.Gametime.advanceTime({ minutes: 5 });
else if (advanceMode == '15m')
game.Gametime.advanceTime({ minutes: 15 });
else if (advanceMode == '1h')
game.Gametime.advanceTime({ hours: 1 });
const advanceMode = settings.simpleCalendarAdvanceMode ? settings.simpleCalendarAdvanceMode : 'dawn';
if (advanceMode == 'sunrise') SimpleCalendar.api.advanceTimeToPreset(SimpleCalendar.api.PresetTimeOfDay.Sunrise);
if (advanceMode == 'midday') SimpleCalendar.api.advanceTimeToPreset(SimpleCalendar.api.PresetTimeOfDay.Midday);
if (advanceMode == 'sunset') SimpleCalendar.api.advanceTimeToPreset(SimpleCalendar.api.PresetTimeOfDay.Sunset);
if (advanceMode == 'midnight') SimpleCalendar.api.advanceTimeToPreset(SimpleCalendar.api.PresetTimeOfDay.Midnight);
else if (advanceMode == '1s') SimpleCalendar.api.changeDate({seconds: 1});
else if (advanceMode == '30s') SimpleCalendar.api.changeDate({seconds: 30});
else if (advanceMode == '1m') SimpleCalendar.api.changeDate({minute: 1});
else if (advanceMode == '5m') SimpleCalendar.api.changeDate({minute: 5});
else if (advanceMode == '15m') SimpleCalendar.api.changeDate({minute: 15});
else if (advanceMode == '1h') SimpleCalendar.api.changeDate({hour: 1});
else if (advanceMode == '6h') SimpleCalendar.api.changeDate({hour: 6});
else if (advanceMode == '12h') SimpleCalendar.api.changeDate({hour: 12});
else if (advanceMode == '1d') SimpleCalendar.api.changeDate({day: 1});
else if (advanceMode == '7d') SimpleCalendar.api.changeDate({day: 7});
else if (advanceMode == '1M') SimpleCalendar.api.changeDate({month: 1});
else if (advanceMode == '1y') SimpleCalendar.api.changeDate({year: 1});
}
else if (onClick == 'recede') {
const advanceMode = settings.aboutTimeAdvanceMode ? settings.aboutTimeAdvanceMode : 'dawn';
let now = Gametime.DTNow();
if (advanceMode == 'dawn') {
let newDT = now.add({
days: now.hours < 7 ? -1 : 0
}).setAbsolute({
hours: 7,
minutes: 0,
seconds: 0
});
Gametime.setAbsolute(newDT);
const advanceMode = settings.simpleCalendarAdvanceMode ? settings.simpleCalendarAdvanceMode : 'dawn';
let now = SimpleCalendar.api.currentDateTime();
if (advanceMode == 'sunrise') {
SimpleCalendar.api.changeDate({day: -1});
SimpleCalendar.api.advanceTimeToPreset(SimpleCalendar.api.PresetTimeOfDay.Sunrise);
}
else if (advanceMode == 'noon') {
let newDT = now.add({
days: now.hours < 12 ? -1 : 0
}).setAbsolute({
hours: 12,
minutes: 0,
seconds: 0
});
Gametime.setAbsolute(newDT);
else if (advanceMode == 'midday') {
SimpleCalendar.api.changeDate({day: -1});
SimpleCalendar.api.advanceTimeToPreset(SimpleCalendar.api.PresetTimeOfDay.Midday);
}
else if (advanceMode == 'dusk') {
let newDT = now.add({
days: now.hours < 20 ? -1 : 0
}).setAbsolute({
hours: 20,
minutes: 0,
seconds: 0
});
Gametime.setAbsolute(newDT);
else if (advanceMode == 'sunset') {
SimpleCalendar.api.changeDate({day: -1});
SimpleCalendar.api.advanceTimeToPreset(SimpleCalendar.api.PresetTimeOfDay.Sunset);
}
else if (advanceMode == 'midnight') {
let newDT = Gametime.DTNow().add({
days: -1
}).setAbsolute({
hours: 0,
minutes: 0,
seconds: 0
});
Gametime.setAbsolute(newDT);
SimpleCalendar.api.changeDate({day: -1});
SimpleCalendar.api.advanceTimeToPreset(SimpleCalendar.api.PresetTimeOfDay.Midnight);
}
else if (advanceMode == '1s')
game.Gametime.advanceClock(-1);
else if (advanceMode == '30s')
game.Gametime.advanceClock(-30);
else if (advanceMode == '1m')
game.Gametime.advanceTime({ minutes: -1 });
else if (advanceMode == '5m')
game.Gametime.advanceTime({ minutes: -5 });
else if (advanceMode == '15m')
game.Gametime.advanceTime({ minutes: -15 });
else if (advanceMode == '1h')
game.Gametime.advanceTime({ hours: -1 });
else if (advanceMode == '1s') SimpleCalendar.api.changeDate({seconds: -1});
else if (advanceMode == '30s') SimpleCalendar.api.changeDate({seconds: -30});
else if (advanceMode == '1m') SimpleCalendar.api.changeDate({minute: -1});
else if (advanceMode == '5m') SimpleCalendar.api.changeDate({minute: -5});
else if (advanceMode == '15m') SimpleCalendar.api.changeDate({minute: -15});
else if (advanceMode == '1h') SimpleCalendar.api.changeDate({hour: -1});
else if (advanceMode == '6h') SimpleCalendar.api.changeDate({hour: -6});
else if (advanceMode == '12h') SimpleCalendar.api.changeDate({hour: -12});
else if (advanceMode == '1d') SimpleCalendar.api.changeDate({day: -1});
else if (advanceMode == '7d') SimpleCalendar.api.changeDate({day: -7});
else if (advanceMode == '1M') SimpleCalendar.api.changeDate({month: -1});
else if (advanceMode == '1y') SimpleCalendar.api.changeDate({year: -1});
}
}
@@ -792,6 +708,7 @@ export class ExternalModules{
}
streamDeck.setTitle(txt,context);
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background,ring:ring,ringColor:ringColor});
}
@@ -1000,9 +917,9 @@ export class ExternalModules{
updateMonksActiveTiles(settings,context,device) {
const id = settings.monksActiveTilesId;
if (id == undefined || id == '') return;
let tile = canvas.background.placeables.find(t => t.id == id);
let tile = canvas.tiles.placeables.find(t => t.id == id);
if (tile == undefined) return;
const tileData = tile.data.flags?.['monks-active-tiles'];
const tileData = tile.document.flags?.['monks-active-tiles'];
if (tileData == undefined) return;
let ring = 1;
@@ -1012,9 +929,10 @@ export class ExternalModules{
ring = 2;
ringColor = '#00ff00'
}
let src = tile.data.img;
let src = tile.document.texture.sr;
streamDeck.setTitle('',context);
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background,ring:ring,ringColor:ringColor});
}
@@ -1022,9 +940,9 @@ export class ExternalModules{
const mode = settings.monksActiveTilesMode ? settings.monksActiveTilesMode : 'toggle';
const id = settings.monksActiveTilesId;
if (id == undefined || id == '') return;
let tile = canvas.background.placeables.find(t => t.id == id);
let tile = canvas.tiles.placeables.find(t => t.id == id);
if (tile == undefined) return;
const tileData = tile.data.flags?.['monks-active-tiles'];
const tileData = tile.document.flags?.['monks-active-tiles'];
if (tileData == undefined) return;
if (mode == 'toggle') tile.document.setFlag('monks-active-tiles','active',!tileData.active);

View File

@@ -36,6 +36,7 @@ export class MacroControl{
let src = "";
let macroId = undefined;
let uses = undefined;
let macroLabel = "";
if (mode == 'macroBoard') { //Macro board
if ((getPermission('MACRO','MACROBOARD') == false )) {
@@ -56,8 +57,14 @@ export class MacroControl{
else { //Execute macro
macroNumber += this.offset - 1;
if (macroNumber < 0) macroNumber = 0;
macroId = game.settings.get(moduleName,'macroSettings').macros[macroNumber];
background = game.settings.get(moduleName,'macroSettings').color[macroNumber];
const macroSettings = game.settings.get(moduleName,'macroSettings');
macroId = macroSettings.macros[macroNumber];
background = macroSettings.color[macroNumber];
try {
macroLabel = macroSettings.labels[macroNumber];
}
catch (err) {}
if ((macroLabel == undefined || macroLabel == "") && game.macros.get(macroId)) macroLabel = game.macros.get(macroId).name;
if (background == undefined) background = '#000000';
ring = 0;
}
@@ -72,7 +79,7 @@ export class MacroControl{
streamDeck.noPermission(context,device);
return;
}
if (mode == 'hotbar') macroId = compatibleCore('10.0') ? game.user.hotbar[macroNumber] : game.user.data.hotbar[macroNumber];
if (mode == 'hotbar') macroId = game.user.hotbar[macroNumber];
else {
let macros;
if (mode == 'customHotbar' && game.modules.get('custom-hotbar') != undefined)
@@ -88,7 +95,8 @@ export class MacroControl{
let macro = game.macros._source.find(p => p._id == macroId);
if (macro != undefined) {
if (displayName) name = macro.name;
if (displayName && mode == 'macroBoard') name = macroLabel;
else if (displayName) name = macro.name;
if (displayIcon) src = macro.img;
if (hotbarUses && displayUses) uses = await this.getUses(macro);
}
@@ -98,6 +106,7 @@ export class MacroControl{
if (displayIcon) src = "modules/MaterialDeck/img/black.png";
}
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background,ring:ring,ringColor:ringColor,uses:uses});
streamDeck.setTitle(name,context);
}
@@ -114,8 +123,7 @@ export class MacroControl{
if (device?.buttons == undefined) continue;
for (let i=0; i<device.buttons.length; i++){
const data = device.buttons[i];
if (data == undefined || data.action != 'macro' || data.settings.macroMode == 'macroBoard') continue;
if (data == undefined || data.action != 'macro' || data.settings.macroMode != 'hotbar') continue;
const context = data.context;
const mode = data.settings.macroMode ? data.settings.macroMode : 'hotbar';
const displayName = data.settings.displayName ? data.settings.displayName : false;
@@ -137,7 +145,7 @@ export class MacroControl{
let macroId;
if (mode == 'hotbar'){
macroId = game.user.data.hotbar[macroNumber];
macroId = game.user.hotbar[macroNumber];
}
else {
if (macroNumber > 9) macroNumber = 0;
@@ -151,6 +159,7 @@ export class MacroControl{
if (displayIcon) src += macro.img;
if (hotbarUses && displayUses) uses = await this.getUses(macro);
}
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background,uses:uses});
streamDeck.setTitle(name,context);
}
@@ -177,19 +186,35 @@ export class MacroControl{
const args = settings.macroArgs ? settings.macroArgs : "";
let advancedMacrosEnabled = false;
let advancedMacros = game.modules.get("advanced-macros");
if (advancedMacros != undefined && advancedMacros.active) advancedMacrosEnabled = true;
if (compatibleCore('11.0')) {
advancedMacrosEnabled = true;
}
else {
let advancedMacros = game.modules.get("advanced-macros");
if (advancedMacros != undefined && advancedMacros.active) advancedMacrosEnabled = true;
}
if (args == "" || args == " ") advancedMacrosEnabled = false;
if (advancedMacrosEnabled == false) macro.execute({token:target});
else {
let chatData = {
user: game.user._id,
speaker: ChatMessage.getSpeaker(),
content: "/'" + macro.name + "' " + args
};
ChatMessage.create(chatData, {});
if (compatibleCore('11.0')) {
let argument;
try {
argument = JSON.parse(args)
macro.execute(argument);
} catch (err) {
console.error(err)
}
}
else {
let chatData = {
user: game.user._id,
speaker: ChatMessage.getSpeaker(),
content: "/amacro '" + macro.name + "' " + args[macroNumber]
};
ChatMessage.create(chatData, {});
}
}
}
@@ -208,7 +233,7 @@ export class MacroControl{
executeHotbar(macroNumber,mode,target){
let macroId
if (mode == 'hotbar') macroId = compatibleCore('10.0') ? game.user.hotbar[macroNumber] : game.user.data.hotbar[macroNumber];
if (mode == 'hotbar') macroId = game.user.hotbar[macroNumber];
else {
let macros;
if (mode == 'customHotbar' && game.modules.get('custom-hotbar') != undefined) {
@@ -234,19 +259,35 @@ export class MacroControl{
if (macro != undefined && macro != null) {
const args = game.settings.get(moduleName,'macroSettings').args;
let advancedMacrosEnabled = false;
let advancedMacros = game.modules.get("advanced-macros");
if (advancedMacros != undefined && advancedMacros.active) advancedMacrosEnabled = true;
if (compatibleCore('11.0')) {
advancedMacrosEnabled = true;
}
else {
let advancedMacros = game.modules.get("advanced-macros");
if (advancedMacros != undefined && advancedMacros.active) advancedMacrosEnabled = true;
}
if (args == undefined || args[macroNumber] == undefined || args[macroNumber] == "") advancedMacrosEnabled = false;
if (advancedMacrosEnabled == false) macro.execute();
else {
let chatData = {
user: game.user._id,
speaker: ChatMessage.getSpeaker(),
content: "/'" + macro.name + "' " + args
};
ChatMessage.create(chatData, {});
if (compatibleCore('11.0')) {
let argument;
try {
argument = JSON.parse(args[macroNumber])
macro.execute(argument);
} catch (err) {
console.error(err)
}
}
else {
let chatData = {
user: game.user._id,
speaker: ChatMessage.getSpeaker(),
content: "/amacro '" + macro.name + "' " + args[macroNumber]
};
ChatMessage.create(chatData, {});
}
}
}
}

View File

@@ -1,5 +1,5 @@
import { streamDeck, gamingSystem, getPermission } from "../../MaterialDeck.js";
import { compatibleCore } from "../misc.js";
import { } from "../misc.js";
export class OtherControls{
constructor(){
@@ -8,6 +8,7 @@ export class OtherControls{
this.rollOption = 'dialog';
this.controlsOffset = 0;
this.toolsOffset = 0;
this.attackMode = 'chat';
}
setRollOption(option) {
@@ -15,6 +16,11 @@ export class OtherControls{
this.updateAll();
}
setAttackMode(option) {
this.attackMode = option;
this.updateAll();
}
async updateAll(options={}){
if (this.active == false) return;
for (let device of streamDeck.buttonContext) {
@@ -55,8 +61,12 @@ export class OtherControls{
this.updateChatMessage(settings,context,device,options);
else if (mode == 'rollOptions')
this.updateRollOptions(settings,context,device,options);
else if (mode == 'attackModes')
this.updateAttackMode(settings,context,device,options);
else if (mode == 'rollMode')
this.updateRollMode(settings,context,device,options);
else if (mode == 'globalVolumeControls')
this.updateGlobalVolumeControls(settings, context, device, options);
}
keyPress(settings,context,device){
@@ -86,8 +96,12 @@ export class OtherControls{
this.keyPressChatMessage(settings);
else if (mode == 'rollOptions')
this.keyPressRollOptions(settings);
else if (mode == 'attackModes')
this.keyPressAttackMode(settings);
else if (mode == 'rollMode')
this.keyPressRollMode(settings);
else if (mode == 'globalVolumeControls')
this.keyPressGlobalVolumeControls(settings);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
@@ -113,7 +127,12 @@ export class OtherControls{
}
else if (pauseFunction == 'toggle') //toggle
src = 'modules/MaterialDeck/img/other/pause/playpause.png';
streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor,overlay:true});
let overlay = true;
if (settings.iconOverride != '' && settings.iconOverride != undefined) {
src = settings.iconOverride;
overlay = false;
}
streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor,overlay});
streamDeck.setTitle('',context);
}
@@ -163,8 +182,12 @@ export class OtherControls{
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});
let overlay = true;
if (settings.iconOverride != '' && settings.iconOverride != undefined) {
url = settings.iconOverride;
overlay = false;
}
streamDeck.setIcon(context,device,url,{background:background,overlay});
streamDeck.setTitle('',context);
}
@@ -185,7 +208,7 @@ export class OtherControls{
}
else {
let viewPosition = canvas.scene._viewPosition;
const gridSize = compatibleCore('10.0') ? canvas.scene.grid.size : canvas.scene.data.grid;
const gridSize = canvas.scene.grid.size;
viewPosition.duration = 100;
if (dir == 'up') viewPosition.y -= gridSize;
@@ -324,6 +347,7 @@ export class OtherControls{
}
}
}
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor});
streamDeck.setTitle(txt,context);
}
@@ -345,20 +369,8 @@ 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;
for (let layer of canvas.layers) {
if (layer.options == undefined) continue;
if (layer.options.name == selectedControl.layer) {
layer.activate();
break;
}
}
}
ui.controls.initialize({layer: selectedControl.layer});
canvas.layers.find(l => l.options.name == selectedControl.layer).activate();
}
}
else if (control == 'dispTools'){ //displayed tools
@@ -385,12 +397,8 @@ export class OtherControls{
selectedTool.onClick();
}
else {
if (compatibleCore('10.0')) {
ui.controls.initialize({layer: selectedControl.layer, tool: selectedTool.name});
}
else {
selectedControl.activeTool = selectedTool.name;
}
ui.controls.initialize({layer: selectedControl.layer, tool: selectedTool.name});
canvas.layers.find(l => l.options.name == selectedControl.layer).activate();
}
}
@@ -414,21 +422,8 @@ 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;
for (let layer of canvas.layers) {
if (layer.options == undefined) continue;
if (layer.options.name == selectedControl.layer) {
layer.activate();
break;
}
}
}
ui.controls.initialize({layer: selectedControl.layer});
canvas.layers.find(l => l.options.name == selectedControl.layer).activate();
}
else {
const selectedTool = selectedControl.tools.find(t => t.name == tool);
@@ -437,39 +432,23 @@ 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});
if (selectedTool.toggle) {
ui.controls.initialize({layer: selectedControl.layer});
canvas.layers.find(l => l.options.name == selectedControl.layer).activate();
selectedTool.active = !selectedTool.active;
selectedTool.onClick(selectedTool.active);
}
else if (selectedTool.button){
ui.controls.initialize({layer: selectedControl.layer});
canvas.layers.find(l => l.options.name == selectedControl.layer).activate();
selectedTool.onClick();
}
else {
ui.controls.activeControl = control;
for (let layer of canvas.layers) {
if (layer.options == undefined) continue;
if (layer.options.name == selectedControl.layer) {
layer.activate();
break;
}
}
if (selectedTool.toggle) {
selectedTool.active = !selectedTool.active;
selectedTool.onClick(selectedTool.active);
}
else if (selectedTool.button){
selectedTool.onClick();
}
else
selectedControl.activeTool = tool;
ui.controls.initialize({layer: selectedControl.layer, tool: selectedTool.name});
canvas.layers.find(l => l.options.name == selectedControl.layer).activate();
}
}
}
}
@@ -500,11 +479,16 @@ export class OtherControls{
}
else if (func == 'disp'){ //display darkness
src = 'modules/MaterialDeck/img/other/darkness/darkness.png';
const darkness = canvas.scene != null ? compatibleCore('10.0') ? Math.floor(canvas.scene.darkness*100)/100 : Math.floor(canvas.scene.data.darkness*100)/100 : '';
const darkness = canvas.scene != null ? Math.floor(canvas.scene.darkness*100)/100 : '';
txt += darkness;
}
streamDeck.setTitle(txt,context);
streamDeck.setIcon(context,device,src,{background:background,overlay:true});
let overlay = true;
if (settings.iconOverride != '' && settings.iconOverride != undefined) {
src = settings.iconOverride;
overlay = false;
}
streamDeck.setIcon(context,device,src,{background:background,overlay});
}
keyPressDarkness(settings) {
@@ -517,16 +501,16 @@ export class OtherControls{
if (func == 'value') //value
canvas.scene.update({darkness: value}, {animateDarkness});
else if (func == 'incDec'){ //increase/decrease
let darkness = compatibleCore('10.0') ? canvas.scene.darkness - value : canvas.scene.data.darkness - value;
let darkness = canvas.scene.darkness - value;
if (darkness > 1) darkness = 1;
if (darkness < 0) darkness = 0;
canvas.scene.update({darkness: darkness}, {animateDarkness});
}
else if (func == 'transitionDay') {
canvas.scene.update({darkness: 0}, {animateDarkness: 10000})
canvas.scene.update({darkness: 0}, {animateDarknes})
}
else if (func == 'transitionNight') {
canvas.scene.update({darkness: 1}, {animateDarkness: 10000})
canvas.scene.update({darkness: 1}, {animateDarknes})
}
}
@@ -544,7 +528,9 @@ export class OtherControls{
if (settings.displayDiceName) txt = 'Roll: ' + formula;
streamDeck.setTitle(txt,context);
streamDeck.setIcon(context,device,'',{background:background});
let src = '';
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background});
}
keyPressRollDice(settings,context,device){
@@ -599,7 +585,7 @@ export class OtherControls{
if (table == undefined) return;
let txt = settings.displayRollName ? table.name : '';
let src = settings.displayRollIcon ? (compatibleCore('10.0') ? table.img : table.data.img) : '';
let src = settings.displayRollIcon ? table.img : '';
if (table == undefined) {
src = '';
@@ -613,6 +599,7 @@ export class OtherControls{
}
streamDeck.setTitle(txt,context);
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background});
}
@@ -642,34 +629,18 @@ 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");
else if (nr == 'actors') name = game.i18n.localize("SIDEBAR.TabActors");
else if (nr == 'items') name = game.i18n.localize("SIDEBAR.TabItems");
else if (nr == 'journal') name = game.i18n.localize("SIDEBAR.TabJournal");
else if (nr == 'tables') name = game.i18n.localize("SIDEBAR.TabTables");
else if (nr == 'cards') name = game.i18n.localize("SIDEBAR.TabCards");
else if (nr == 'playlists') name = game.i18n.localize("SIDEBAR.TabPlaylists");
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");
}
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");
return name;
}
@@ -708,9 +679,10 @@ export class OtherControls{
}
else if (popOut == false) ringColor = (sidebarTab == 'collapse' && collapsed || (activeTab == sidebarTab)) ? ringOnColor : ringOffColor;
const name = settings.displaySidebarName ? this.getSidebarName(sidebarTab) : '';
const icon = settings.displaySidebarIcon ? this.getSidebarIcon(sidebarTab) : '';
let icon = settings.displaySidebarIcon ? this.getSidebarIcon(sidebarTab) : '';
streamDeck.setTitle(name,context);
if (settings.iconOverride != '' && settings.iconOverride != undefined) icon = settings.iconOverride;
streamDeck.setIcon(context,device,icon,{background:background,ring:2,ringColor:ringColor});
}
@@ -745,7 +717,9 @@ export class OtherControls{
const txt = settings.displayCompendiumName ? name : '';
streamDeck.setTitle(txt,context);
streamDeck.setIcon(context,device,"",{background:background,ring:2,ringColor:ringColor});
let src = '';
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor});
}
keyPressCompendiumBrowser(settings){
@@ -785,7 +759,9 @@ export class OtherControls{
const txt = settings.displayCompendiumName ? name : '';
streamDeck.setTitle(txt,context);
streamDeck.setIcon(context,device,"",{background:background,ring:2,ringColor:ringColor});
let src = '';
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor});
}
keyPressCompendium(settings){
@@ -834,7 +810,9 @@ export class OtherControls{
const txt = settings.displayCompendiumName ? name : '';
streamDeck.setTitle(txt,context);
streamDeck.setIcon(context,device,"",{background:background,ring:2,ringColor:ringColor});
let src = '';
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor});
}
keyPressJournal(settings){
@@ -860,7 +838,9 @@ export class OtherControls{
}
const background = settings.background ? settings.background : '#000000';
streamDeck.setTitle("",context);
streamDeck.setIcon(context,device,"",{background:background});
let src = '';
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background});
}
keyPressChatMessage(settings){
@@ -881,11 +861,16 @@ export class OtherControls{
const background = settings.background ? settings.background : '#000000';
const ringOffColor = settings.offRing ? settings.offRing : '#000000';
const ringOnColor = settings.onRing ? settings.onRing : '#00FF00';
const iconSrc = "modules/MaterialDeck/img/other/d20.png";
const rollOption = settings.rollOptionFunction ? settings.rollOptionFunction : 'normal';
let iconSrc = "modules/MaterialDeck/img/other/d20.png";
const rollOption = settings.rollOptionFunction ? settings.rollOptionFunction : 'dialog';
const ringColor = (rollOption == this.rollOption) ? ringOnColor : ringOffColor;
streamDeck.setTitle("",context);
streamDeck.setIcon(context,device,iconSrc,{background:background,ring:2,ringColor:ringColor,overlay:true});
let overlay = true;
if (settings.iconOverride != '' && settings.iconOverride != undefined) {
iconSrc = settings.iconOverride;
overlay = false;
}
streamDeck.setIcon(context,device,iconSrc,{background:background,ring:2,ringColor:ringColor,overlay});
}
keyPressRollOptions(settings){
@@ -896,17 +881,49 @@ export class OtherControls{
}
}
//////////////////////////////////////////////////////////////////////////////////////////
updateAttackMode(settings,context,device,options={}){
const background = settings.background ? settings.background : '#000000';
const ringOffColor = settings.offRing ? settings.offRing : '#000000';
const ringOnColor = settings.onRing ? settings.onRing : '#00FF00';
let iconSrc = "modules/MaterialDeck/img/other/d20.png";
const attackMode = settings.attackMode ? settings.attackMode : 'chat';
const ringColor = (attackMode == this.attackMode) ? ringOnColor : ringOffColor;
streamDeck.setTitle("",context);
let overlay = true;
if (settings.iconOverride != '' && settings.iconOverride != undefined) {
iconSrc = settings.iconOverride;
overlay = false;
}
streamDeck.setIcon(context,device,iconSrc,{background:background,ring:2,ringColor:ringColor,overlay});
}
keyPressAttackMode(settings){
const attackMode = settings.attackMode ? settings.attackMode : 'chat';
if (this.attackMode != attackMode) {
this.setAttackMode(attackMode)
}
}
//////////////////////////////////////////////////////////////////////////////////////////
updateRollMode(settings,context,device,options={}){
const background = settings.background ? settings.background : '#000000';
const ringOffColor = settings.offRing ? settings.offRing : '#000000';
const ringOnColor = settings.onRing ? settings.onRing : '#00FF00';
const iconSrc = "modules/MaterialDeck/img/other/d20.png";
let iconSrc = "modules/MaterialDeck/img/other/d20.png";
const rollMode = settings.rollMode ? settings.rollMode : 'roll';
const ringColor = (rollMode == game.settings.get('core','rollMode')) ? ringOnColor : ringOffColor;
streamDeck.setTitle("",context);
streamDeck.setIcon(context,device,iconSrc,{background:background,ring:2,ringColor:ringColor,overlay:true});
let overlay = true;
let src = '';
if (settings.iconOverride != '' && settings.iconOverride != undefined) {
iconSrc = settings.iconOverride;
overlay = false;
}
streamDeck.setIcon(context,device,iconSrc,{background:background,ring:2,ringColor:ringColor,overlay});
}
async keyPressRollMode(settings){
@@ -914,4 +931,48 @@ export class OtherControls{
await game.settings.set('core','rollMode',rollMode);
this.updateAll();
}
}
//////////////////////////////////////////////////////////////////////////////////////////
async updateGlobalVolumeControls(settings,context,device,options={}){
const background = settings.background ? settings.background : '#000000';
let iconSrc = "modules/MaterialDeck/img/transparant.png";
const type = settings.globalVolumeType ? settings.globalVolumeType : 'playlists';
let txt = "";
if (settings.displayGlobalVolumeValue) {
if (type == 'playlists') txt += Math.round(AudioHelper.volumeToInput(await game.settings.get("core", "globalPlaylistVolume"))*100)/100;
else if (type == 'ambient') txt += Math.round(AudioHelper.volumeToInput(await game.settings.get("core", "globalAmbientVolume"))*100)/100;
else if (type == 'interface') txt += Math.round(AudioHelper.volumeToInput(await game.settings.get("core", "globalInterfaceVolume"))*100)/100;
}
streamDeck.setTitle(txt,context);
if (settings.iconOverride != '' && settings.iconOverride != undefined) {
iconSrc = settings.iconOverride;
}
streamDeck.setIcon(context,device,iconSrc,{background:background});
}
async keyPressGlobalVolumeControls(settings){
const type = settings.globalVolumeType ? settings.globalVolumeType : 'playlists';
const mode = settings.globalVolumeMode ? settings.globalVolumeMode : 'incDec';
const value = settings.globalVolumeValue ? settings.globalVolumeValue : 0.1;
let settingLabel = '';
let newVolume = 0;
if (type == 'playlists') settingLabel = "globalPlaylistVolume";
else if (type == 'ambient') settingLabel = "globalAmbientVolume";
else if (type == 'interface') settingLabel = "globalInterfaceVolume";
if (mode == 'incDec') newVolume = AudioHelper.volumeToInput(await game.settings.get("core", settingLabel)) + parseFloat(value);
else if (mode == 'set') newVolume = value;
if (newVolume > 1) newVolume = 1;
else if (newVolume < 0) newVolume = 0;
await game.settings.set("core", settingLabel, AudioHelper.inputToVolume(newVolume));
document.getElementsByName(settingLabel)[0].value = newVolume;
this.updateAll();
}
}

View File

@@ -34,12 +34,17 @@ export class PlaylistControl{
this.updateTrack(settings,context,device);
}
else {
const src = mode == 'stopAll' ? 'modules/MaterialDeck/img/playlist/stop.png' : 'modules/MaterialDeck/img/playlist/pause.png';
let src = mode == 'stopAll' ? 'modules/MaterialDeck/img/playlist/stop.png' : 'modules/MaterialDeck/img/playlist/pause.png';
const background = settings.background ? settings.background : '#000000';
const ringColor = (game.playlists.playing.length > 0) ? '#00FF00' : '#000000';
const ring = (game.playlists.playing.length > 0) ? 2 : 1;
const txt = settings.displayPlaylistName ? this.getPlaylist(this.playlistOffset).name : '';
streamDeck.setIcon(context,device,src,{background:background,ring:ring,ringColor:ringColor,overlay:true});
let overlay = true;
if (settings.iconOverride != '' && settings.iconOverride != undefined) {
src = settings.iconOverride;
overlay = false;
}
streamDeck.setIcon(context,device,src,{background:background,ring:ring,ringColor:ringColor,overlay});
streamDeck.setTitle(txt,context);
}
}
@@ -88,6 +93,8 @@ export class PlaylistControl{
const targetPlaylist = this.getPlaylist(number);
if (targetPlaylist != undefined) name = targetPlaylist.name;
}
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor});
streamDeck.setTitle(name,context);
}
@@ -102,7 +109,7 @@ export class PlaylistControl{
let src = "modules/MaterialDeck/img/transparant.png";
//Play/Stop
if (playlistType == 'playStop'){
if (playlistType == 'playStop' || playlistType == 'incDecVol' || playlistType == 'setVol'){
let playlistNr = parseInt(settings.playlistNr);
if (isNaN(playlistNr) || playlistNr < 1) playlistNr = 1;
playlistNr--;
@@ -122,6 +129,11 @@ export class PlaylistControl{
ringColor = ringOffColor;
if (settings.displayName)
name = track.name;
if (settings.displayTrackVolume) {
if (settings.displayName) name += ' ';
name += Math.round(AudioHelper.volumeToInput(track.volume)*100)/100
}
}
}
}
@@ -134,6 +146,7 @@ export class PlaylistControl{
//Relative Offset
else if (playlistType == 'relativeOffset') {
}
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor});
streamDeck.setTitle(name,context);
}
@@ -261,6 +274,29 @@ export class PlaylistControl{
}
this.updateAll();
}
else if (playlistType == 'incDecVol' || playlistType == 'setVol') {
const value = settings.trackVolumeValue ? parseFloat(settings.trackVolumeValue) : 0.1;
let playlist = this.getPlaylist(playlistNr);
if (playlist != undefined){
if (playlistMode != 'track') return;
const track = playlist.sounds.contents[trackNr];
if (track != undefined){
let newVolume = playlistType == 'incDecVol' ? AudioHelper.volumeToInput(track.volume) + value : value;
if (newVolume > 1) newVolume = 1;
else if (newVolume < 0) newVolume = 0;
track.updateSource({volume:AudioHelper.inputToVolume(newVolume)})
track.sound?.fade(track.effectiveVolume, {duration: PlaylistSound.VOLUME_DEBOUNCE_MS});
if ( track.isOwner ) track.debounceVolume(AudioHelper.inputToVolume(newVolume));
for (let elmnt of document.getElementById('currently-playing').getElementsByClassName('sound')) {
if (elmnt.getAttribute('data-sound-id') == track.id) {
elmnt.getElementsByClassName('sound-volume')[0].value = newVolume;
return;
}
}
this.updateAll();
}
}
}
}
}
@@ -280,14 +316,14 @@ export class PlaylistControl{
return;
}
let mode = game.settings.get(moduleName,'playlists').playlistMode[playlistNr];
const originalPlayMode = playlist.mode;
await playlist.update({mode: CONST.PLAYLIST_MODES.SEQUENTIAL});
//const originalPlayMode = playlist.mode;
//await playlist.update({mode: CONST.PLAYLIST_MODES.SEQUENTIAL});
if (mode == 0) {
mode = game.settings.get(moduleName,'playlists').playMode;
if (mode == 2) await this.stopAll(true);
}
playlist.playAll();
await playlist.update({mode: originalPlayMode});
//await playlist.update({mode: originalPlayMode});
}
async playTrack(track,playlist,playlistNr){

View File

@@ -1,5 +1,5 @@
import { streamDeck, getPermission } from "../../MaterialDeck.js";
import { compatibleCore } from "../misc.js";
import { } from "../misc.js";
export class SceneControl{
constructor(){
@@ -27,6 +27,7 @@ export class SceneControl{
const background = settings.background ? settings.background : '#000000';
const ringOffColor = settings.offRing ? settings.offRing : '#000000';
const ringOnColor = settings.onRing ? settings.onRing : '#00FF00';
const ringActiveColor = settings.activeRing ? settings.activeRing : '#FFFF00'
let ringColor = "#000000";
let ring = 2;
@@ -46,7 +47,7 @@ export class SceneControl{
if (scene != undefined){
ringColor = scene.isView ? ringOnColor : ringOffColor;
if (settings.displaySceneName) name = scene.name;
if (settings.displaySceneIcon) src = compatibleCore('10.0') ? scene.background.src : scene.img;
if (settings.displaySceneIcon) src = scene.background.src;
if (scene.active) name += "\n(Active)";
}
}
@@ -60,34 +61,24 @@ 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 = 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])
}
sceneList = ui.scenes.documents;
const scene = sceneList[nr+this.sceneOffset];
if (scene != undefined){
if (scene.isView)
if (scene.active)
ringColor = ringActiveColor;
else if (scene.isView)
ringColor = ringOnColor;
else if ((compatibleCore('10.0') && scene.navigation && scene.permission.default == 0) || (!compatibleCore('10.0') && scene.data.navigation && scene.data.permission.default == 0))
else if (scene.navigation && scene.permission.default == 0)
ringColor = '#000791';
else if ((compatibleCore('10.0') && scene.navigation) || (!compatibleCore('10.0') && scene.data.navigation))
else if (scene.navigation)
ringColor = '#2d2d2d';
else
ringColor = ringOffColor;
if (settings.displaySceneName) name = scene.name;
if (settings.displaySceneIcon) src = compatibleCore('10.0') ? scene.background.src : scene.img;
if (settings.displaySceneIcon) src = scene.background.src;
if (scene.active) name += "\n(Active)";
}
}
@@ -100,9 +91,12 @@ export class SceneControl{
let scene = game.scenes.getName(settings.sceneName);
if (scene != undefined){
ringColor = scene.isView ? ringOnColor : ringOffColor;
if (scene.active)
ringColor = ringActiveColor;
else if (scene.isView)
ringColor = ringOnColor;
if (settings.displaySceneName) name = scene.name;
if (settings.displaySceneIcon) src = compatibleCore('10.0') ? scene.background.src : scene.img;
if (settings.displaySceneIcon) src = scene.background.src;
if (scene.active) name += "\n(Active)";
}
}
@@ -114,7 +108,7 @@ export class SceneControl{
const scene = game.scenes.active;
if (scene == undefined) return;
if (settings.displaySceneName) name = scene.name;
if (settings.displaySceneIcon) src = compatibleCore('10.0') ? scene.background.src : scene.img;
if (settings.displaySceneIcon) src = scene.background.src;
ring = 0;
}
else if (func == 'offset'){
@@ -124,6 +118,7 @@ export class SceneControl{
src = "modules/MaterialDeck/img/transparant.png";
}
streamDeck.setTitle(name,context);
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background,ring:ring,ringColor:ringColor});
}
@@ -159,18 +154,7 @@ 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 = 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])
}
sceneList = ui.scenes.documents;
const scene = sceneList[nr+this.sceneOffset];

View File

@@ -45,6 +45,7 @@ export class SoundboardControl{
if (settings.displayIcon && soundboardSettings.img != undefined) src = soundboardSettings.img[soundNr];
streamDeck.setTitle(txt,context);
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor});
}
else if (mode == 'offset') { //Offset
@@ -57,7 +58,9 @@ export class SoundboardControl{
else ringColor = ringOffColor;
streamDeck.setTitle(txt,context);
streamDeck.setIcon(context,device,"",{background:background,ring:2,ringColor:ringColor});
let src = '';
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:ringColor});
}
else if (mode == 'stopAll') { //Stop all sounds
let src = 'modules/MaterialDeck/img/playlist/stop.png';
@@ -66,6 +69,7 @@ export class SoundboardControl{
for (let i=0; i<this.activeSounds.length; i++)
if (this.activeSounds[i])
soundPlaying = true;
if (settings.iconOverride != '' && settings.iconOverride != undefined) src = settings.iconOverride;
if (soundPlaying)
streamDeck.setIcon(context,device,src,{background:background,ring:2,ringColor:'#00FF00',overlay:true});
else
@@ -184,4 +188,14 @@ export class SoundboardControl{
}
this.updateAll();
}
ambientVolumeChanged(ambientVolume) {
for (let i = 0; i<this.activeSounds.length; i++) {
let sound = this.activeSounds[i];
if (sound == undefined) continue;
let volume = game.settings.get(moduleName,'soundboardSettings').volume[i]/100;
volume = AudioHelper.inputToVolume(volume) * ambientVolume;
sound.gain.value = volume;
}
}
}

View File

@@ -1,5 +1,5 @@
import { streamDeck, macroControl, otherControls, tokenHelper, getPermission } from "../../MaterialDeck.js";
import { compatibleCore } from "../misc.js";
import { } from "../misc.js";
export class TokenControl{
constructor(){
@@ -20,21 +20,20 @@ export class TokenControl{
}
}
async pushData(tokenId,settings,context,device,ring=0,ringColor='#000000'){
async pushData(tokenId,settings,context,device,ring=0,ringColor='#000000',forceIcon,hideName=false){
const name = settings.displayName ? settings.displayName : false;
const icon = settings.icon ? settings.icon : 'none';
const background = settings.background ? settings.background : "#000000";
let stats = settings.stats ? settings.stats : 'none';
const selection = settings.selection ? settings.selection : 'selected';
const tokenIdentifier = settings.tokenName ? settings.tokenName : '';
const prependTitle = settings.prependTitle ? settings.prependTitle : '';
const mode = settings.tokenMode ? settings.tokenMode : 'token';
const background = (mode == 'inventory') ? (settings.inventoryBackground ? settings.inventoryBackground : "#000000") : (settings.background ? settings.background : "#000000");
let validToken = false;
let token;
if (settings.combatTrackerMode) token = tokenHelper.getTokenFromTokenId(tokenId);
else token = tokenHelper.getToken(selection,tokenIdentifier);
if (token != undefined) validToken = true;
let txt = "";
let iconSrc = "";
@@ -78,21 +77,7 @@ export class TokenControl{
if (stats == 'custom'){
const custom = settings.custom ? settings.custom : '';
let split = custom.split('[');
for (let i=0; i<split.length; i++) split[i] = split[i].split(']');
for (let i=0; i<split.length; i++)
for (let j=0; j<split[i].length; j++){
if (split[i][j][0] != '@') txt += split[i][j];
else {
const dataPath = split[i][j].split('@')[1].split('.');
let data = token;
for (let i=0; i<dataPath.length; i++)
data = data?.[dataPath[i]];
if (data == undefined) txt += '[undef]';
else txt += data;
}
}
txt += this.decodeCustomStat(custom, token);
}
if (stats == 'HP' || stats == 'Wounds') {
@@ -236,7 +221,7 @@ export class TokenControl{
return;
}
ring = 1;
if (compatibleCore('10.0') ? token.document.hidden : token.data.hidden){
if (token.document.hidden){
ring = 2;
ringColor = "#FF7B00";
}
@@ -392,7 +377,7 @@ export class TokenControl{
if (item != undefined && displayUses) uses = tokenHelper.getFeatureUses(item);
}
else if (mode == 'spellbook') {
items = tokenHelper.getSpells(token,settings.spellType);
items = tokenHelper.getSpells(token,settings.spellType,settings.spellMode);
items = this.sortItems(items);
if (selectionMode == 'order') item = items[itemNr];
else if (selectionMode == 'name') item = items.filter(i => i.name == settings.itemName)[0];
@@ -533,14 +518,19 @@ export class TokenControl{
}
}
if (forceIcon) {
iconSrc = forceIcon;
txt = "";
}
else if (hideName) txt = "";
if (settings.iconOverride != '' && settings.iconOverride != undefined) iconSrc = settings.iconOverride;
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);
if (compatibleCore('10.0')) sorted.sort((a,b) => a.sort - b.sort);
else sorted.sort((a,b) => a.data.sort - b.data.sort);
sorted.sort((a,b) => a.sort - b.sort);
return sorted;
}
@@ -640,24 +630,15 @@ export class TokenControl{
//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.visionEnabled == 'toggle')
sight.enabled = !token.document.sight.enabled;
else
sight.enabled = 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.visionAngle && isNaN(settings.visionAngle) == false) sight.angle = parseInt(settings.visionAngle);
if (settings.visionMode && settings.visionMode != 'noChange') sight.visionMode = settings.visionMode;
//Vision detection modes
@@ -691,7 +672,7 @@ export class TokenControl{
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;
light.animation.reverse = !token.document.light.animation.reverse;
else if (settings.lightAnimationReverseDirection == 'enable')
light.animation.reverse = true;
else if (settings.lightAnimationReverseDirection == 'disable')
@@ -716,15 +697,9 @@ export class TokenControl{
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;
data = {
sight,
light
}
token.document.update(data);
}
@@ -927,7 +902,8 @@ export class TokenControl{
}
else {
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 selectionMode = settings.inventorySelection ? settings.inventorySelection : 'order';
let items = allItems;
if (mode == 'inventory') {
@@ -945,7 +921,7 @@ export class TokenControl{
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, otherControls.rollOption);
tokenHelper.rollItem(item, settings, otherControls.rollOption, otherControls.attackMode);
}
}
@@ -985,4 +961,64 @@ export class TokenControl{
pf2eCondition(condition){
return "systems/pf2e/icons/conditions-2/" + condition + ".png";
}
decodeCustomStat(custom, token) {
let txt = "";
let split = custom.split(/\[|\]/g)
for (let segment of split) {
if (segment.startsWith('if')) {
let ifA;
let ifMode;
let ifB;
let ifThen;
let ifElse;
let spaceSplit = segment.split(' ');
let count = 0;
for (let segment of spaceSplit) {
if (segment.startsWith('if')) ifA = this.decodeIfSegment(segment, token);
else if (segment.startsWith('then')) ifThen = this.decodeIfSegment(segment, token);
else if (segment.startsWith('else')) ifElse = this.decodeIfSegment(segment, token);
else {
segment = segment.split(')')[0];
if (count == 1) ifMode = segment;
else if (count == 2) ifB = segment.startsWith('@') ? this.getCustomDataPath(segment, token) : segment;
}
count++;
}
if (ifMode == '>') txt += ifA > ifB ? ifThen : ifElse;
else if (ifMode == '>=') txt += ifA >= ifB ? ifThen : ifElse;
else if (ifMode == '<') txt += ifA < ifB ? ifThen : ifElse;
else if (ifMode == '<=') txt += ifA <= ifB ? ifThen : ifElse;
else if (ifMode == '==') txt += ifA == ifB ? ifThen : ifElse;
}
else if (segment.startsWith('@')) txt += this.getCustomDataPath(segment, token);
else txt += segment;
}
return txt;
}
decodeIfSegment(segment, token) {
let split = segment.split(/\(|\)/g);
if (split[1].startsWith('@')) return this.getCustomDataPath(split[1], token);
return split[1];
}
getCustomDataPath(path, token) {
const dataPath = path.split('@')[1].split('.');
let data;
if (dataPath[0] == 'actor') data = token.actor;
else if (dataPath[0] == 'token') data = token;
for (let i=1; i<dataPath.length; i++) {
data = data?.[dataPath[i]];
}
if (data == undefined) return '[undef]';
return data;
}
}

View File

@@ -27,8 +27,8 @@ export function compatibleCore(compatibleVersion){
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);
let coreVersion = game.system.version;
return compareVersions(coreVersion, compatibleVersion);
}
export class playlistConfigForm extends FormApplication {
@@ -190,29 +190,38 @@ export class macroConfigForm extends FormApplication {
return;
}
//Get the settings
var selectedMacros = game.settings.get(moduleName,'macroSettings').macros;
var color = game.settings.get(moduleName,'macroSettings').color;
var args = game.settings.get(moduleName,'macroSettings').args;
const settings = game.settings.get(moduleName,'macroSettings');
var selectedMacros = settings.macros;
var color = settings.color;
var args = settings.args;
var labels = settings.labels;
//Check if the settings are defined
if (selectedMacros == undefined) selectedMacros = [];
if (color == undefined) color = [];
if (args == undefined) args = [];
if (labels == undefined) labels = [];
//Check if the Furnace is installed and enabled
let height = 95;
let advancedMacrosEnabled = false;
let advancedMacros = game.modules.get("advanced-macros");
if (advancedMacros != undefined && advancedMacros.active) advancedMacrosEnabled = true;
if (advancedMacrosEnabled) {
if (compatibleCore('11.0')) {
advancedMacrosEnabled = true;
height += 50;
}
else {
let advancedMacros = game.modules.get("advanced-macros");
if (advancedMacros != undefined && advancedMacros.active) advancedMacrosEnabled = true;
if (advancedMacrosEnabled) {
advancedMacrosEnabled = true;
height += 50;
}
}
let iteration = this.page*32;
let macroData = [];
for (let j=0; j<4; j++){
let macroThis = [];
let macroRowConfig = [];
for (let i=0; i<8; i++){
let colorData = color[iteration];
@@ -227,18 +236,20 @@ export class macroConfigForm extends FormApplication {
}
else
colorData = '#000000';
const label = labels[iteration] == undefined || labels[iteration] == "" ? game.macros.get(selectedMacros[iteration])?.name : labels[iteration];
let dataThis = {
iteration: iteration+1,
macro: selectedMacros[iteration],
color: colorData,
args: args[iteration]
args: args[iteration],
label
}
macroThis.push(dataThis);
macroRowConfig.push(dataThis);
iteration++;
}
macroData.push({dataThis: macroThis});
macroData.push({macroRowConfig});
}
return {
height: height,
macros: game.macros,
@@ -271,6 +282,7 @@ export class macroConfigForm extends FormApplication {
const macro = html.find("select[name='macros']");
const args = html.find("input[name='args']");
const color = html.find("input[name='colorPicker']");
const label = html.find("input[name='macroLabel']")
importBtn.on('click', async(event) => {
let importDialog = new importConfigForm();
@@ -360,13 +372,18 @@ export class macroConfigForm extends FormApplication {
macro.on("change", event => {
let id = event.target.id.replace('materialDeck_macroConfig_macros','');
let settings = game.settings.get(moduleName,'macroSettings');
settings.macros[id-1]=event.target.value;
settings.macros[id-1] = event.target.value;
if (settings.labels == undefined) settings.labels = [];
const macroLabel = event.target.value == '' ? '' : game.macros.get(event.target.value).name;
settings.labels[id-1] = macroLabel;
document.getElementById(`materialDeck_macroConfig_label${id}`).value = macroLabel;
this.updateSettings(settings);
});
args.on("change", event => {
let id = event.target.id.replace('materialDeck_macroConfig_args','');
let settings = game.settings.get(moduleName,'macroSettings');
if (settings.args == undefined) settings.args = [];
settings.args[id-1]=event.target.value;
this.updateSettings(settings);
});
@@ -377,6 +394,14 @@ export class macroConfigForm extends FormApplication {
settings.color[id-1]=event.target.value;
this.updateSettings(settings);
});
label.on("change", event => {
let id = event.target.id.replace('materialDeck_macroConfig_label','');
let settings = game.settings.get(moduleName,'macroSettings');
if (settings.labels == undefined) settings.labels = [];
settings.labels[id-1] = event.target.value;
this.updateSettings(settings);
})
}
async updateSettings(settings){
@@ -1020,6 +1045,7 @@ export class downloadUtility extends FormApplication {
this.masterSDversion;
this.localMSversion = msVersion;
this.masterMSversion;
this.masterModuleVersion;
this.releaseAssets = [];
this.profiles = [];
@@ -1027,6 +1053,7 @@ export class downloadUtility extends FormApplication {
setTimeout(function(){
parent.checkForUpdate('SD');
parent.checkForUpdate('MS');
parent.checkForUpdate('Module');
parent.getReleaseData();
},100)
}
@@ -1071,6 +1098,8 @@ export class downloadUtility extends FormApplication {
localMsVersion: this.localMSversion,
masterMsVersion: this.masterMSversion,
msDlDisable: this.masterMSversion == undefined,
localModuleVersion: game.modules.get('MaterialDeck').version,
masterModuleVersion: this.masterModuleVersion,
profiles: this.profiles,
profileDlDisable: dlDisabled
}
@@ -1118,6 +1147,8 @@ export class downloadUtility extends FormApplication {
this.checkForUpdate('SD');
document.getElementById('materialDeck_dlUtil_masterMsVersion').value = 'Getting data';
this.checkForUpdate('MS');
document.getElementById('materialDeck_dlUtil_masterModuleVersion').value = 'Getting data';
this.checkForUpdate('Module');
this.getReleaseData();
})
}
@@ -1152,9 +1183,19 @@ export class downloadUtility extends FormApplication {
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/package.json';
const elementId = reqType == 'SD' ? 'materialDeck_dlUtil_masterSdVersion' : 'materialDeck_dlUtil_masterMsVersion';
let elementId;
if (reqType == 'SD') {
elementId = 'materialDeck_dlUtil_masterSdVersion';
url = 'https://raw.githubusercontent.com/CDeenen/MaterialDeck_SD/master/Plugin/com.cdeenen.materialdeck.sdPlugin/manifest.json';
}
else if (reqType == 'MS') {
elementId = 'materialDeck_dlUtil_masterMsVersion';
url = 'https://raw.githubusercontent.com/CDeenen/MaterialServer/master/package.json';
}
else if (reqType == 'Module') {
elementId = 'materialDeck_dlUtil_masterModuleVersion';
url = game.modules.get('MaterialDeck').manifest;
}
var request = new XMLHttpRequest();
request.open('GET', url, true);
@@ -1165,6 +1206,7 @@ export class downloadUtility extends FormApplication {
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;
else if (reqType == 'Module') parent.masterModuleVersion = JSON.parse(request.responseText).version;
parent.render(true);
return;
}
@@ -1206,7 +1248,6 @@ export class deviceConfig extends FormApplication {
dConfig = {};
game.settings.set(moduleName, 'devices', dConfig);
}
for (let d of streamDeck.buttonContext) {
if (d == undefined) continue;
let type;
@@ -1231,7 +1272,6 @@ export class deviceConfig extends FormApplication {
this.devices.push(device);
}
return {
devices: this.devices
}

View File

@@ -72,6 +72,7 @@ export const registerSettings = async function() {
//Enabled the module
game.settings.register(moduleName,'Enable', {
name: "MaterialDeck.Sett.Enable",
hint: "MaterialDeck.Sett.EnableHint",
scope: "client",
config: true,
default: false,
@@ -79,6 +80,14 @@ export const registerSettings = async function() {
onChange: x => window.location.reload()
});
game.settings.register(moduleName,'EnableDialogShown', {
name: "MaterialDeck_EnableDialogShown",
scope: "client",
config: false,
default: false,
type: Boolean
});
/**
* System override
*/

View File

@@ -47,12 +47,16 @@ export class StreamDeck{
device: device.id,
name: device.name,
type: device.type,
size: size,
size: deckSize,
buttons: buttons
}
}
}
removeDevice(iteration) {
this.buttonContext[iteration] = undefined;
}
setContext(device,size,iteration,action,context,coordinates = {column:0,row:0},settings, name, type){
if (device == undefined) return;
if (this.buttonContext[iteration] == undefined) {
@@ -131,6 +135,7 @@ export class StreamDeck{
counter++;
}
}
let txtNew = "";
let newTxtArray = ['','','','','','','','','','','','','','','','','','','',''];
counter = 0;
@@ -139,27 +144,41 @@ export class StreamDeck{
let txtNewPart = txtArray[i];
if (txtNewPart != undefined && txtNewPart.length > 10){
let syllables = this.syllabify(txtNewPart);
for (let j=0; j<syllables.length; j++){
if (syllables.length == 0){
let syllables = [];
if (game.i18n.lang == "ru") {
newTxtArray[counter] = txtNewPart.slice(0,txtNewPart.length/2) + '-';
counter++;
newTxtArray[counter] = txtNewPart.slice(txtNewPart.length/2+1,txtNewPart.length);
counter++;
}
else {
syllables = this.syllabify(txtNewPart);
if (syllables == null) {
newTxtArray[counter] = txtNewPart;
counter++;
}
else if (syllables[j+1] == undefined){
newTxtArray[counter] = syllables[j];
counter++;
}
else if ((syllables[j].length+syllables[j+1].length) < 10){
newTxtArray[counter] = syllables[j]+syllables[j+1];
if (syllables.length-2 > j) newTxtArray[counter] += '-';
counter++;
j++;
}
else {
newTxtArray[counter] = syllables[j];
if (syllables.length > j) newTxtArray[counter] += '-';
counter++;
for (let j=0; j<syllables.length; j++){
if (syllables.length == 0){
newTxtArray[counter] = txtNewPart;
counter++;
}
else if (syllables[j+1] == undefined){
newTxtArray[counter] = syllables[j];
counter++;
}
else if ((syllables[j].length+syllables[j+1].length) < 10){
newTxtArray[counter] = syllables[j]+syllables[j+1];
if (syllables.length-2 > j) newTxtArray[counter] += '-';
counter++;
j++;
}
else {
newTxtArray[counter] = syllables[j];
if (syllables.length > j) newTxtArray[counter] += '-';
counter++;
}
}
}
}
}
@@ -186,15 +205,14 @@ export class StreamDeck{
setTitle(txt,context){
if (txt == null || txt == undefined) txt = '';
txt = this.formatTitle(txt);
for (let i=0; i<32; i++){
if (this.buttonContext[i] == undefined) continue;
if (this.buttonContext[i].context == context) {
if (this.buttonContext[i].txt != undefined)
if (this.buttonContext[i].txt == txt)
return;
this.buttonContext[i].txt = txt;
}
for (let device of this.buttonContext) {
if (device == undefined) continue;
const btn = device.buttons.find(b => b?.context == context);
if (btn == undefined) continue;
btn.txt = txt;
}
let msg = {
target: "SD",
event: 'setTitle',

View File

@@ -1,16 +1,42 @@
import { compatibleCore } from "../misc.js";
export class demonlord{
conf;
constructor(){
console.log("Material Deck: Using system 'Shadow of the Demon Lord'");
this.conf = CONFIG.DL;
}
getActorData(token) {
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
return token.actor.system;
}
getItemData(item) {
return compatibleCore('10.0') ? item.system : item.data.data;
return item.system;
}
getStatsList() {
return [
{value:'HP', name:'HP'},
{value:'HPbox', name:'HP (box)'},
{value:'AC', name:'AC'},
{value:'Speed', name:'Speed'},
{value:'Init', name:'Initiative'},
{value:'Ability', name:'Ability Score'},
{value:'AbilityMod', name:'Ability Score Modifier'}
]
}
getAttackModes() {
return [
{value:'attack', name:'Attack'},
{value:'damage', name:'Damage'},
{value:'damageCrit', name:'Critical Damage'},
{value:'versatile', name:'Versatile Damage'},
{value:'versatileCrit', name:'Versatile Critical Damage'},
{value:'otherFormula', name:'Other Formula'},
]
}
getHP(token) {
@@ -71,6 +97,17 @@ export class demonlord{
return;
}
getSavesList() {
return [];
}
getAbilityList() {
const keys = Object.keys(this.conf.attributes);
let abilities = [];
for (let k of keys) abilities.push({value:k, name:this.conf.attributes?.[k]})
return abilities;
}
getSkill(token, skill) {
if (skill == undefined) skill = 'acr';
const val = this.getActorData(token).skills?.[skill].total;
@@ -92,6 +129,12 @@ export class demonlord{
return token.actor.effects.find(e => e.isTemporary === condition) != undefined;
}
getConditionList() {
let conditions = [];
for (let c of CONFIG.statusEffects) if (c.disabled != undefined) conditions.push({value:c.id, name:c.label});
return conditions;
}
async toggleCondition(token,condition) {
if (condition == undefined) condition = 'removeAll';
if (condition == 'removeAll'){
@@ -128,7 +171,7 @@ export class demonlord{
/**
* Spells
*/
getSpells(token,level) {
getSpells(token,level,type) {
if (level == undefined) level = 'any';
const allItems = token.actor.items;
if (level == 'any') return allItems.filter(i => i.type == 'spell')
@@ -139,6 +182,11 @@ export class demonlord{
return;
}
getSpellTypes() {
return [
]
}
rollItem(item) {
return item.roll()
}
@@ -153,4 +201,46 @@ export class demonlord{
getSaveRingColor(token, save) {
return;
}
getSkillList() {
return [];
}
getOnClickList() {
return [{value:'initiative',name:'Toggle Initiative'}]
}
getRollTypes() {
return []
}
getItemTypes() {
return []
}
getWeaponRollModes() {
return []
}
getFeatureTypes() {
return [
{value:'class', name:'Class'},
{value:'feat', name:'Abilities'}
]
}
getSpellLevels() {
return [
{value:'0', name:'Cantrip'},
{value:'1', name:'1st Level'},
{value:'2', name:'2nd Level'},
{value:'3', name:'3rd Level'},
{value:'4', name:'4th Level'},
{value:'5', name:'5th Level'},
{value:'6', name:'6th Level'},
{value:'7', name:'7th Level'},
{value:'8', name:'8th Level'},
{value:'9', name:'9th Level'}
]
}
}

View File

@@ -1,16 +1,47 @@
import { compatibleCore } from "../misc.js";
export class dnd35e{
constructor(){
conf;
system;
constructor(gamingSystem){
console.log("Material Deck: Using system 'Dungeons & Dragons 3.5e'/'Pathfinder 1e'");
if (gamingSystem == 'D35E') this.conf = CONFIG.D35E;
else if (gamingSystem == 'pf1') this.conf = CONFIG.PF1;
this.system = gamingSystem;
}
getActorData(token) {
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
return token.actor.system;
}
getItemData(item) {
return compatibleCore('10.0') ? item.system : item.data.data;
return item.system;
}
getStatsList() {
return [
{value:'HP', name:'HP'},
{value:'HPbox', name:'HP (box)'},
{value:'TempHP', name:'Temp HP'},
{value:'AC', name:'AC'},
{value:'Speed', name:'Speed'},
{value:'Init', name:'Initiative'},
{value:'Ability', name:'Ability Score'},
{value:'AbilityMod', name:'Ability Score Modifier'},
{value:'Save', name:'Saving Throw Modifier'},
{value:'Skill', name:'Skill Modifier'},
{value:'Prof', name:'Proficiency'}
]
}
getAttackModes() {
return [
]
}
getOnClickList() {
return []
}
getHP(token) {
@@ -94,12 +125,36 @@ export class dnd35e{
return (val >= 0) ? `+${val}` : val;
}
getAbilityList() {
const keys = Object.keys(this.conf.abilities);
let abilities = [];
for (let k of keys) abilities.push({value:this.conf.abilityAbbreviations?.[k], name:this.conf.abilities?.[k]})
return abilities;
}
getSavesList() {
const keys = Object.keys(this.conf.savingThrows);
let saves = [];
for (let k of keys) saves.push({value:k, name:this.conf.savingThrows?.[k]})
return saves;
}
getSkill(token, skill) {
if (skill == undefined) skill = 'apr';
const val = this.getActorData(token).skills?.[skill].mod;
return (val >= 0) ? `+${val}` : val;
}
getSkillList() {
const keys = Object.keys(this.conf.skills);
let skills = [];
for (let s of keys) {
const skill = this.conf.skills?.[s];
skills.push({value:s, name:skill})
}
return skills;
}
getProficiency(token) {
const val = this.getActorData(token).attributes.prof;
return (val >= 0) ? `+${val}` : val;
@@ -129,6 +184,12 @@ export class dnd35e{
return true;
}
getConditionList() {
let conditions = [];
for (let c of CONFIG.statusEffects) conditions.push({value:c.id, name:game.i18n.localize(c.label)});
return conditions;
}
/**
* Roll
*/
@@ -151,6 +212,27 @@ export class dnd35e{
else if (roll == 'ranged') token.actor.rollRanged(options);
}
getRollTypes() {
if (this.system == 'D35E') {
return [
{value:'initiative', name:'Initiative'},
{value:'grapple', name:'Grapple'},
{value:'bab', name:'Base Attack Bonus'},
{value:'melee', name:'Melee'},
{value:'ranged', name:'Ranged'}
]
}
else if (this.system == 'pf1') {
return [
{value:'initiative', name:'Initiative'},
{value:'cmb', name:'Combat Maneuver Bonus'},
{value:'bab', name:'Base Attack Bonus'},
{value:'attack', name:'Attack'},
{value:'defenses', name:'Defenses'}
]
}
}
/**
* Items
*/
@@ -170,6 +252,23 @@ export class dnd35e{
return {available: this.getItemData(item).quantity};
}
getItemTypes() {
return [
{value:'weapon', name:'Weapons'},
{value:'equipment', name:'Armor/Equipment'},
{value:'consumable', name:'Consumables'},
{value:'gear', name:'Gear'},
{value:'ammo', name:'Ammunition'},
{value:'misc', name:'Miscellaneous'},
{value:'tradeGoods', name:'Trade Goods'},
{value:'container', name:'Containers'}
]
}
getWeaponRollModes() {
return []
}
/**
* Features
*/
@@ -188,10 +287,17 @@ export class dnd35e{
};
}
getFeatureTypes() {
return [
{value:'class', name:'Class'},
{value:'feat', name:'Abilities'}
]
}
/**
* Spells
*/
getSpells(token,level) {
getSpells(token,level,type) {
if (level == undefined) level = 'any';
const allItems = token.actor.items;
if (level == 'any') return allItems.filter(i => i.type == 'spell')
@@ -207,6 +313,18 @@ export class dnd35e{
}
}
getSpellLevels() {
const keys = Object.keys(this.conf.spellLevels);
let levels = [];
for (let l of keys) levels.push({value:l, name:this.conf.spellLevels?.[l]});
return levels;
}
getSpellTypes() {
return [
]
}
rollItem(item) {
return item.roll()
}

View File

@@ -1,4 +1,4 @@
import { compatibleCore } from "../misc.js";
import { compatibleCore, compatibleSystem } from "../misc.js";
const proficiencyColors = {
0: "#000000",
@@ -8,16 +8,52 @@ const proficiencyColors = {
}
export class dnd5e{
conf;
constructor(){
console.log("Material Deck: Using system 'Dungeons & Dragons 5e'");
this.conf = game.system.config;
}
getActorData(token) {
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
return token.actor.system;
}
getItemData(item) {
return compatibleCore('10.0') ? item.system : item.data.data;
return item.system;
}
getStatsList() {
return [
{value:'HP', name:'HP'},
{value:'HPbox', name:'HP (box)'},
{value:'TempHP', name:'Temp HP'},
{value:'AC', name:'AC'},
{value:'Speed', name:'Speed'},
{value:'Init', name:'Initiative'},
{value:'Ability', name:'Ability Score'},
{value:'AbilityMod', name:'Ability Score Modifier'},
{value:'Save', name:'Saving Throw Modifier'},
{value:'Skill', name:'Skill Modifier'},
{value:'PassivePerception', name:'Passive Perception'},
{value:'PassiveInvestigation', name:'Passive Investigation'},
{value:'Prof', name:'Proficiency'}
]
}
getAttackModes() {
return [
{value:'attack', name:'Attack'},
{value:'damage', name:'Damage'},
{value:'damageCrit', name:'Critical Damage'},
{value:'versatile', name:'Versatile Damage'},
{value:'versatileCrit', name:'Versatile Critical Damage'},
{value:'otherFormula', name:'Other Formula'},
]
}
getOnClickList() {
return []
}
getHP(token) {
@@ -107,12 +143,36 @@ export class dnd5e{
return (val >= 0) ? `+${val}` : val;
}
getAbilityList() {
const keys = Object.keys(this.conf.abilities);
let abilities = [];
if (compatibleSystem("2.2.0"))
for (let k of keys) abilities.push({value:this.conf.abilityAbbreviations?.[k], name:this.conf.abilities?.[k]})
else
for (let k of keys) abilities.push({value:this.conf.abilities?.[k].abbreviation, name:this.conf.abilities?.[k].label})
return abilities;
}
getSavesList() {
return this.getAbilityList();
}
getSkill(token, skill) {
if (skill == undefined) skill = 'acr';
const val = this.getActorData(token).skills?.[skill].total;
return (val >= 0) ? `+${val}` : val;
}
getSkillList() {
const keys = Object.keys(this.conf.skills);
let skills = [];
for (let s of keys) {
const skill = this.conf.skills?.[s];
skills.push({value:s, name:skill.label})
}
return skills;
}
getProficiency(token) {
const val = this.getActorData(token).attributes.prof;
return (val >= 0) ? `+${val}` : val;
@@ -129,6 +189,12 @@ export class dnd5e{
return token.actor.effects.find(e => e.isTemporary === condition) != undefined;
}
getConditionList() {
let conditions = [];
for (let c of CONFIG.statusEffects) conditions.push({value:c.id, name:game.i18n.localize(c.label)});
return conditions;
}
async toggleCondition(token,condition) {
if (condition == undefined) condition = 'removeAll';
if (condition == 'removeAll'){
@@ -161,6 +227,13 @@ export class dnd5e{
else if (roll == 'deathSave') token.actor.rollDeathSave(options);
}
getRollTypes() {
return [
{value:'initiative', name:'Initiative'},
{value:'deathSave', name:'Death Save'}
]
}
/**
* Items
*/
@@ -175,6 +248,29 @@ export class dnd5e{
return {available: this.getItemData(item).quantity};
}
getItemTypes() {
return [
{value:'weapon', name:'Weapons'},
{value:'equipment', name:'Equipment'},
{value:'consumable', name:'Consumables'},
{value:'tool', name:'Tools'},
{value:'backpack', name:'Containers'},
{value:'loot', name:'Loot'}
]
}
getWeaponRollModes() {
return [
{value:'default', name:'Default'},
{value:'attack', name:'Attack'},
{value:'damage', name:'Damage'},
{value:'damageCrit', name:'Damage (Critical)'},
{value:'versatile', name:'Versatile'},
{value:'versatileCrit', name:'Versatile (Critical)'},
{value:'otherFormula', name:'Other Formula'}
]
}
/**
* Features
*/
@@ -196,14 +292,26 @@ export class dnd5e{
};
}
getFeatureTypes() {
return [
{value:'class', name:'Class'},
{value:'feat', name:'Abilities'},
{value:'activeAbilities', name:'Active Abilities'},
{value:'passiveAbilities', name:'Passive Abilities'}
]
}
/**
* Spells
*/
getSpells(token,level) {
getSpells(token,level,type) {
if (level == undefined) level = 'any';
if (type == undefined) type = 'any';
const allItems = token.actor.items;
if (level == 'any') return allItems.filter(i => i.type == 'spell')
else return allItems.filter(i => i.type == 'spell' && this.getItemData(i).level == level)
else if (type == 'any') return allItems.filter(i => i.type == 'spell' && this.getItemData(i).level == level)
else if (type == 'prepared') return allItems.filter(i => i.type == 'spell' && this.getItemData(i).level == level && i.system.preparation.prepared == true)
else if (type == 'unprepared') return allItems.filter(i => i.type == 'spell' && this.getItemData(i).level == level && i.system.preparation.prepared == false)
}
getSpellUses(token,level,item) {
@@ -215,40 +323,47 @@ export class dnd5e{
}
}
rollItem(item, settings, rollOption) {
getSpellLevels() {
const keys = Object.keys(this.conf.spellLevels);
let levels = [];
for (let l of keys) levels.push({value:l, name:this.conf.spellLevels?.[l]});
return levels;
}
getSpellTypes() {
return [
{value: 'prepared', name:'Prepared'},
{value: 'unprepared', name:'Unprepared'}
]
}
rollItem(item, settings, rollOption, attackMode) {
let options = {
fastForward: rollOption != 'dialog',
advantage: rollOption == 'advantage',
disadvantage: rollOption == 'disadvantage'
}
if (settings.inventoryType == 'weapon') {
if (settings.weaponRollMode == 'attack') {
if (settings.tokenMode == 'inventory' && settings.inventoryType == 'weapon') {
const mode = settings.weaponRollMode == 'default' ? attackMode : settings.weaponRollMode;
if (mode == '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') {
else if (mode == 'otherFormula') {
return item.rollFormula(options);
}
else if (mode != 'default' && mode != 'chat') {
options.fastForward = true;
return item.rollDamage({
options,
critical: (mode == 'damageCrit' || mode == 'versatileCrit'),
versatile: (mode == 'versatile' || mode == 'versatileCrit')
});
}
}
if (compatibleCore('10.0')) item.use(options)
else item.roll(options)
item.use(options)
}
/**

View File

@@ -1,16 +1,41 @@
import { compatibleCore } from "../misc.js";
export class forbiddenlands{
conf;
constructor(){
console.log("Material Deck: Using system 'Forbidden Lands'");
this.conf = CONFIG.fbl;
}
getActorData(token) {
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
return token.actor.system;
}
getItemData(item) {
return compatibleCore('10.0') ? item.system : item.data.data;
return item.system;
}
getStatsList() {
return [
{value:'HP', name:'Strength'},
{value:'HPbox', name:'Strength (box)'},
{value:'Agility', name:'Agility'},
{value:'Wits', name:'Wits'},
{value:'Empathy', name:'Empathy'},
{value:'WillPower', name:'Will Power'},
{value:'AC', name:'Armor'},
{value:'Skill', name:'Skill'}
]
}
getAttackModes() {
return [
]
}
getOnClickList() {
return []
}
getHP(token) {
@@ -103,6 +128,17 @@ export class forbiddenlands{
return this.getAbility(token, ability);
}
getAbilityList() {
const abilityList = this.conf.attributes;
let abilities = [];
for (let a of abilityList) abilities.push({value:a, name:a.charAt(0).toUpperCase() + a.slice(1)})
return abilities;
}
getSavesList() {
return this.getAbilityList();
}
getSkill(token, skill) {
if (skill == undefined) skill = 'might';
let skillComp = token.actor.sheet.getSkill(skill);
@@ -110,6 +146,18 @@ export class forbiddenlands{
return game.i18n.localize(skillComp.skill.label)+`-${val}`;
}
getSkillList() {
const keys = Object.keys(this.conf.skillAttributeMap);
let skills = [];
for (let s of keys) {
const nameArr = s.split('-');
let name = '';
for (let p of nameArr) name += p.charAt(0).toUpperCase() + p.slice(1) + ' ';
skills.push({value:s, name})
}
return skills;
}
getProficiency(token) {
return;
}
@@ -138,6 +186,12 @@ export class forbiddenlands{
return true;
}
getConditionList() {
let conditions = [];
for (let c of CONFIG.statusEffects) conditions.push({value:c.id, name:game.i18n.localize(c.label)});
return conditions;
}
/**
* Roll
*/
@@ -159,6 +213,17 @@ export class forbiddenlands{
//else if (roll == 'initiative') token.actor.rollInitiative(options);
}
getRollTypes() {
return [
{value:'rollFood', name:'Roll Food'},
{value:'rollWater', name:'Roll Water'},
{value:'rollArrows', name:'Roll Arrows'},
{value:'rollTorches', name:'Roll Torches'},
{value:'rollArmor', name:'Roll Armor'},
{value:'monsterAttack', name:'Roll Monster Attack'}
]
}
/**
* Items
*/
@@ -180,6 +245,19 @@ export class forbiddenlands{
maximum: this.getItemData(item).bonus.max};
}
getItemTypes() {
return [
{value:'armor', name: "Armour"},
{value:'gear', name: "Gear"},
{value:'weapon', name: "Weapons"},
{value:'rawMaterial', name: "Raw Material"}
]
}
getWeaponRollModes() {
return []
}
/**
* Features
*/
@@ -198,10 +276,14 @@ export class forbiddenlands{
};
}
getFeatureTypes() {
return []
}
/**
* Spells
*/
getSpells(token,level) {
getSpells(token,level,type) {
if (level == undefined) level = 'any';
const allItems = token.actor.items;
if (level == 'any') return allItems.filter(i => i.type == 'spell')
@@ -217,6 +299,15 @@ export class forbiddenlands{
}
}
getSpellLevels() {
return [];
}
getSpellTypes() {
return [
]
}
rollItem(item) {
const sheet = item.actor.sheet;
if (item.type === "armor")

View File

@@ -12,19 +12,49 @@ const proficiencyColors =
};
export class pf2e{
conf;
constructor(){
console.log("Material Deck: Using system 'Pathfinder 2e'");
this.conf = CONFIG.PF2E;
}
tokenSpellData = new Map();
getActorData(token) {
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
return token.actor.system;
}
getItemData(item) {
return compatibleCore('10.0') ? item.system : item.data.data;
return item.system;
}
getStatsList() {
return [
{value:'HP', name:'HP'},
{value:'HPbox', name:'HP (box)'},
{value:'TempHP', name:'Temp HP'},
{value:'AC', name:'AC'},
{value:'ShieldHP', name:'Shield HP'},
{value:'Speed', name:'Speed'},
{value:'Init', name:'Initiative'},
{value:'Ability', name:'Ability Score'},
{value:'AbilityMod', name:'Ability Score Modifier'},
{value:'Save', name:'Saving Throw Modifier'},
{value:'Skill', name:'Skill Modifier'},
{value:'Prof', name:'Proficiency'},
{value:'Condition', name: 'Condition'},
{value:'Perception', name: 'Perception'}
]
}
getAttackModes() {
return [
]
}
getOnClickList() {
return []
}
getHP(token) {
@@ -116,24 +146,41 @@ export class pf2e{
}
getAbilitySave(token, ability) {
ability = this.fixSave(ability);
if (ability == undefined) return 'fortitude';
//ability = this.fixSave(ability);
const save = this.findSave(token, ability);
if (save == undefined) return '';
let val = save?.value;
return (val >= 0) ? `+${val}` : val;
}
getAbilityList() {
const keys = Object.keys(this.conf.abilities);
let abilities = [];
for (let k of keys) abilities.push({value:k, name:game.i18n.localize(this.conf.abilities?.[k])})
return abilities;
}
findSave(token, ability) {
if (this.isLimitedSheet(token.actor)) return;
return this.getActorData(token).saves?.[ability];
}
/*
fixSave(ability) {
if (ability == undefined) return 'fortitude';
else if (ability == 'fort') return 'fortitude';
else if (ability == 'ref') return 'reflex';
else if (ability == 'will') return 'will';
}
*/
getSavesList() {
const keys = Object.keys(this.conf.saves);
let saves = [];
for (let k of keys) saves.push({value:k, name:game.i18n.localize(this.conf.saves?.[k])})
return saves;
}
getSkill(token, skill) {
const tokenSkill = this.findSkill(token, skill);
@@ -162,6 +209,16 @@ export class pf2e{
return this.getActorData(token).skills?.[skill];
}
getSkillList() {
const keys = Object.keys(this.conf.skills);
let skills = [];
for (let s of keys) {
skills.push({value:s, name:game.i18n.localize(this.conf.skills?.[s])})
}
for (let i=1; i<4; i++) skills.push({value:`lor_${i}`, name: `${game.i18n.localize(this.conf.skillList.lore)} #${i}`})
return skills;
}
getLoreSkills(token) {
if (this.isLimitedSheet(token.actor)) return [];
const skills = this.getActorData(token).skills;
@@ -240,6 +297,12 @@ export class pf2e{
return true;
}
getConditionList() {
let conditions = [];
for (let c of CONFIG.statusEffects) conditions.push({value:c.id, name:game.i18n.localize(c.label)});
return conditions;
}
/**
* Roll
*/
@@ -289,6 +352,13 @@ export class pf2e{
game.pf2e.Check.roll(checkModifier, {type:type, actor: actor, skipDialog: true}, null);
}
getRollTypes() {
return [
{value:'initiative', name:'Initiative'},
{value:'perception', name:'Perception'}
]
}
/**
* Items
*/
@@ -304,6 +374,20 @@ export class pf2e{
getItemUses(item) {
return {available: item.quantity};
}
getItemTypes() {
return [
{value:'weapon', name:'Weapons'},
{value:'armor', name:'Armor'},
{value:'equipment', name:'Equipment'},
{value:'consumable', name:'Consumables'},
{value:'treasure', name:'Treasure'}
]
}
getWeaponRollModes() {
return []
}
/**
* Features
@@ -347,6 +431,30 @@ export class pf2e{
else return;
}
getFeatureTypes() {
return [
{value:'ancestry', name:'Ancestry'},
{value:'ancestryfeature', name:'Ancestry Feature'},
{value:'heritage', name: 'Heritage'},
{value:'background', name: 'Background'},
{value:'class', name:'Class'},
{value:'classfeature', name:'Class Feature'},
{value:'deity', name: 'Deity'},
{value:'feat-any', name:'Feats - Any'},
{value:'feat-anc', name:'Feats - Ancestry'},
{value:'feat-arc', name: 'Feats - Archetype'},
{value:'feat-ded', name: 'Feats - Dedication'},
{value:'feat-cla', name: 'Feats - Class'},
{value:'feat-gen', name: 'Feats - General'},
{value:'feat-ski', name: 'Feats - Skill'},
{value:'action-any', name:'Actions - Any'},
{value:'action-def', name:'Actions - Defensive'},
{value:'action-int', name:'Actions - Interaction'},
{value:'action-off', name:'Actions - Offensive'},
{value:'strike', name:'Strikes'}
]
}
/**
* Spells
*/
@@ -402,7 +510,7 @@ export class pf2e{
return spell.level;
}
getSpells(token,level) {
getSpells(token,level,type) {
if (this.isLimitedSheet(token.actor)) return '';
if (level == undefined) level = 'any';
let spellData = this.getSpellData(token);
@@ -468,6 +576,21 @@ export class pf2e{
return result;
}
getSpellLevels() {
const keys = Object.keys(this.conf.spellLevels);
let levels = [
{value:'f', name: game.i18n.localize("PF2E.SpellCategoryFocus")},
{value:'0', name: game.i18n.localize("PF2E.SpellCantripLabel")}
];
for (let l of keys) levels.push({value:l, name:game.i18n.localize(this.conf.spellLevels?.[l])});
return levels;
}
getSpellTypes() {
return [
]
}
rollItem(item, settings) {
let variant = 0;
if (otherControls.rollOption == 'map1') variant = 1;
@@ -514,7 +637,7 @@ export class pf2e{
}
getSaveRingColor(token, save) {
save = this.fixSave(save);
//save = this.fixSave(save);
return this.getRingColor(this.findSave(token, save));
}

View File

@@ -8,16 +8,44 @@ const proficiencyColors = {
}
export class starfinder{
conf;
constructor(){
console.log("Material Deck: Using system 'Starfinder'");
this.conf = CONFIG.SFRPG;
}
getActorData(token) {
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
return token.actor.system;
}
getItemData(item) {
return compatibleCore('10.0') ? item.system : item.data.data;
return item.system;
}
getStatsList() {
return [
{value:'HP', name:'HP'},
{value:'HPbox', name:'HP (box)'},
{value:'Stamina', name:'Stamina'},
{value:'AC', name:'Energy AC'},
{value:'KinAC', name:'Kinetic AC'},
{value:'Speed', name:'Speed'},
{value:'Init', name:'Initiative'},
{value:'Ability', name:'Ability Score'},
{value:'AbilityMod', name:'Ability Score Modifier'},
{value:'Save', name:'Saving Throw Modifier'},
{value:'Skill', name:'Skill Modifier'}
]
}
getAttackModes() {
return [
]
}
getOnClickList() {
return []
}
getHP(token) {
@@ -110,12 +138,36 @@ export class starfinder{
return (val >= 0) ? `+${val}` : val;
}
getAbilityList() {
const keys = Object.keys(this.conf.abilities);
let abilities = [];
for (let k of keys) abilities.push({value:k, name:this.conf.abilities?.[k]})
return abilities;
}
getSavesList() {
const keys = Object.keys(this.conf.saves);
let saves = [];
for (let k of keys) saves.push({value:k, name:this.conf.saves?.[k]})
return saves;
}
getSkill(token, skill) {
if (skill == undefined) skill = 'acr';
const val = this.getActorData(token).skills?.[skill].mod;
return (val >= 0) ? `+${val}` : val;
}
getSkillList() {
const keys = Object.keys(this.conf.skills);
let skills = [];
for (let s of keys) {
const skill = this.conf.skills?.[s];
skills.push({value:s, name:skill.label})
}
return skills;
}
getProficiency(token) {
return;
}
@@ -144,6 +196,12 @@ export class starfinder{
return true;
}
getConditionList() {
let conditions = [];
for (let c of CONFIG.statusEffects) conditions.push({value:c.id, name:c.label});
return conditions;
}
/**
* Roll
*/
@@ -163,6 +221,13 @@ export class starfinder{
else if (roll == 'deathSave') token.actor.rollDeathSave(options);
}
getRollTypes() {
return [
{value:'initiative', name:'Initiative'},
{value:'deathSave', name:'Death Save'}
]
}
/**
* Items
*/
@@ -178,6 +243,25 @@ export class starfinder{
return {available: this.getItemData(item).quantity};
}
getItemTypes() {
return [
{value:'weapon', name:'Weapons'},
{value:'shield', name:'Shields'},
{value:'equipment', name:'Armor'},
{value:'ammunition', name:'Ammunition'},
{value:'consumable', name:'Consumables'},
{value:'goods', name:'Goods'},
{value:'container', name:'Containers'},
{value:'technological', name:'Technological, Magical, and Hybrid Items'},
{value:'enhancers', name:'Equipment Enhancers'},
{value:'augmentation', name:'Augmentations'}
]
}
getWeaponRollModes() {
return []
}
/**
* Features
*/
@@ -201,10 +285,23 @@ export class starfinder{
};
}
getFeatureTypes() {
return [
{value:'class', name:'Class'},
{value:'race', name:'Race'},
{value:'theme', name:'Theme'},
{value:'asi', name:'Ability Score Increases'},
{value:'archetypes', name:'Archetypes'},
{value:'activeFeat', name:'Active Feats'},
{value:'passiveFeat', name:'Passive Feats'},
{value:'actorResource', name:'Actor Resources'}
]
}
/**
* Spells
*/
getSpells(token,level) {
getSpells(token,level,type) {
if (level == undefined) level = 'any';
const allItems = token.actor.items;
if (level == 'any') return allItems.filter(i => i.type == 'spell')
@@ -232,6 +329,18 @@ export class starfinder{
return uses;
}
getSpellLevels() {
const keys = Object.keys(this.conf.spellLevels);
let levels = [{label:'innate', name:game.i18n.localize("SFRPG.SpellPreparationModesInnate")}];
for (let l of keys) levels.push({value:l, name:this.conf.spellLevels?.[l]});
return levels;
}
getSpellTypes() {
return [
]
}
rollItem(item) {
return item.roll()
}

View File

@@ -24,16 +24,54 @@ const proficiencyColors = {
//Rename 'template' to the name of your system
export class template{
conf; //this variable stores the configuration data for the system, set in the constructor
constructor(){
console.log("Material Deck: Using system 'SystemName'");
this.conf = CONFIG.DND5E; //You can use this to get various things like the list of ability scores, conditions, etc. Make sure you set it to the correct value for your system
}
getActorData(token) {
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
return token.actor.system;
}
getItemData(item) {
return compatibleCore('10.0') ? item.system : item.data.data;
return item.system;
}
/**
* This generates a list of stats to be displayed on the SD: Token Action => Stats.
* Choose the ones you want to use and change the 'name' value if desired. If you add new ones, you will need to add a function to handle them in src/token.js.
* After each option you'll find what function it will call after the button is pressed on the SD
*/
getStatsList() {
return [
{value:'HP', name:'HP'}, //will call getHP()
{value:'HPbox', name:'HP (box)'}, //will call getHP()
{value:'TempHP', name:'Temp HP'}, //will call getTempHP()
{value:'AC', name:'AC'}, //will call getAC()
{value:'ShieldHP', name:'Shield HP'}, //will call getShieldHP()
{value:'Speed', name:'Speed'}, //will call getSpeed()
{value:'Init', name:'Initiative'}, //will call getInitiative()
{value:'Ability', name:'Ability Score'}, //will call getAbility()
{value:'AbilityMod', name:'Ability Score Modifier'}, //will call getAbilityModifier()
{value:'Save', name:'Saving Throw Modifier'}, //will call getAbilitySave()
{value:'Skill', name:'Skill Modifier'}, //will call getSkill()
{value:'PassivePerception', name:'Passive Perception'}, //will call getPassivePerception()
{value:'PassiveInvestigation', name:'Passive Investigation'}, //will call getPassiveInvestigation()
{value:'Prof', name:'Proficiency'}, //will call getProficiency()
{value:'Condition', name: 'Condition'}, //will call getConditionValue()
]
}
/**
* Adds an on click option to the SD: Token Action => On Click
* Currently only supports toggling initiative (for Shadow of the Demonlord)
*/
getOnClickList() {
return [
//{value:'initiative',name:'Toggle Initiative'}
]
}
/**
@@ -149,6 +187,17 @@ export class template{
return;
}
/**
* Returns a list of abilities available to the system
* Each array item must be {value:'abilityId', name:'abilityName'}
* 'abilityId' is defined by the system, the name can be anything you want
* @returns
*/
getAbilityList() {
let abilities = [];
return abilities;
}
/**
* Returns the skill value of the token
* @param {Token} token Token instance to get the skill value from

View File

@@ -8,7 +8,6 @@ import { starfinder } from "./starfinder.js";
import { compatibleCore } from "../misc.js";
import { gamingSystem } from "../../MaterialDeck.js";
export class TokenHelper{
constructor(){
this.system;
@@ -16,7 +15,7 @@ export class TokenHelper{
}
setSystem() {
if (gamingSystem == 'D35E' || gamingSystem == 'pf1') this.system = new dnd35e();
if (gamingSystem == 'D35E' || gamingSystem == 'pf1') this.system = new dnd35e(gamingSystem);
else if (gamingSystem == 'pf2e') this.system = new pf2e();
else if (gamingSystem == 'demonlord') this.system = new demonlord();
else if (gamingSystem == 'wfrp4e') this.system = new wfrp4e();
@@ -58,7 +57,7 @@ export class TokenHelper{
moveToken(token,dir){
if (dir == undefined) dir = 'up';
const gridSize = compatibleCore('10.0') ? canvas.scene.grid.size : canvas.scene.data.grid;
const gridSize = canvas.scene.grid.size;
let x = token.x;
let y = token.y;
@@ -99,7 +98,7 @@ export class TokenHelper{
value = isNaN(parseInt(value)) ? 0 : parseInt(value);
let rotationVal;
if (move == 'by') rotationVal = compatibleCore('10.0') ? token.document.rotation + value : token.data.rotation + value;
if (move == 'by') rotationVal = token.document.rotation + value;
else rotationVal = value;
token.document.update({rotation: rotationVal});
@@ -128,16 +127,29 @@ export class TokenHelper{
////////////////////////////////////////////////////
getTokenIcon(token) {
return compatibleCore('10.0') ? token.document.texture.src : token.data.img;
return token.document.texture.src;
}
getActorIcon(token) {
return compatibleCore('10.0') ? token.actor.img : token.actor.data.img;
return token.actor.img;
}
/***********************************************************************
* System specific functions
***********************************************************************/
getStatsList() {
return this.system.getStatsList();
}
getAttackModes() {
return this.system.getAttackModes();
}
getOnClickList() {
return this.system.getOnClickList();
}
getHP(token) {
return this.system.getHP(token);
}
@@ -186,10 +198,22 @@ export class TokenHelper{
return this.system.getAbilitySave(token, ability);
}
getAbilityList() {
return this.system.getAbilityList();
}
getSavesList() {
return this.system.getSavesList();
}
getSkill(token, skill) {
return this.system.getSkill(token, skill);
}
getSkillList() {
return this.system.getSkillList();
}
getProficiency(token) {
return this.system.getProficiency(token);
}
@@ -279,6 +303,10 @@ export class TokenHelper{
return this.system.toggleCondition(token,condition);
}
getConditionList() {
return this.system.getConditionList();
}
/* PF2E */
getConditionValue(token,condition) {
return this.system.getConditionValue(token,condition);
@@ -296,6 +324,10 @@ export class TokenHelper{
return this.system.roll(token,roll,options,ability,skill,save);
}
getRollTypes() {
return this.system.getRollTypes();
}
/**
* Items
*/
@@ -307,6 +339,14 @@ export class TokenHelper{
return this.system.getItemUses(item);
}
getItemTypes() {
return this.system.getItemTypes();
}
getWeaponRollModes() {
return this.system.getWeaponRollModes();
}
/**
* Features
*/
@@ -318,19 +358,31 @@ export class TokenHelper{
return this.system.getFeatureUses(item);
}
getFeatureTypes() {
return this.system.getFeatureTypes();
}
/**
* Spells
*/
getSpells(token,level) {
return this.system.getSpells(token,level);
getSpells(token,level,type) {
return this.system.getSpells(token,level,type);
}
getSpellUses(token,level,item) {
return this.system.getSpellUses(token,level,item);
}
rollItem(item, settings, rollOption) {
return this.system.rollItem(item, settings, rollOption);
rollItem(item, settings, rollOption, attackMode) {
return this.system.rollItem(item, settings, rollOption, attackMode);
}
getSpellLevels() {
return this.system.getSpellLevels();
}
getSpellTypes() {
return this.system.getSpellTypes();
}
/**

View File

@@ -1,16 +1,44 @@
import { compatibleCore } from "../misc.js";
export class wfrp4e {
conf;
constructor(){
console.log("Material Deck: Using system 'Warhammer Fantasy Roleplaying 4e'");
this.conf = game.wfrp4e.config;
}
getActorData(token) {
return compatibleCore('10.0') ? token.actor.system : token.actor.data.data;
return token.actor.system;
}
getItemData(item) {
return compatibleCore('10.0') ? item.system : item.data.data;
return item.system;
}
getStatsList() {
return [
{value: 'Advantage', name: 'Advantage'},
{value: 'Corruption', name: 'Corruption'},
{value: 'CriticalWounds', name: 'Critical Wounds'},
{value: 'Encumbrance', name: 'Encumbrance'},
{value: 'Fate', name: 'Fate'},
{value: 'Fortune', name: 'Fortune'},
{value: 'Wounds', name: 'Wounds'},
{value: 'Movement', name: 'Movement'},
{value: 'Resilience', name: 'Resilience'},
{value: 'Resolve', name: 'Resolve'},
{value: 'Ability', name: 'Characteristics' } //value is ability to conform to the interface
]
}
getAttackModes() {
return [
]
}
getOnClickList() {
return []
}
getFate(token) {
@@ -27,7 +55,6 @@ export class wfrp4e {
value: wounds.value,
max: wounds.max
}
}
getCriticalWounds(token) {
@@ -58,6 +85,13 @@ export class wfrp4e {
return this.getCharacteristics(token, abilityName);
}
getAbilityList() {
const keys = Object.keys(this.conf.characteristics);
let abilities = [];
for (let k of keys) abilities.push({value:k, name:this.conf.characteristics?.[k]})
return abilities;
}
getCharacteristics(token, characteristicName) {
if (characteristicName == undefined ) characteristicName = `AG`;
const characteristic = this.getActorData(token).characteristics[characteristicName.toLowerCase()]
@@ -71,7 +105,14 @@ export class wfrp4e {
if (featureType == 'any') return allItems.filter(i => i.type == 'skill' || i.type == 'talent' || i.type == "career" || i.type == 'trait');
return allItems.filter(i => i.type == featureType);
}
getSpells(token,spellType) {
getFeatureTypes() {
return [
{value: 'skill', name: 'Skills'}
]
}
getSpells(token,spellLevel,type) {
const allItems = token.actor.items;
return allItems.filter(i => i.type == 'spell')
}
@@ -80,6 +121,26 @@ export class wfrp4e {
return;
}
getSpellLevels() {
return [
{value:'0', name:'Cantrip'},
{value:'1', name:'1st Level'},
{value:'2', name:'2nd Level'},
{value:'3', name:'3rd Level'},
{value:'4', name:'4th Level'},
{value:'5', name:'5th Level'},
{value:'6', name:'6th Level'},
{value:'7', name:'7th Level'},
{value:'8', name:'8th Level'},
{value:'9', name:'9th Level'}
]
}
getSpellTypes() {
return [
]
}
getFeatureUses(item) {
return {available: `+${this.getItemData(item).total.value}`};
}
@@ -92,6 +153,13 @@ export class wfrp4e {
return game.wfrp4e.utility.rollItemMacro(item.name, item.type, false);
}
getRollTypes() {
return [
{value:'initiative', name:'Initiative'},
{value:'deathSave', name:'Death Save'}
]
}
getSpeed(token) {
return this.getActorData(token).details.move.value;
}
@@ -110,13 +178,17 @@ export class wfrp4e {
return true;
}
getConditionList() {
let conditions = [];
for (let c of CONFIG.statusEffects) conditions.push({value:c.id, name:game.i18n.localize(c.label)});
return conditions;
}
roll(token,roll,options,ability,skill,save) {
if (ability == undefined) ability = 'ag';
return game.wfrp4e.utility.rollItemMacro(ability, "characteristic", false);
}
getItems(token,itemType) {
if (itemType == undefined) itemType = 'any';
const allItems = token.actor.items;
@@ -129,7 +201,6 @@ export class wfrp4e {
}
}
getItemUses(item) {
if ( item.type == 'ammunition') {
return {available: this.getItemData(item).quantity.value};
@@ -139,6 +210,20 @@ export class wfrp4e {
}
}
getItemTypes() {
return [
{value:'weapon', name: "Weapons"},
{value:'ammunition', name: "Ammunition"},
{value:'trapping', name: "Trapping"},
{value:'armour', name: "Armour"},
{value:'cargo', name: "Cargo"}
]
}
getSkillList() {
return this.getAbilityList();
}
/* this is all cargo-culted in and some of it could be deleted once the interface is resolved
to not be the superset of all possible systems
@@ -173,6 +258,14 @@ export class wfrp4e {
return;
}
getSavesList() {
return [];
}
getWeaponRollModes() {
return []
}
/**
* Ring Colors
*/