Error in question: /home/symbly/www/d20-api-server/node_modules/firebase/lib/firebase-node.js:1
orts, require, module, __filename, __dirname) { function f(a){throw a;}var j=v
^
Error: Firebase.child failed: First argument must be a non-empty string and can't contain ".", "#", "$", "[", or "]".
at Error (<anonymous>)
at Ha (/home/symbly/www/d20-api-server/node_modules/firebase/lib/firebase-node.js:12:204)
at G.W.H (/home/symbly/www/d20-api-server/node_modules/firebase/lib/firebase-node.js:126:213)
at TrackedObj._doSave ( How to reproduce: Create a fresh campaign and select the D&D 4e sheet. Copy script from bottom of post into a script tab and save. Create a new character and open to the sheet tab. Goto the powers tab and expand the settings for the top left power. Add to the end of the "Power Macro" box "!use @{character_id} 1" without quotes. Select the "Encounter" radio button. Make sure there is no attribute called power-1-used if there is one delete it. Roll the power. Untick the used box. Roll the power again. To repeatedly reproduce start again at 7. Amount of time between step 8 and 10 appears to make no difference. Simply saving the script clears the error and prevents it from happening again until you start at set 7. Script: var AlexL = AlexL || {}; /* Name Space off the script */
AlexL.utility = {};
//Utilities
(function(self) {
"use strict";
self.strictInt = function(value) {
var i = Number(value);
if (!isNaN(i)) {
return i;
}
return 0;
};
self.parseChat = function(msg) {
if(msg.type === "api") {
var parseRes = parseString(msg.content),Command = "", Who = "", i = 0, arg = [], opt = {}, selected = false;
if(parseRes != undefined && parseRes.length === 2) {
opt = parseRes[1];
arg = parseRes[0];
if(arg.length > 1) {
Command = arg[0].toLowerCase();
arg.splice(0, 1); //Remove the command.
Who = msg.who.split(" ")[0];
// if(msg.selected != undefined && msg.selected.length > 0) {
// selected = msg.selected[0]._id;
// }
selected = arg[0];
arg.splice(0, 1);
if(Command === "!use") { // power: !ca-power [selected] [name] [key]
if(selected !== false) {
if(arg.length == 1) {
var cha = getObj("character", selected);
if(typeof cha !== 'object' || cha === null) {
log("Error: character is not an Object.");
return false;
}
if(!("get" in cha)) {
log("Error: character is not a Roll20 Object. Missing get.");
return false;
}
var i = AlexL.utility.strictInt(arg[0]);
if(i < 1 || i > 100) {
log("Error: Power id not valid.");
return false;
}
//Find out what sort of power it is.
var usageName = "power-" + i + "-useage";
var usage = findObjs({
_type: "attribute",
name: usageName
})[0];
var use = "";
if(typeof usage !== 'object' || usage === null || !("get" in usage)) {
use = "At-Will";
} else {
use = usage.get("current");
}
//Ignore at-will powers they don't get used.
if(use !== "At-Will" && (use === "Encounter" || use === "Daily")) {
//Find the checkbox and check it
var checkboxName = "power-" + i + "-used";
var checkbox = findObjs({
_type: "attribute",
name: checkboxName
})[0];
log(checkbox);
var u = "Unused";
if(typeof checkbox !== 'object' || checkbox === null || !("get" in checkbox)) {
log("used doesn't exist lets make it");
checkbox = createObj("attribute", {
name: checkboxName,
current: 1,
characterid: selected
});
} else {
log("found used");
if(checkbox.get("current") == 1) u = "Used";
checkbox.set("current", 1);
}
//sendChat("player|" + msg.playerid, u);
sendChat(msg.who, u);
}
}
}
}
}
}
}
}
self.replaceAll = function(find, replace, str) {
return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
function parseString(str) {
var re = /(?:")([^"]+)(?:")|([^\s"]+)(?=\s+|$)/g, res=[], arr=null, arg = [], opt = {}, i = 0, optName = "";
while (arr = re.exec(str)) { res.push(arr[1] ? arr[1] : arr[0]); }
for(i = 0; i < res.length; i++) {
if(res[i].indexOf("--") !== 0) { // arg
arg.push(res[i]);
} else {
optName = res[i].replace("--", "").toLowerCase();
if(!(optName in opt)) {
opt[optName] = [];
}
if((i + 1) < res.length) {
opt[optName].push(res[++i]);
}
}
}
return [arg, opt];
}
})(AlexL.utility);
on("chat:message", function(msg) {
if(msg.type === "api") {
AlexL.utility.parseChat(msg);
}
});