1498 lines
53 KiB
JavaScript
1498 lines
53 KiB
JavaScript
/*
|
|
* Version 0.0.1
|
|
* Made By Noel da Costa
|
|
*/
|
|
// import compendium from './compendium'
|
|
function empty(mixedVar) {
|
|
// discuss at: http://locutus.io/php/empty/
|
|
// original by: Philippe Baumann
|
|
// input by: Onno Marsman (https://twitter.com/onnomarsman)
|
|
// input by: LH
|
|
// input by: Stoyan Kyosev (http://www.svest.org/)
|
|
// bugfixed by: Kevin van Zonneveld (http://kvz.io)
|
|
// improved by: Onno Marsman (https://twitter.com/onnomarsman)
|
|
// improved by: Francesco
|
|
// improved by: Marc Jansen
|
|
// improved by: Rafał Kukawski (http://blog.kukawski.pl)
|
|
// example 1: empty(null)
|
|
// returns 1: true
|
|
// example 2: empty(undefined)
|
|
// returns 2: true
|
|
// example 3: empty([])
|
|
// returns 3: true
|
|
// example 4: empty({})
|
|
// returns 4: true
|
|
// example 5: empty({'aFunc' : function () { alert('humpty'); } })
|
|
// returns 5: false
|
|
var undef;
|
|
var key;
|
|
var i;
|
|
var len;
|
|
var emptyValues = [undef, null, false, 0, "", "0"];
|
|
|
|
for (i = 0, len = emptyValues.length; i < len; i++) {
|
|
if (mixedVar === emptyValues[i]) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (typeof mixedVar === "object") {
|
|
for (key in mixedVar) {
|
|
if (mixedVar.hasOwnProperty(key)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
import compendium from "./compendium";
|
|
|
|
var GW3Companion =
|
|
GW3Companion ||
|
|
(function () {
|
|
"use strict";
|
|
|
|
let observers = {
|
|
tokenChange: [],
|
|
};
|
|
|
|
// Styling for the chat responses.
|
|
const styles = {
|
|
reset: "padding: 0; margin: 0;",
|
|
menuborder:
|
|
"border: 0px solid transparent; border-radius: 4px; padding: 6px; background: red;",
|
|
menu:
|
|
"background-color: #f1f1f1; border: 5px solid transparent; padding: 6px 5px 10px 5px; border-radius: 4px;",
|
|
button:
|
|
"background-color: #000; border: 1px solid #292929; border-radius: 3px; padding: 5px; color: #f1f1f1; text-align: center;",
|
|
list: "list-style: none;",
|
|
float: {
|
|
right: "float: right;",
|
|
left: "float: left;",
|
|
},
|
|
success:
|
|
"color: green; background-color: white; padding: 0.3rem 1rem; margin-left: 1rem, border-radius: 3px;",
|
|
fail:
|
|
"color: red; background-color: white; padding: 0.3rem 1rem; margin-left: 1rem, border-radius: 3px;",
|
|
rank:
|
|
"border: solid 1px black; border-radius: 2px; padding: 2px 4px; background-color: #fefefe; cursor: pointer; display: inline-block;",
|
|
overflow: "overflow: hidden;",
|
|
row: "margin-bottom: 5px",
|
|
fullWidth: "width: 100%;",
|
|
underline: "text-decoration: underline;",
|
|
strikethrough: "text-decoration: strikethrough",
|
|
border:
|
|
"margin-top: 1rem; border: 1px solid #aaa; padding: 1rem; border-radius: 5px;",
|
|
description:
|
|
"font-weight: normal; margin-top: 5px; border: 1px solid grey; padding: 1rem; border-radius: 5px; background-color: #aaa; color: white;",
|
|
effect:
|
|
"font-weight: bold; margin-top: 5px; border: 1px solid grey; padding: 1rem; border-radius: 5px; background-color: #aaa; color: white;",
|
|
},
|
|
script_name = "GW3Companion",
|
|
state_name = "GW3COMPANION",
|
|
markers = [
|
|
"none",
|
|
"blue",
|
|
"brown",
|
|
"green",
|
|
"pink",
|
|
"purple",
|
|
"red",
|
|
"yellow",
|
|
"-",
|
|
"all-for-one",
|
|
"angel-outfit",
|
|
"archery-target",
|
|
"arrowed",
|
|
"aura",
|
|
"back-pain",
|
|
"black-flag",
|
|
"bleeding-eye",
|
|
"bolt-shield",
|
|
"broken-heart",
|
|
"broken-shield",
|
|
"broken-skull",
|
|
"chained-heart",
|
|
"chemical-bolt",
|
|
"cobweb",
|
|
"dead",
|
|
"death-zone",
|
|
"drink-me",
|
|
"edge-crack",
|
|
"fishing-net",
|
|
"fist",
|
|
"fluffy-wing",
|
|
"flying-flag",
|
|
"frozen-orb",
|
|
"grab",
|
|
"grenade",
|
|
"half-haze",
|
|
"half-heart",
|
|
"interdiction",
|
|
"lightning-helix",
|
|
"ninja-mask",
|
|
"overdrive",
|
|
"padlock",
|
|
"pummeled",
|
|
"radioactive",
|
|
"rolling-tomb",
|
|
"screaming",
|
|
"sentry-gun",
|
|
"skull",
|
|
"sleepy",
|
|
"snail",
|
|
"spanner",
|
|
"stopwatch",
|
|
"strong",
|
|
"three-leaves",
|
|
"tread",
|
|
"trophy",
|
|
"white-tower",
|
|
],
|
|
generateUUID = (function () {
|
|
var a = 0,
|
|
b = [];
|
|
return function () {
|
|
var c = new Date().getTime() + 0,
|
|
d = c === a;
|
|
a = c;
|
|
for (var e = new Array(8), f = 7; 0 <= f; f--) {
|
|
e[
|
|
f
|
|
] = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".charAt(
|
|
c % 64
|
|
);
|
|
c = Math.floor(c / 64);
|
|
}
|
|
c = e.join("");
|
|
if (d) {
|
|
for (f = 11; 0 <= f && 63 === b[f]; f--) {
|
|
b[f] = 0;
|
|
}
|
|
b[f]++;
|
|
} else {
|
|
for (f = 0; 12 > f; f++) {
|
|
b[f] = Math.floor(64 * Math.random());
|
|
}
|
|
}
|
|
for (f = 0; 12 > f; f++) {
|
|
c += "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".charAt(
|
|
b[f]
|
|
);
|
|
}
|
|
return c;
|
|
};
|
|
})(),
|
|
generateRowID = function () {
|
|
return generateUUID().replace(/_/g, "Z");
|
|
},
|
|
getParameters = function (args) {
|
|
let parameters = {};
|
|
_.each(args, (arg, key) => {
|
|
let splat = args.shift().split("|");
|
|
if (splat[1] !== undefined) {
|
|
parameters[splat[0]] =
|
|
splat[0] === "title" ? splat[1].replace("_", " ") : splat[1];
|
|
}
|
|
});
|
|
return parameters;
|
|
},
|
|
getRollResult = function (msg, rolltext, callback, parameters) {
|
|
sendChat(msg.playerid, rolltext, function (ops) {
|
|
const rollresult = ops[0];
|
|
log(rollresult);
|
|
let result = JSON.parse(ops[0].content);
|
|
roll = parseInt(result.total);
|
|
callback(roll, parameters);
|
|
});
|
|
},
|
|
handleInput = (msg) => {
|
|
if (msg.type != "api") return;
|
|
let data = {},
|
|
listItems = [],
|
|
contents = "",
|
|
button = "";
|
|
// Split the message into command and argument(s)
|
|
let args = msg.content.split(" ");
|
|
let command = args.shift().substring(1);
|
|
let extracommand = args.shift();
|
|
log(msg);
|
|
log("GM issued " + script_name + " msg: " + msg.content);
|
|
log("GM issued " + script_name + " command: " + command);
|
|
log("state config", state[state_name].config.command);
|
|
if (command == state[state_name].config.command) {
|
|
switch (extracommand) {
|
|
case "reset":
|
|
if (!playerIsGM(msg.playerid)) return;
|
|
state[state_name] = {};
|
|
setDefaults(true);
|
|
sendConfigMenu();
|
|
break;
|
|
|
|
case "config":
|
|
if (!playerIsGM(msg.playerid)) return;
|
|
let message;
|
|
if (args.length > 0) {
|
|
let setting = args.shift().split("|");
|
|
let key = setting.shift();
|
|
let value =
|
|
setting[0] === "true"
|
|
? true
|
|
: setting[0] === "false"
|
|
? false
|
|
: setting[0];
|
|
state[state_name].config[key] = value;
|
|
if (key === "bar") {
|
|
//registerEventHandlers();
|
|
message =
|
|
'<span style="color: red">The API Sandbox needs to be restarted for this to take effect.</span>';
|
|
}
|
|
}
|
|
|
|
sendConfigMenu(false, message);
|
|
break;
|
|
case "set":
|
|
if (!playerIsGM(msg.playerid)) return;
|
|
if (args.length > 0) {
|
|
let score = args.shift().split("|");
|
|
let ability = score.shift();
|
|
log("ability: " + ability);
|
|
log("score: " + score);
|
|
_.each(msg.selected, function (obj) {
|
|
let token, character, attribute, exists;
|
|
token = getObj("graphic", obj._id);
|
|
if (token) {
|
|
character = getObj("character", token.get("represents"));
|
|
}
|
|
|
|
// attribute = getAttrByName(parameters['character'], `${ability}_rolled`);
|
|
attribute = findObjs({
|
|
_type: "attribute",
|
|
characterid: character.id,
|
|
name: `${ability}_rolled`,
|
|
});
|
|
log("ATTRIBUTE: ");
|
|
log(attribute);
|
|
log(attribute.length);
|
|
if (attribute.length) {
|
|
attribute[0].setWithWorker({ current: score });
|
|
}
|
|
// if (character) {
|
|
// let rowId = generateRowID();
|
|
// let objTemplate = {
|
|
// max: '',
|
|
// _id: rowId,
|
|
// _characterid: character.id
|
|
// };
|
|
// let obj = Object.assign(objTemplate, {
|
|
// name:`attr_${ability}_rolled`,
|
|
// current: score
|
|
// });
|
|
// log(obj);
|
|
// createObj('attribute',obj);
|
|
// }
|
|
});
|
|
}
|
|
break;
|
|
case "act":
|
|
log("ACT roll");
|
|
if (args.length > 0) {
|
|
log("args obj...");
|
|
log(args);
|
|
// Get main settings
|
|
let rankSetting = args.shift().split("|");
|
|
log("rankSetting...");
|
|
log(rankSetting);
|
|
let rank = rankSetting.shift();
|
|
log("rank: ", rank);
|
|
let roll1 = rankSetting[0];
|
|
let roll2 = rankSetting[1];
|
|
|
|
// Get other parameters
|
|
const parameters = getParameters(args);
|
|
log("parameters: ");
|
|
log(parameters);
|
|
log("act passed rank: " + rank);
|
|
log("roll1 & roll2...");
|
|
log(roll1);
|
|
log(roll2);
|
|
// log(value);
|
|
|
|
// get target if any and target CS mod and
|
|
rollAct(msg, rank, parameters, roll1, roll2);
|
|
}
|
|
break;
|
|
case "import":
|
|
let ids = args.shift().split("|");
|
|
let category = ids.shift();
|
|
log("name: " + ids);
|
|
log("typeof ids: " + typeof ids);
|
|
log("ids: " + ids);
|
|
log("category: " + category);
|
|
log("typeof category: " + typeof category);
|
|
importCompendiumItemToCharacter(msg, ids, category);
|
|
break;
|
|
case "category":
|
|
log("category");
|
|
log("args length:" + args.length);
|
|
if (args.length > 0) {
|
|
let category = args.shift();
|
|
log("category: " + category);
|
|
let cost = 0;
|
|
data = getData();
|
|
if (!data) {
|
|
return;
|
|
}
|
|
log("got data");
|
|
listItems = [];
|
|
let items = Object.keys(data[category]);
|
|
let subcat = {};
|
|
let header = "";
|
|
log("got items");
|
|
_.each(items, (item) => {
|
|
// render type headers
|
|
if (data[category][item].type) {
|
|
log("type: " + data[category][item].type);
|
|
if (!subcat[data[category][item].type]) {
|
|
subcat[data[category][item].type] = true;
|
|
header = `<h3>${ucFirst(data[category][item].type)}</h3>`;
|
|
log("set header");
|
|
log(header);
|
|
} else {
|
|
header = "";
|
|
}
|
|
}
|
|
cost = data[category][item].cost
|
|
? data[category][item].cost
|
|
: data[category][item].rarity === 2
|
|
? "**"
|
|
: "";
|
|
button =
|
|
header +
|
|
makeButton(
|
|
ucFirst(data[category][item].name),
|
|
`!gw import ${category}|${item}`,
|
|
styles.button + styles.float.right
|
|
);
|
|
// log("COST: "+cost);
|
|
if (cost !== "") {
|
|
listItems.push(`<span>cost: ${cost}</span>` + button);
|
|
} else {
|
|
listItems.push(button);
|
|
}
|
|
});
|
|
let backbutton = makeButton(
|
|
"Back",
|
|
`!gw compendium`,
|
|
styles.button + styles.float.right
|
|
);
|
|
|
|
contents =
|
|
makeList(
|
|
listItems,
|
|
styles.reset + styles.list + styles.overflow,
|
|
styles.overflow
|
|
) +
|
|
'<hr><p style="font-size: 80%">You can always come back to the compendium by typing `!' +
|
|
state[state_name].config.command +
|
|
" compendium`.</p><hr>" +
|
|
backbutton;
|
|
makeAndSendMenu(
|
|
contents,
|
|
"Compendium </br> " + category + " import",
|
|
""
|
|
);
|
|
}
|
|
// button = makeButton('Backpack', '!' + state[state_name].config.command + ' import backpack', styles.button + styles.fullWidth);
|
|
// makeAndSendMenu(button, 'Import Gear');
|
|
break;
|
|
case "compendium":
|
|
log("compendium");
|
|
data = getData();
|
|
if (!data) {
|
|
return;
|
|
}
|
|
listItems = [];
|
|
let categories = [
|
|
"armour",
|
|
"attacks",
|
|
"gear",
|
|
"mutations",
|
|
"skills",
|
|
"talents",
|
|
];
|
|
_.each(categories, (category) => {
|
|
button = makeButton(
|
|
ucFirst(category),
|
|
`!gw category ${category}`,
|
|
styles.button + styles.float.right
|
|
);
|
|
listItems.push(button);
|
|
});
|
|
contents =
|
|
makeList(
|
|
listItems,
|
|
styles.reset + styles.list + styles.overflow,
|
|
styles.overflow
|
|
) +
|
|
'<hr><p style="font-size: 80%">You can always come back to the compendium by typing `!' +
|
|
state[state_name].config.command +
|
|
" compendium`.</p><hr>";
|
|
makeAndSendMenu(contents, "Compendium - Categories", "");
|
|
break;
|
|
case "effect":
|
|
if (args.length > 0) {
|
|
log(args);
|
|
let setting = args.shift().split("|");
|
|
log(setting);
|
|
let effect = setting.shift();
|
|
let background = setting[0] || null;
|
|
let colour =
|
|
background == "white" || background == "yellow"
|
|
? "black"
|
|
: "white";
|
|
let result = getEffectResult(effect, background);
|
|
let title = result.name;
|
|
let player = getObj("player", msg.playerid);
|
|
log("PLAYER: ");
|
|
log(player);
|
|
const parameters = getParameters(args);
|
|
let whisper = parameters["whisper"]
|
|
? player.get("_displayname")
|
|
: "";
|
|
let content = `<div>${makeResult(
|
|
colour,
|
|
background,
|
|
result.result
|
|
)}</div>`;
|
|
makeAndSendResult(content, title, whisper, msg.playerid);
|
|
}
|
|
break;
|
|
default:
|
|
sendConfigMenu();
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
getRollColour = (roll, row) => {
|
|
let colour = "white",
|
|
RF = 0,
|
|
background = "black";
|
|
if (roll >= row[0]) {
|
|
colour = "black";
|
|
background = "white";
|
|
}
|
|
if (roll >= row[1]) {
|
|
colour = "white";
|
|
RF++;
|
|
background = "blue";
|
|
}
|
|
if (roll >= row[2]) {
|
|
colour = "white";
|
|
RF++;
|
|
background = "green";
|
|
}
|
|
if (row[3] !== null && roll >= row[3]) {
|
|
colour = "black";
|
|
RF++;
|
|
background = "yellow";
|
|
}
|
|
if (row[4] !== null && roll >= row[4]) {
|
|
colour = "white";
|
|
RF++;
|
|
background = "orange";
|
|
}
|
|
if (roll >= row[5]) {
|
|
colour = "white";
|
|
RF++;
|
|
background = "red";
|
|
}
|
|
return { colour, RF, background };
|
|
},
|
|
/**
|
|
* @param {object} msg the msg object from chat window
|
|
* @param {string} rank the rank column to roll against
|
|
* @param {object} parameters the message content parsed as key, value pairs
|
|
* @param {Number} roll1 the ability ACT roll (i.e. number from 1 - 100)
|
|
* @param {Number} roll2 the save ACT roll (i.e. number from 1 - 100)
|
|
*/
|
|
rollAct = (msg, rank, parameters = {}, roll1, roll2) => {
|
|
const self = this;
|
|
log("rollACT: " + rank);
|
|
const data = getData();
|
|
if (!data) {
|
|
return;
|
|
}
|
|
let save,
|
|
rankHTML = "",
|
|
effectType = "effect",
|
|
token = false,
|
|
character = false,
|
|
targetCharacter = false,
|
|
colorResult = {},
|
|
effectName = "",
|
|
category = parameters["category"],
|
|
dmgTotalString = "",
|
|
orig_rank = parseInt(rank);
|
|
rank = parseInt(rank);
|
|
rankHTML = `<span style="${styles.rank}" title="Score: ${rank}">${rank}</span>`;
|
|
sendChat(msg.playerid, "/roll 2d100", function (ops) {
|
|
log("roll1: " + roll1);
|
|
log("roll2: " + roll2);
|
|
if (roll1) {
|
|
log("roll1 hardcoded");
|
|
} else {
|
|
log("roll object");
|
|
log(ops);
|
|
log(JSON.parse(ops[0].content));
|
|
// return;
|
|
roll1 = parseInt(JSON.parse(ops[0].content).rolls[0].results[0].v);
|
|
roll2 = parseInt(JSON.parse(ops[0].content).rolls[0].results[1].v);
|
|
}
|
|
// ops will be an ARRAY of command results.
|
|
log("roll1: " + roll1);
|
|
log("roll2: " + roll2);
|
|
if (parameters["mod"]) {
|
|
// log('calculating rank based on modifier');
|
|
// log(parameters['character']);
|
|
// log(`${parameters['modifier']}_mod`);
|
|
// log(getAttrByName(parameters['character'], 'PS_modifier'));
|
|
|
|
const mod = parseInt(
|
|
getAttrByName(
|
|
parameters["character"],
|
|
`${parameters["mod"]}_modifier`
|
|
)
|
|
);
|
|
rankHTML += ` + <span style="${styles.rank}" title="${parameters["mod"]} modifier">${mod}</span>`;
|
|
rank += mod;
|
|
}
|
|
if (parameters["character"]) {
|
|
character = getObj("character", parameters["character"]);
|
|
log("character: ");
|
|
log(character);
|
|
}
|
|
if (parameters["CS"]) {
|
|
log("calculating rank based on CS: " + parseInt(parameters["CS"]));
|
|
rankHTML += ` + <span style="${styles.rank}" title="Situational CS">${parameters["CS"]}</span>`;
|
|
rank += parseInt(parameters["CS"]);
|
|
log("rank: " + rank);
|
|
}
|
|
if (parameters["tech"]) {
|
|
log("calculating rank based on tech level");
|
|
let character_tech_level;
|
|
if (character) {
|
|
character_tech_level = getAttrByName(
|
|
character.id,
|
|
"character_tech_level"
|
|
);
|
|
let tech_difference = Math.abs(
|
|
parseInt(character_tech_level) - parseInt(parameters["tech"])
|
|
);
|
|
rankHTML += ` - <span style="${styles.rank}" title="Tech Level Difference">${tech_difference}</span>`;
|
|
rank -= tech_difference;
|
|
log("rank: " + rank);
|
|
}
|
|
}
|
|
if (parameters["target_id"]) {
|
|
log("target attributes");
|
|
token = getObj("graphic", parameters["target_id"]);
|
|
log(token);
|
|
if (token) {
|
|
targetCharacter = getObj("character", token.get("represents"));
|
|
log(targetCharacter);
|
|
}
|
|
if (!targetCharacter) {
|
|
log("character not found");
|
|
return;
|
|
}
|
|
if (parameters["target_mod"]) {
|
|
let modVal = getAttrByName(
|
|
targetCharacter.id,
|
|
parameters["target_mod"]
|
|
);
|
|
log("modVal: " + modVal);
|
|
rank += parseInt(modVal);
|
|
// attributes = findObjs({
|
|
// _type: 'attribute',
|
|
// characterid: targetCharacter.id
|
|
// });
|
|
// _.each(attributes, fnction(attribute) {
|
|
// log(attribute);
|
|
// });
|
|
}
|
|
|
|
// minus target's DX mod for melee attacks
|
|
if (parameters["category"] === "attacks") {
|
|
let character_rank = parseInt(
|
|
getAttrByName(character.id, "character_rank")
|
|
);
|
|
log("character");
|
|
log(character);
|
|
log("talents");
|
|
|
|
rank += character_rank;
|
|
rankHTML += ` + <span style="${styles.rank}" title="Character rank">${character_rank}</span>`;
|
|
if (parameters["type"] === "melee") {
|
|
let targetDXmod = getAttrByName(
|
|
targetCharacter.id,
|
|
"DX_modifier"
|
|
);
|
|
log("targetDXmod: " + targetDXmod);
|
|
rankHTML += ` - <span style="${styles.rank}" title="Melee target DX mod">${targetDXmod}</span>`;
|
|
rank -= parseInt(targetDXmod);
|
|
}
|
|
if (parameters["type"] === "throwing") {
|
|
let throwingTalent = filterObjs(
|
|
(a) =>
|
|
a.get("type") === "attribute" &&
|
|
a.get("characterid") === character.id &&
|
|
/^repeating_talents_[^_]*_ref$/.test(a.get("name")) &&
|
|
a.get("current") === "throwing"
|
|
);
|
|
if (throwingTalent.length) {
|
|
rankHTML += ` + <span style="${styles.rank}" title="Throwing talent">${character_rank}</span>`;
|
|
rank += character_rank;
|
|
}
|
|
}
|
|
if (parameters["type"] === "shooting") {
|
|
let shootingTalent = filterObjs(
|
|
(a) =>
|
|
a.get("type") === "attribute" &&
|
|
a.get("characterid") === character.id &&
|
|
/^repeating_talents_[^_]*_ref$/.test(a.get("name")) &&
|
|
a.get("current") === "shooting"
|
|
);
|
|
if (shootingTalent.length) {
|
|
rankHTML += ` + <span style="${styles.rank}" title="Shooting talent">${character_rank}</span>`;
|
|
rank += character_rank;
|
|
}
|
|
}
|
|
if (parameters["type"] === "grappling") {
|
|
let grapplingTalent = filterObjs(
|
|
(a) =>
|
|
a.get("type") === "attribute" &&
|
|
a.get("characterid") === character.id &&
|
|
/^repeating_talents_[^_]*_ref$/.test(a.get("name")) &&
|
|
a.get("current") === "grappling"
|
|
);
|
|
if (grapplingTalent.length) {
|
|
rankHTML += ` + <span style="${styles.rank}" title="Wrestling talent">${character_rank}</span>`;
|
|
rank += character_rank;
|
|
}
|
|
}
|
|
if (parameters["type"] === "martialarts") {
|
|
let martialartsTalent = filterObjs(
|
|
(a) =>
|
|
a.get("type") === "attribute" &&
|
|
a.get("characterid") === character.id &&
|
|
/^repeating_talents_[^_]*_ref$/.test(a.get("name")) &&
|
|
a.get("current") === "martialarts"
|
|
);
|
|
if (martialartsTalent.length) {
|
|
rankHTML += ` + <span style="${styles.rank}" title="Martialarts talent">${character_rank}</span>`;
|
|
rank += character_rank;
|
|
}
|
|
}
|
|
if (parameters["type"] === "brawling") {
|
|
let brawlingTalent = filterObjs(
|
|
(a) =>
|
|
a.get("type") === "attribute" &&
|
|
a.get("characterid") === character.id &&
|
|
/^repeating_talents_[^_]*_ref$/.test(a.get("name")) &&
|
|
a.get("current") === "brawling"
|
|
);
|
|
if (brawlingTalent.length) {
|
|
rankHTML += ` + <span style="${styles.rank}" title="Brawling talent">${character_rank}</span>`;
|
|
rank += character_rank;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
rankHTML += `: <span style="${styles.rank}" title="Final Rank">${rank}</span>`;
|
|
let row = getActRow(rank);
|
|
log("row: " + row);
|
|
log(typeof row);
|
|
log(Array.isArray(row));
|
|
if (!Array.isArray(row)) {
|
|
let player = getObj("player", msg.playerid);
|
|
makeAndSendResult(
|
|
"ACT roll failed!",
|
|
"Error:",
|
|
player.get("_displayname"),
|
|
msg.playerid
|
|
);
|
|
return;
|
|
}
|
|
|
|
colorResult = getRollColour(roll1, row);
|
|
log("colorResult: " + colorResult);
|
|
// log('background: ' + background);
|
|
// log('RC: ' + background);
|
|
// log('RF: ' + RF);
|
|
let title = `ACT Roll'`;
|
|
if (parameters["title"]) {
|
|
if (parameters["category"] && parameters["title"] === "ref") {
|
|
if (
|
|
data[parameters["category"]] &&
|
|
data[parameters["category"]][parameters["id"]]
|
|
) {
|
|
title = data[parameters["category"]][parameters["id"]].name;
|
|
}
|
|
} else {
|
|
title = parameters["title"];
|
|
}
|
|
title += ` (${rank})`;
|
|
}
|
|
let content = "";
|
|
content += `<div style="${styles.row}; font-weight: bold;">Roll: <span>${roll1}</span><div style="font-weight: bold; margin-bottom: 5px;">Rank: ${rankHTML}</div>`;
|
|
|
|
if (parameters["dmg"]) {
|
|
log(
|
|
"damage parameter: " +
|
|
parameters["dmg"] +
|
|
" - " +
|
|
parameters["dmg_type"]
|
|
);
|
|
let baseDmg = 0,
|
|
DR = 0,
|
|
dmgAfterDRsoak = 0;
|
|
if (parameters["dmg"] === "mutation" || parameters["dmg"] === "M") {
|
|
baseDmg = parseInt(orig_rank) / 2;
|
|
} else if (parameters["dmg"].includes("/")) {
|
|
//- cater for damage ratings for different sizes
|
|
let dmg = parameters["dmg"].split("/");
|
|
log("dmg: ");
|
|
log(dmg);
|
|
let size =
|
|
getAttrByName(targetCharacter.id, "character_size") || 3;
|
|
log("size: " + size);
|
|
baseDmg =
|
|
parseInt(size) < 4 ? parseInt(dmg[0]) : parseInt(dmg[1]);
|
|
log("baseDmg after size: " + baseDmg);
|
|
if (_.isNaN(baseDmg)) baseDmg = 0;
|
|
} else {
|
|
baseDmg = parseInt(parameters["dmg"]);
|
|
if (_.isNaN(baseDmg)) baseDmg = 0;
|
|
}
|
|
|
|
if (parameters["category"] === "attacks") {
|
|
if (parameters["skilldmg"]) {
|
|
log("baseDmg orig_rank: " + orig_rank);
|
|
log("baseDmg before skilldmg: " + baseDmg);
|
|
baseDmg += parseInt(orig_rank);
|
|
log("baseDmg after skilldmg: " + baseDmg);
|
|
}
|
|
}
|
|
|
|
log("baseDMG: " + baseDmg);
|
|
log("RF: " + colorResult.RF);
|
|
DR = getAttrByName(targetCharacter.id, "DR_physical") || 0;
|
|
log("DR: " + DR);
|
|
log("DR in: " + parseInt(DR));
|
|
|
|
let dmgTotal = parseInt(colorResult.RF) * parseInt(baseDmg);
|
|
if (_.isNaN(dmgTotal)) dmgTotal = 0;
|
|
dmgAfterDRsoak = dmgTotal;
|
|
dmgAfterDRsoak += parseInt(DR);
|
|
dmgAfterDRsoak = dmgAfterDRsoak < 1 ? 0 : dmgAfterDRsoak;
|
|
log("dmgTotal: " + dmgTotal);
|
|
log("dmgAfterDRsoak: " + dmgAfterDRsoak);
|
|
dmgTotalString = `Physical Damage: <span title="Base: ${baseDmg}, Dmg: ${dmgTotal} DR: ${DR}">${dmgAfterDRsoak}</span>`;
|
|
}
|
|
|
|
content += makeResult(
|
|
colorResult.colour,
|
|
colorResult.background,
|
|
colorResult.background,
|
|
"RF",
|
|
colorResult.RF,
|
|
dmgTotalString
|
|
);
|
|
|
|
const send = (msg, parameters, title, content) => {
|
|
if (parameters["character"]) {
|
|
makeAndSendResult(
|
|
content,
|
|
title,
|
|
"",
|
|
parameters["character"],
|
|
"character"
|
|
);
|
|
} else {
|
|
makeAndSendResult(content, title, "", msg.playerid);
|
|
}
|
|
};
|
|
|
|
// show ability description
|
|
if (parameters["describe"] === "on") {
|
|
const description = _.defaults(
|
|
data[parameters["category"]][parameters["id"]],
|
|
{ description: false }
|
|
).description;
|
|
if (description) {
|
|
content += `<div style="${styles.description};">${description}</div>`;
|
|
}
|
|
}
|
|
|
|
if (parameters["save"]) {
|
|
save = parameters["save"];
|
|
}
|
|
let effectsContent = "";
|
|
// override save type from damage type
|
|
if (parameters["dmg_type"]) {
|
|
log(
|
|
"Damage Type: " +
|
|
data["damage_types"][parameters["dmg_type"]].name
|
|
);
|
|
if (data["damage_types"][parameters["dmg_type"]]) {
|
|
if (data["damage_types"][parameters["dmg_type"]].save) {
|
|
save = data["damage_types"][parameters["dmg_type"]].save;
|
|
}
|
|
if (data["damage_types"][parameters["dmg_type"]].effect_crit) {
|
|
parameters["effect_crit"] =
|
|
data["damage_types"][parameters["dmg_type"]].effect_crit;
|
|
}
|
|
if (data["damage_types"][parameters["dmg_type"]].effect) {
|
|
parameters["effect"] =
|
|
data["damage_types"][parameters["dmg_type"]].effect;
|
|
}
|
|
if (data["damage_types"][parameters["dmg_type"]].description) {
|
|
content += `<div style="${
|
|
styles.description
|
|
};"><b style="${row}">Damage Type: ${
|
|
data["damage_types"][parameters["dmg_type"]].name
|
|
}</b><p>${
|
|
data["damage_types"][parameters["dmg_type"]].description
|
|
}</p></div>`;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (parameters["effect"]) {
|
|
effectName = parameters["effect"];
|
|
log("effect name: " + effectName);
|
|
if (
|
|
!empty(data.effects) &&
|
|
!empty(data.effects[parameters["effect"]])
|
|
) {
|
|
effectDisplayName = data.effects[parameters["effect"]].name;
|
|
log("effect name: " + effectDisplayName);
|
|
// let result = getEffectResult(parameters['effect'], colorResult.background);
|
|
content += `<div style="font-weight: bold">Effect: </div><div>${effectDisplayName}</div>`;
|
|
} else if (
|
|
!empty(data.damage_types) &&
|
|
data.damage_types[parameters["effect"]]
|
|
) {
|
|
log("damage_type based on effect: " + effectName);
|
|
log(data.damage_types[parameters["effect"]]);
|
|
|
|
effectsContent += `<div style="${
|
|
styles.effect
|
|
}">Effect: <span style="font-weight: normal" title="${
|
|
data.damage_types[parameters["effect"]].description
|
|
}">${data.damage_types[parameters["effect"]].name}</span></div>`;
|
|
save = data.damage_types[parameters["effect"]].save;
|
|
}
|
|
}
|
|
|
|
if (parameters["effect_crit"]) {
|
|
effectName = "(Critical)";
|
|
log("effect_crit: " + parameters["effect_crit"]);
|
|
log("background: " + colorResult.background);
|
|
log(
|
|
!empty(data.effects) && data.effects[parameters["effect_crit"]]
|
|
);
|
|
if (colorResult.background === "red") {
|
|
log("RED show save");
|
|
if (data.effects[parameters["effect_crit"]]) {
|
|
log("Crit effect according to Ability setting");
|
|
effectType = "effect_crit";
|
|
effectsContent += `<div style="${
|
|
styles.effect
|
|
}">Critical Effect: <span style="font-weight: normal">${
|
|
data.effects[parameters["effect_crit"]].name
|
|
}</span></div>`;
|
|
}
|
|
// else if (data.damage_types[parameters["effect_crit"]]) {
|
|
// log("Crit effect according to Damage Type");
|
|
// log(data.damage_types);
|
|
// log(parameters["effect_crit"]);
|
|
// log(data.damage_types[parameters["effect_crit"]]);
|
|
// content += `<div style="${
|
|
// styles.effect
|
|
// }">Critical Effect: <span style="font-weight: normal" title="${
|
|
// data.damage_types[parameters["effect_crit"]].description
|
|
// }">${
|
|
// data.damage_types[parameters["effect_crit"]].name
|
|
// }</span></div>`;
|
|
// save = data.damage_types[parameters["effect_crit"]].save;
|
|
// content += renderSaveRoll(
|
|
// save,
|
|
// targetCharacter,
|
|
// roll2,
|
|
// parameters,
|
|
// effectType,
|
|
// colorResult,
|
|
// effectName
|
|
// );
|
|
// }
|
|
}
|
|
}
|
|
if (!empty(save)) {
|
|
content += renderSaveRoll(
|
|
save,
|
|
targetCharacter,
|
|
roll2,
|
|
parameters,
|
|
effectType,
|
|
colorResult,
|
|
effectsContent
|
|
);
|
|
} else {
|
|
log('Will not render Save as the "save" parameter was not set.');
|
|
}
|
|
send(msg, parameters, title, content);
|
|
});
|
|
},
|
|
renderSaveRoll = (
|
|
save,
|
|
targetCharacter,
|
|
roll2,
|
|
parameters,
|
|
effectType,
|
|
colorResult,
|
|
effectsContent
|
|
) => {
|
|
const data = getData();
|
|
if (!data) {
|
|
return;
|
|
}
|
|
log("START renderSaveRoll");
|
|
let saveScore = getAttrByName(targetCharacter.id, `${save}`);
|
|
log("saveScore: " + saveScore);
|
|
let effectsActRow = getActRow(saveScore);
|
|
log("effectsActRow");
|
|
log(effectsActRow);
|
|
let effectsColorResult = getRollColour(roll2, effectsActRow);
|
|
let effectsResult = { result: effectsColorResult.background };
|
|
let result = "";
|
|
if (!empty(data.effects) && data.effects[parameters[effectType]]) {
|
|
effectsResult = getEffectResult(
|
|
parameters[effectType],
|
|
effectsColorResult.background
|
|
);
|
|
}
|
|
result = effectsResult.result;
|
|
let success =
|
|
parseInt(effectsColorResult.RF) >= parseInt(colorResult.RF);
|
|
let successMessage = success
|
|
? `<span style="${styles.success}">success</span>`
|
|
: `<span style="${styles.fail}">fail</span>`;
|
|
|
|
log("END renderSaveRoll");
|
|
let content = `<div style="${styles.border} font-weight: bold; background-color: ${effectsColorResult.background}; color: ${effectsColorResult.colour};">Save vs. ${save}: <span style="font-weight: normal; font-variant:small-caps;">${result} ${successMessage}</span></div>`;
|
|
if (!success) {
|
|
content += effectsContent;
|
|
}
|
|
return content;
|
|
},
|
|
getActRow = (rank) => {
|
|
log("getActRow");
|
|
rank = parseInt(rank);
|
|
log(typeof rank + ": " + rank);
|
|
const cols = {
|
|
A: [18, 74, 99, null, null, 100],
|
|
B: [17, 73, 98, 99, null, 100],
|
|
C: [16, 72, 97, 99, null, 100],
|
|
1: [15, 71, 96, 98, 99, 100],
|
|
2: [14, 69, 94, 97, 99, 100],
|
|
3: [13, 68, 93, 97, 97, 100],
|
|
4: [12, 66, 91, 96, 97, 100],
|
|
5: [11, 62, 87, 93, 97, 99],
|
|
6: [10, 60, 85, 92, 96, 99],
|
|
7: [9, 58, 83, 91, 96, 99],
|
|
8: [8, 56, 80, 89, 95, 99],
|
|
9: [7, 54, 78, 88, 93, 99],
|
|
10: [6, 52, 75, 86, 92, 99],
|
|
11: [5, 49, 71, 83, 91, 98],
|
|
12: [5, 47, 68, 81, 90, 98],
|
|
13: [4, 44, 65, 79, 89, 98],
|
|
14: [4, 42, 62, 77, 88, 98],
|
|
15: [4, 40, 58, 75, 87, 98],
|
|
16: [3, 37, 53, 72, 86, 97],
|
|
17: [3, 35, 49, 70, 85, 97],
|
|
18: [3, 33, 45, 68, 84, 97],
|
|
19: [3, 30, 41, 66, 83, 97],
|
|
20: [2, 26, 36, 63, 82, 96],
|
|
21: [2, 23, 32, 61, 81, 96],
|
|
X: [2, 20, 27, 59, 80, 96],
|
|
Y: [2, 17, 22, 56, 78, 95],
|
|
Z: [2, 13, 16, 51, 76, 94],
|
|
};
|
|
if (rank <= -26) return cols["A"];
|
|
if (rank <= -6) return cols["B"];
|
|
if (rank <= 0) return cols["C"];
|
|
if (rank === 1) return cols["1"];
|
|
if (rank === 2) return cols["2"];
|
|
if (rank === 3) return cols["3"];
|
|
if (rank === 4) return cols["4"];
|
|
if (rank === 5) return cols["5"];
|
|
if (rank === 6) return cols["6"];
|
|
if (rank === 7) return cols["7"];
|
|
if (rank === 8) return cols["8"];
|
|
if (rank === 9) return cols["9"];
|
|
if (rank === 10) return cols["10"];
|
|
if (rank === 11) return cols["11"];
|
|
if (rank === 12) return cols["12"];
|
|
if (rank === 13) return cols["13"];
|
|
if (rank === 14) return cols["14"];
|
|
if (rank === 15) return cols["15"];
|
|
if (rank === 16) return cols["16"];
|
|
if (rank === 17) return cols["17"];
|
|
if (rank === 18) return cols["18"];
|
|
if (rank === 19) return cols["19"];
|
|
if (rank === 20) return cols["20"];
|
|
if (rank === 21) return cols["21"];
|
|
if (rank <= 120) return cols["X"];
|
|
if (rank <= 600) return cols["Y"];
|
|
if (rank > 600) return cols["Z"];
|
|
},
|
|
getEffectResult = (effect, colour) => {
|
|
let data = getData().effects;
|
|
const index =
|
|
colour === "red"
|
|
? 0
|
|
: colour === "orange"
|
|
? 1
|
|
: colour === "yellow"
|
|
? 2
|
|
: colour === "green"
|
|
? 3
|
|
: colour === "blue"
|
|
? 4
|
|
: colour === "white"
|
|
? 5
|
|
: 6;
|
|
log("index: ", index);
|
|
log("effectname: ", effect);
|
|
log(data[effect]);
|
|
log(data[effect].name);
|
|
log(data[effect].data[index]);
|
|
return { name: data[effect].name, result: data[effect].data[index] };
|
|
},
|
|
importCompendiumItemToCharacter = function (msg, ids, category) {
|
|
log("import");
|
|
const data = getData();
|
|
let player = getObj("player", msg.playerid);
|
|
log("player:");
|
|
log(player);
|
|
log("player displayname:");
|
|
log(player.get("_displayname"));
|
|
if (msg.selected === undefined) {
|
|
makeAndSendResult(
|
|
"Please first select a token representing the character to which you wish to import!",
|
|
"Error:",
|
|
player.get("_displayname"),
|
|
msg.playerid
|
|
);
|
|
return;
|
|
}
|
|
_.each(msg.selected, function (obj) {
|
|
let token, character, attribute, sections, exists;
|
|
token = getObj("graphic", obj._id);
|
|
if (token) {
|
|
character = getObj("character", token.get("represents"));
|
|
}
|
|
if (character) {
|
|
attribute = findObjs({
|
|
_type: "attribute",
|
|
characterid: character.id,
|
|
});
|
|
} else {
|
|
log("character not found");
|
|
return;
|
|
}
|
|
if (!attribute) {
|
|
makeAndSendResult(
|
|
"This character sheet is blank.",
|
|
"Error: ",
|
|
player.get("_displayname"),
|
|
character.id,
|
|
"character"
|
|
);
|
|
return;
|
|
}
|
|
_.each(ids, (itemId) => {
|
|
let rowId = generateRowID();
|
|
let objTemplate = {
|
|
max: "",
|
|
_id: rowId,
|
|
_characterid: character.id,
|
|
};
|
|
if (data[category] === undefined) {
|
|
makeAndSendResult(
|
|
"The selected category could not be found.",
|
|
"Error: ",
|
|
player.get("_displayname"),
|
|
character.id,
|
|
"character"
|
|
);
|
|
return;
|
|
}
|
|
// let items = data[category].filter(item => item.id === itemId);
|
|
if (!_.has(data[category], itemId)) {
|
|
makeAndSendResult(
|
|
"The selected itemID could not be found.",
|
|
"Error: ",
|
|
player.get("_displayname"),
|
|
character.id,
|
|
"character"
|
|
);
|
|
return;
|
|
}
|
|
let itemAttributes = data[category][itemId];
|
|
log("itemAttributes: ");
|
|
log(itemAttributes);
|
|
_.each(itemAttributes, (attributeValue, attributeName) => {
|
|
if (attributeName !== "id") {
|
|
let obj = Object.assign(objTemplate, {
|
|
name: `repeating_${category}_${rowId}_${attributeName}`,
|
|
current: attributeValue,
|
|
});
|
|
log(obj);
|
|
createObj("attribute", obj);
|
|
}
|
|
});
|
|
// add in the compendium reference
|
|
let obj = Object.assign(objTemplate, {
|
|
name: `repeating_${category}_${rowId}_ref`,
|
|
current: itemId,
|
|
});
|
|
createObj("attribute", obj);
|
|
if (category === "armour" || category === "gear") {
|
|
let obj = Object.assign(objTemplate, {
|
|
name: `repeating_${category}_${rowId}_equipped`,
|
|
current: 0,
|
|
});
|
|
createObj("attribute", obj);
|
|
}
|
|
if (category === "attacks" || category === "ammo") {
|
|
if (category === "attacks") {
|
|
//@deprecated: Attack ranks are distinct from Character ranks
|
|
// log("import attack");
|
|
// let character_rank = parseInt(
|
|
// getAttrByName(character.id, "character_rank")
|
|
// );
|
|
// log("character rank:" + character_rank);
|
|
// if (_.isNaN(character_rank)) {
|
|
// log(
|
|
// "character rank was not found and thus the attack rank could not be accurately determined and will default to 1"
|
|
// );
|
|
// character_rank = 1;
|
|
// }
|
|
// let obj = Object.assign(objTemplate, {
|
|
// name: `repeating_${category}_${rowId}_rank`,
|
|
// current: character_rank,
|
|
// });
|
|
// createObj("attribute", obj);
|
|
}
|
|
// also add it to gear
|
|
_.each(itemAttributes, (attributeValue, attributeName) => {
|
|
if (attributeName !== "id") {
|
|
let obj = Object.assign(objTemplate, {
|
|
name: `repeating_gear_${rowId}_${attributeName}`,
|
|
current: attributeValue,
|
|
});
|
|
log(obj);
|
|
createObj("attribute", obj);
|
|
}
|
|
});
|
|
}
|
|
if (category === "mutations") {
|
|
sendChat(msg.playerid, "/roll 2d6", function (ops) {
|
|
let rollresult = ops[0];
|
|
let result = JSON.parse(ops[0].content);
|
|
let rolltotal = parseInt(result.total);
|
|
if (itemAttributes.modifier !== undefined) {
|
|
let mod =
|
|
itemAttributes["type"] === "mental"
|
|
? "MS_modifier"
|
|
: "PS_modifier";
|
|
let ability = attribute.filter((x) => x.get("name") === mod);
|
|
if (ability.length) {
|
|
let obj = Object.assign(objTemplate, {
|
|
name: `repeating_${category}_${rowId}_rank`,
|
|
current: parseInt(ability[0].get("current")) + rolltotal,
|
|
});
|
|
createObj("attribute", obj);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
});
|
|
},
|
|
handleBarValueChange = (obj, prev) => {
|
|
pre_log("handleBarValueChange: ");
|
|
log(obj);
|
|
log(prev);
|
|
|
|
let bar = "bar" + state[state_name].config.bar;
|
|
|
|
if (
|
|
!obj ||
|
|
!prev ||
|
|
!obj.get("represents") ||
|
|
obj.get(bar + "_value") === prev[bar + "_value"]
|
|
) {
|
|
return;
|
|
}
|
|
|
|
// let attributes = {};
|
|
let character = {},
|
|
characterID = obj.get("represents");
|
|
character = getObj("character", characterID);
|
|
|
|
// obj.set(attributes);
|
|
notifyObservers("tokenChange", obj, prev);
|
|
},
|
|
getColor = (value) => {
|
|
return hslToHex((1 - value) * 120, 75, 50);
|
|
},
|
|
hslToHex = (h, s, l) => {
|
|
h /= 360;
|
|
s /= 100;
|
|
l /= 100;
|
|
let r, g, b;
|
|
if (s === 0) {
|
|
r = g = b = l; // achromatic
|
|
} else {
|
|
const hue2rgb = (p, q, t) => {
|
|
if (t < 0) t += 1;
|
|
if (t > 1) t -= 1;
|
|
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
if (t < 1 / 2) return q;
|
|
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
return p;
|
|
};
|
|
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
const p = 2 * l - q;
|
|
r = hue2rgb(p, q, h + 1 / 3);
|
|
g = hue2rgb(p, q, h);
|
|
b = hue2rgb(p, q, h - 1 / 3);
|
|
}
|
|
const toHex = (x) => {
|
|
const hex = Math.round(x * 255).toString(16);
|
|
return hex.length === 1 ? "0" + hex : hex;
|
|
};
|
|
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
},
|
|
ucFirst = (string) => {
|
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
},
|
|
sendConfigMenu = (first, message) => {
|
|
let commandButton = makeButton(
|
|
"!" + state[state_name].config.command,
|
|
"!" +
|
|
state[state_name].config.command +
|
|
" config command|?{Command (without !)}",
|
|
styles.button + styles.float.right
|
|
),
|
|
barButton = makeButton(
|
|
"bar " + state[state_name].config.bar,
|
|
"!" +
|
|
state[state_name].config.command +
|
|
" config bar|?{Bar|Bar 1 (green),1|Bar 2 (blue),2|Bar 3 (red),3}",
|
|
styles.button + styles.float.right
|
|
),
|
|
listItems = [
|
|
'<span style="' +
|
|
styles.float.left +
|
|
'">Command:</span> ' +
|
|
commandButton,
|
|
'<span style="' +
|
|
styles.float.left +
|
|
'">HP Bar:</span> ' +
|
|
barButton,
|
|
];
|
|
|
|
let resetButton = makeButton(
|
|
"Reset",
|
|
"!" + state[state_name].config.command + " reset",
|
|
styles.button + styles.fullWidth
|
|
);
|
|
|
|
let title_text = first
|
|
? script_name + " First Time Setup"
|
|
: script_name + " Config";
|
|
message = message ? "<p>" + message + "</p>" : "";
|
|
let contents =
|
|
message +
|
|
makeList(
|
|
listItems,
|
|
styles.reset + styles.list + styles.overflow,
|
|
styles.overflow
|
|
) +
|
|
'<hr><p style="font-size: 80%">You can always come back to this config by typing `!' +
|
|
state[state_name].config.command +
|
|
" config`.</p><hr>" +
|
|
resetButton;
|
|
makeAndSendMenu(contents, title_text, "gm");
|
|
},
|
|
makeAndSendMenu = (contents, title, whisper) => {
|
|
title = title && title != "" && makeTitle(title);
|
|
whisper = whisper && whisper !== "" && "/w " + whisper + " ";
|
|
sendChat(
|
|
script_name,
|
|
whisper +
|
|
'<div style="'+styles.menuborder+'"><div style="' +
|
|
styles.menu +
|
|
styles.overflow +
|
|
'">' +
|
|
title +
|
|
contents +
|
|
"</div></div>",
|
|
null,
|
|
{
|
|
noarchive: true,
|
|
}
|
|
);
|
|
},
|
|
makeAndSendResult = (contents, title, whisper, id, type = "player") => {
|
|
log("makeAndSendResult");
|
|
log(id);
|
|
log(type);
|
|
title = title && title != "" && makeTitle(title);
|
|
whisper = whisper && whisper !== "" ? "/w " + whisper + " " : "";
|
|
sendChat(
|
|
`${type}|${id}`,
|
|
whisper +
|
|
'<div style="'+styles.menuborder+'"><div style="' +
|
|
styles.menu +
|
|
styles.overflow +
|
|
'">' +
|
|
title +
|
|
contents +
|
|
"</div></div>",
|
|
null,
|
|
{
|
|
noarchive: true,
|
|
}
|
|
);
|
|
},
|
|
makeTitle = (title) => {
|
|
return (
|
|
'<h3 style="margin-bottom: 10px; color: #ae6a00"; font-family: "Contrail One";>' +
|
|
title +
|
|
"</h3>"
|
|
);
|
|
},
|
|
makeButton = (title, href, style) => {
|
|
return '<a style="' + style + '" href="' + href + '">' + title + "</a>";
|
|
},
|
|
makeList = (items, listStyle, itemStyle) => {
|
|
let list = '<ul style="' + listStyle + '">';
|
|
items.forEach((item) => {
|
|
list += '<li style="' + itemStyle + '">' + item + "</li>";
|
|
});
|
|
list += "</ul>";
|
|
return list;
|
|
},
|
|
makeResult = (colour, background, text, label, value, category = "") => {
|
|
return `<div style="color:${colour}; background-color:${background}; border: 1px solid #aaa; border-radius: 5px; padding: 1rem; margin-bottom: 10px;"><div>${category}</div><div style="font-variant:small-caps">${text} (${label}: ${value})</div></div>`;
|
|
},
|
|
pre_log = (message) => {
|
|
log(
|
|
"---------------------------------------------------------------------------------------------"
|
|
);
|
|
log(message);
|
|
log(
|
|
"---------------------------------------------------------------------------------------------"
|
|
);
|
|
},
|
|
checkInstall = () => {
|
|
if (!_.has(state, state_name)) {
|
|
state[state_name] = state[state_name] || {};
|
|
}
|
|
setDefaults();
|
|
|
|
log(
|
|
script_name + " Ready! Command: !" + state[state_name].config.command
|
|
);
|
|
if (state[state_name].config.debug) {
|
|
makeAndSendMenu(script_name + " Ready! Debug On.", "", "gm");
|
|
}
|
|
},
|
|
observeTokenChange = function (handler) {
|
|
pre_log("token change: ");
|
|
log(handler);
|
|
if (handler && _.isFunction(handler)) {
|
|
observers.tokenChange.push(handler);
|
|
}
|
|
},
|
|
notifyObservers = function (event, obj, prev) {
|
|
_.each(observers[event], function (handler) {
|
|
handler(obj, prev);
|
|
});
|
|
},
|
|
registerEventHandlers = () => {
|
|
on("chat:message", handleInput);
|
|
on("change:graphic", handleBarValueChange);
|
|
if ("undefined" !== typeof TokenMod && TokenMod.ObserveTokenChange) {
|
|
TokenMod.ObserveTokenChange(handleBarValueChange);
|
|
}
|
|
},
|
|
setDefaults = (reset) => {
|
|
const defaults = {
|
|
config: {
|
|
command: "gw",
|
|
bar: 1,
|
|
firsttime: reset ? false : true,
|
|
},
|
|
};
|
|
|
|
if (!state[state_name].config) {
|
|
state[state_name].config = defaults.config;
|
|
} else {
|
|
if (!state[state_name].config.hasOwnProperty("command")) {
|
|
state[state_name].config.command = defaults.config.command;
|
|
}
|
|
if (!state[state_name].config.hasOwnProperty("bar")) {
|
|
state[state_name].config.bar = defaults.config.bar;
|
|
}
|
|
}
|
|
|
|
if (state[state_name].config.firsttime) {
|
|
sendConfigMenu(true);
|
|
state[state_name].config.firsttime = false;
|
|
}
|
|
},
|
|
getData = () => {
|
|
if (typeof compendium === "undefined") {
|
|
log("The compendium is not installed");
|
|
return false;
|
|
}
|
|
return compendium;
|
|
// return {}
|
|
};
|
|
|
|
return {
|
|
CheckInstall: checkInstall,
|
|
ObserveTokenChange: observeTokenChange,
|
|
RegisterEventHandlers: registerEventHandlers,
|
|
GetData: getData,
|
|
};
|
|
})();
|
|
|
|
on("ready", function () {
|
|
"use strict";
|
|
|
|
GW3Companion.CheckInstall();
|
|
GW3Companion.RegisterEventHandlers();
|
|
});
|