// VERSION INFO
var PowerCards_Author = "Sky";
var PowerCards_Version = "3.6.1";
var PowerCards_LastUpdated = 1520421801;
// FUNCTION DECLARATIONS
var PowerCard = PowerCard || {};
var buildInline = buildInline || {};
var processRoll = processRoll || {};
var doInlineFormatting = doInlineFormatting || {};
var getAttrRefValues = getAttrRefValues || {};
var getBrightness = getBrightness || {};
var getCurrentTime = getCurrentTime || {};
var getHex2Dec = getHex2Dec || {};
var getOnlinePlayerNames = getOnlinePlayerNames || {};
var getPowerCardFormats = getPowerCardFormats || {};
var getPowerCardStatusList = getPowerCardStatusList || {};
var getTargetInfo = getTargetInfo || {};
var statusSymbol = statusSymbol || {};
var safeSendChat = safeSendChat || {};
var sortByKey = sortByKey || {};
// INLINE ROLL COLORS
var INLINE_ROLL_DEFAULT = " background-color: #FFFEA2; border-color: #87850A; color: #000000;";
var INLINE_ROLL_CRIT_LOW = " background-color: #FFAAAA; border-color: #660000; color: #660000;";
var INLINE_ROLL_CRIT_HIGH = " background-color: #88CC88; border-color: #004400; color: #004400;";
var INLINE_ROLL_CRIT_BOTH = " background-color: #8FA4D4; border-color: #061539; color: #061539;";
var INLINE_ROLL_STYLE = "text-align: center; font-size: 100%; display: inline-block; font-weight: bold; height: 1em; min-width: 1.75em; margin-top: -1px; margin-bottom: 1px; padding: 0px 2px; border: 1px solid; border-radius: 3px;";
// API COMMAND HANDLER
on("chat:message", function(msg) {
if (msg.type !== "api") return;
if (msg.content.split(" ", 1)[0] === "!power") {
var player_obj = getObj("player", msg.playerid);
msg.who = msg.who.replace(" (GM)", "");
msg.content = msg.content.replace(/
\n/g, ' ').replace(/({{(.*?)}})/g, " $2 ");
PowerCard.Process(msg, player_obj);
}
if (msg.content.split(" ", 1)[0] === "!power_version") {
sendChat("", "/w " + msg.who + " You are using version " + PowerCards_Version + " of PowerCards, authored by " + PowerCards_Author + ", which was last updated on: " + PowerCards_LastUpdated + ".");
}
});
// LOAD POWERCARD FORMATS
on("ready", function() {
getPowerCardFormats();
log("-=> PowerCards v" +PowerCards_Version + " <=- [" + (new Date(PowerCards_LastUpdated * 1000)) + "]");
//log (Date.now().toString().substr(0, 10));
});
on("change:handout", function() {
getPowerCardFormats();
getPowerCardStatusList();
});
// POWERCARD
PowerCard.Process = function(msg, player_obj) {
// USER CONFIGURATION
var ALLOW_URLS = false; // Allows players to include full urls in powercards
var ALLOW_HIDDEN_URLS = false; // Allows players to hide urls as a link instead
var CUSTOM_EMOTES = true; // Set to true to use custom emotes instead of Roll20 emotes
var SHOW_AVATAR = true; // Set to false to hide character sheet avatar in custom emotes
var USE_DEFAULT_FORMAT = false; // Set to true if you want powercards to default formatting
var USE_PLAYER_COLOR = false; // Set to true to override all color formatting
// REPLACE INLINE ROLLS WITH EXPRESSIONS
if (msg.inlinerolls !== undefined) {
var Count = 0;
while (Count < msg.inlinerolls.length) {
msg.content = msg.content.replace("$[[" + Count + "]]", ("[[" + msg.inlinerolls[Count].expression + " ]]").replace(/\[\[\[/g, "[[ ["));
Count++;
}
}
// DEFINE VARIABLES
var n = (player_obj) ? msg.content.replace("%%who%%", player_obj.get("displayname")).split(/\s+--/) : msg.content.split(/\s+--/);
var PowerCard = {};
var Tag = "";
var Content = "";
var TagCount = 0;
var TagRepeat = 0;
// PLACEHOLDER VARIABLES
var Avatar = "";
var Character = "";
var Character_ID = "";
var Token = "";
// DEFAULT FORMATTING
var Display = "";
var PlayerBGColor = (player_obj) ? player_obj.get("color") : "#FFFFFF";
var PlayerTXColor = (getBrightness(PlayerBGColor) < (255 / 2)) ? "#FFFFFF" : "#000000";
var PlayerTXShadow = (getBrightness(PlayerBGColor) < (255 / 2)) ? "#000000" : "#FFFFFF";
PowerCard.titlefont = "Contrail One";
PowerCard.titlefontvariant = "normal";
PowerCard.titlefontshadow = "-1px -1px 0 " + PlayerTXShadow + ", 1px -1px 0 " + PlayerTXShadow + ", -1px 1px 0 " + PlayerTXShadow + ", 1px 1px 0 " + PlayerTXShadow + ";";
PowerCard.titlebackground = "linear-gradient(rgba(255, 255, 255, .3), rgba(255, 255, 255, 0));";
PowerCard.subtitlefont = "Tahoma";
PowerCard.subtitlefontvariant = "normal";
PowerCard.bodyfont = "Helvetica";
PowerCard.titlefontsize = "1.2em; line-height: 1.2em";
PowerCard.subtitlefontsize = "11px";
PowerCard.bodyfontsize = "14px";
PowerCard.txcolor = PlayerTXColor;
PowerCard.bgcolor = PlayerBGColor;
PowerCard.erowtx = "#000000";
PowerCard.erowbg = "#B6AB91"; // #B6AB91 - Default darker brown
PowerCard.orowtx = "#000000";
PowerCard.orowbg = "#CEC7B6"; // #CEC7B6 - Default light brown
PowerCard.corners = 5; // Set to 0 to remove rounded corners from PowerCards
PowerCard.border = "1px solid #000000"; // size style #color
PowerCard.boxshadow = ""; // h-distance v-distance blur spread #color
PowerCard.lineheight = "1.1em";
// CREATE POWERCARD OBJECT
n.shift();
_.each(n, function(a) {
Tag = a.substring(0, a.indexOf("|")).trim();
Content = a.substring(a.indexOf("|") + 1).trim();
if (Tag === "target_list") Content = Content.split(" | ");
// CREATE 5e OGL SHEET NPC ACTION LIST
if (Tag.includes("npc_action_list") && getObj("character", Content) !== undefined) {
Character_ID = Content;
Tag = "!npc_action_list";
Content = "";
var npc_action = getAttrByName(Character_ID, "repeating_npcaction_$0_name");
var action_count = 0;
while (npc_action !== "") {
Content += "[" + npc_action + "](~selected|repeating_npcaction_$" + action_count + "_npc_action) ^^";
action_count++;
npc_action = getAttrByName(Character_ID, "repeating_npcaction_$" + action_count + "_name");
}
}
// CREATE 5e OGL SHEET PREPARED SPELL LIST (BOTH PC & NPC)
if (Tag.includes("spell_list") && getObj("character", Content) !== undefined) {
Character_ID = Content;
Tag = "!spell_list";
Content = "";
var spell_list = filterObjs(function(z) { return (z.get("characterid") == Character_ID && z.get("name").endsWith("spellname")); });
var cantrips = sortByKey(spell_list.filter(s => s.get("name").startsWith("repeating_spell-cantrip")), "current");
var L1Spells = sortByKey(spell_list.filter(s => s.get("name").startsWith("repeating_spell-1")), "current");
var L2Spells = sortByKey(spell_list.filter(s => s.get("name").startsWith("repeating_spell-2")), "current");
var L3Spells = sortByKey(spell_list.filter(s => s.get("name").startsWith("repeating_spell-3")), "current");
var L4Spells = sortByKey(spell_list.filter(s => s.get("name").startsWith("repeating_spell-4")), "current");
var L5Spells = sortByKey(spell_list.filter(s => s.get("name").startsWith("repeating_spell-5")), "current");
var L6Spells = sortByKey(spell_list.filter(s => s.get("name").startsWith("repeating_spell-6")), "current");
var L7Spells = sortByKey(spell_list.filter(s => s.get("name").startsWith("repeating_spell-7")), "current");
var L8Spells = sortByKey(spell_list.filter(s => s.get("name").startsWith("repeating_spell-8")), "current");
var L9Spells = sortByKey(spell_list.filter(s => s.get("name").startsWith("repeating_spell-9")), "current");
if (cantrips.length > 0) {
Content += "~~~ **Cantrips:** ~~~";
cantrips.forEach(function(s) { Content += "[" + s.get("current") + "](~selected|" + s.get("name").replace("name", "") + ") "; });
}
if (L1Spells.length > 0) {
Content += "~~~ **1st Level Spells:** ~~~";
L1Spells.forEach(function(s) { Content += (getAttrByName(Character_ID, s.get("name").replace("name", "prepared")) == "1") ? "[" + s.get("current") + "](~selected|" + s.get("name").replace("name", "") + ") " : "";});
}
if (L2Spells.length > 0) {
Content += "~~~ **2nd Level Spells:** ~~~";
L2Spells.forEach(function(s) { Content += (getAttrByName(Character_ID, s.get("name").replace("name", "prepared")) == "1") ? "[" + s.get("current") + "](~selected|" + s.get("name").replace("name", "") + ") " : "";});
}
if (L3Spells.length > 0) {
Content += "~~~ **3rd Level Spells:** ~~~";
L3Spells.forEach(function(s) { Content += (getAttrByName(Character_ID, s.get("name").replace("name", "prepared")) == "1") ? "[" + s.get("current") + "](~selected|" + s.get("name").replace("name", "") + ") " : "";});
}
if (L4Spells.length > 0) {
Content += "~~~ **4th Level Spells:** ~~~";
L4Spells.forEach(function(s) { Content += (getAttrByName(Character_ID, s.get("name").replace("name", "prepared")) == "1") ? "[" + s.get("current") + "](~selected|" + s.get("name").replace("name", "") + ") " : "";});
}
if (L5Spells.length > 0) {
Content += "~~~ **5th Level Spells:** ~~~";
L5Spells.forEach(function(s) { Content += (getAttrByName(Character_ID, s.get("name").replace("name", "prepared")) == "1") ? "[" + s.get("current") + "](~selected|" + s.get("name").replace("name", "") + ") " : "";});
}
if (L6Spells.length > 0) {
Content += "~~~ **6th Level Spells:** ~~~";
L6Spells.forEach(function(s) { Content += (getAttrByName(Character_ID, s.get("name").replace("name", "prepared")) == "1") ? "[" + s.get("current") + "](~selected|" + s.get("name").replace("name", "") + ") " : "";});
}
if (L7Spells.length > 0) {
Content += "~~~ **7th Level Spells:** ~~~";
L7Spells.forEach(function(s) { Content += (getAttrByName(Character_ID, s.get("name").replace("name", "prepared")) == "1") ? "[" + s.get("current") + "](~selected|" + s.get("name").replace("name", "") + ") " : "";});
}
if (L8Spells.length > 0) {
Content += "~~~ **8th Level Spells:** ~~~";
L8Spells.forEach(function(s) { Content += (getAttrByName(Character_ID, s.get("name").replace("name", "prepared")) == "1") ? "[" + s.get("current") + "](~selected|" + s.get("name").replace("name", "") + ") " : "";});
}
if (L9Spells.length > 0) {
Content += "~~~ **9th Level Spells:** ~~~";
L9Spells.forEach(function(s) { Content += (getAttrByName(Character_ID, s.get("name").replace("name", "prepared")) == "1") ? "[" + s.get("current") + "](~selected|" + s.get("name").replace("name", "") + ") " : "";});
}
}
// CHECK FOR REPEAT TAG MODIFIER
if (Tag.charAt(0) !== "$") {
if (Tag.indexOf("#") !== -1) {
TagRepeat = parseInt(Tag.substring(Tag.indexOf("#") + 1));
TagCount = 1;
Tag = Tag.substring(0, Tag.indexOf("#"));
while (TagCount <= TagRepeat) {
var NewTag = Tag;
var NewContent = Content;
if (PowerCard.target_list !== undefined) {
if (Tag.indexOf("%%") !== -1 || Content.indexOf("%%") !== -1) {
NewTag = getTargetInfo(Tag, PowerCard.target_list);
NewContent = getTargetInfo(Content, PowerCard.target_list);
PowerCard.target_list.shift();
}
}
PowerCard[NewTag + " #" + TagCount] = NewContent;
TagCount += 1;
}
} else {
if (PowerCard.target_list !== undefined) {
if (Tag.indexOf("%%") !== -1 || Content.indexOf("%%") !== -1) {
Tag = getTargetInfo(Tag, PowerCard.target_list);
Content = getTargetInfo(Content, PowerCard.target_list);
PowerCard.target_list.shift();
}
}
PowerCard[Tag] = Content;
}
}
});
// PROCESS INLINE ROLLS...
safeSendChat("", JSON.stringify(PowerCard), function(x) {
var PowerCard = JSON.parse(x[0].content);
// GET CUSTOM STYLES AND ADD THEM TO POWERCARD...
if (USE_DEFAULT_FORMAT && state.PowerCard_Formats["default"] !== undefined && PowerCard.format === undefined) PowerCard.format = "default";
if (PowerCard.format !== undefined) {
var PowerCard_Formats = (state.PowerCard_Formats && state.PowerCard_Formats[PowerCard.format] !== undefined) ? state.PowerCard_Formats[PowerCard.format].split("--") : ["txcolor|#FFF", "bgcolor|#040", "titlefont|Georgia", "subtitlefont|Tahoma"];
PowerCard_Formats.forEach(function(a) {
Tag = a.substring(0, a.indexOf("|")).trim();
Content = a.substring(a.indexOf("|") + 1).trim();
if (Tag !== "" && Content !== "") PowerCard[Tag] = Content;
});
}
// GET LIST OF ROLL ID'S FOR CONDITIONAL STATEMENTS...
var RollText = "";
var RollID = "";
var RollResults = "";
var RollBase = 0;
var RollOnes = 0;
var RollTens = 0;
var RollTotal = 0;
var RollSuccesses = 0;
var Rolls = {};
Object.keys(x[0].inlinerolls).forEach(function(Roll) {
var RollCount = 0;
while (x[0].inlinerolls[Roll].results.rolls[RollCount] !== undefined) {
if (x[0].inlinerolls[Roll].results.rolls[RollCount].type === "L" && x[0].inlinerolls[Roll].results.rolls[RollCount].text.indexOf("$") !== -1) {
RollText = x[0].inlinerolls[Roll].results.rolls[RollCount].text.split("|");
var t = 0;
while (RollText[t] !== undefined) {
if (RollText[t].charAt(0) === "$") RollID = RollText[t];
t++;
}
// Roll Base
RollResults = x[0].inlinerolls[Roll].results.rolls[RollCount + 1].results;
if (RollResults === undefined) {
RollBase = x[0].inlinerolls[Roll].results.total;
} else {
t = 0;
RollBase = 0;
RollOnes = 0;
RollTens = 0;
while (RollResults[t] !== undefined) {
if ("table" in x[0].inlinerolls[Roll].results.rolls[RollCount + 1]) {
if (RollResults[t].tableidx) RollBase = RollBase + RollResults[t].tableidx;
} else {
if (!RollResults[t].d) RollBase = RollBase + RollResults[t].v;
}
RollOnes = (RollResults[t].v === 1) ? RollOnes += 1 : RollOnes;
RollTens = (RollResults[t].v === 10) ? RollTens += 1 : RollTens;
t++;
}
}
// Roll Total
RollTotal = x[0].inlinerolls[Roll].results.total;
// Roll Successes
if ("mods" in x[0].inlinerolls[Roll].results.rolls[RollCount + 1]) {
if ("success" in x[0].inlinerolls[Roll].results.rolls[RollCount + 1].mods) {
var rCount = 0;
RollSuccesses = 0;
while (rCount <= x[0].inlinerolls[Roll].results.rolls[RollCount + 1].results.length-1) {
if (x[0].inlinerolls[Roll].results.rolls[RollCount + 1].mods.success.comp == ">=") {
if (x[0].inlinerolls[Roll].results.rolls[RollCount + 1].results[rCount].v >= x[0].inlinerolls[Roll].results.rolls[RollCount + 1].mods.success.point) RollSuccesses += 1;
}
if (x[0].inlinerolls[Roll].results.rolls[RollCount + 1].mods.success.comp == "==") {
if (x[0].inlinerolls[Roll].results.rolls[RollCount + 1].results[rCount].v == x[0].inlinerolls[Roll].results.rolls[RollCount + 1].mods.success.point) RollSuccesses += 1;
}
if (x[0].inlinerolls[Roll].results.rolls[RollCount + 1].mods.success.comp == "<=") {
if (x[0].inlinerolls[Roll].results.rolls[RollCount + 1].results[rCount].v <= x[0].inlinerolls[Roll].results.rolls[RollCount + 1].mods.success.point) RollSuccesses += 1;
}
rCount++;
}
}
}
// Create RollID in Rolls with the following values...
Rolls[RollID] = {
"base": RollBase,
"total": RollTotal,
"successes": RollSuccesses,
"ones": RollOnes,
"tens": RollTens
};
}
RollCount++;
}
});
// PREVENT EMPTY EMOTE ERROR IN ROLL20 CHAT...
if (PowerCard.emote === "") PowerCard.emote = undefined;
// REPLACE UNDEFINED TITLE TAG WITH MSG.WHO...
if (PowerCard.title === undefined) PowerCard.title = "PowerCard sent by:
" + msg.who;
// ERROR CATCH FOR EMPTY WHISPER TAG...
if (PowerCard.whisper === "") PowerCard.whisper = "GM";
if (PowerCard.whisper === "self") PowerCard.whisper = msg.who;
if (PowerCard.whisper === "all") PowerCard.whisper = getOnlinePlayerNames();
// CREATE CSS EMOTE...
if (CUSTOM_EMOTES && PowerCard.emote !== undefined && (PowerCard.charid !== undefined || PowerCard.tokenid !== undefined)) {
// GET AVATAR FROM CHARACTER SHEET
if (PowerCard.charid !== undefined) {
Character = getObj("character", PowerCard.charid);
Avatar = (Character !== undefined && Character.get("avatar") !== "") ? "" : "";
}
// GET AVATAR FROM TOKEN IMAGE
if (PowerCard.tokenid !== undefined) {
Token = getObj("graphic", PowerCard.tokenid);
Avatar = (Token !== undefined && Token.get("imgsrc") !== "") ? "" : "";
}
// HIDE AVATAR
if (PowerCard.emote.charAt(0) === "!") {
PowerCard.emote = PowerCard.emote.substring(1);
SHOW_AVATAR = false;
}
// GET TEXT ALIGNMENT FOR EMOTES
var EmoteTextAlign = "center";
if (PowerCard.emote.indexOf("~L") !== -1) {
PowerCard.emote = PowerCard.emote.replace(/\~L/g, "");
EmoteTextAlign = "left";
}
if (PowerCard.emote.indexOf("~R") !== -1) {
PowerCard.emote = PowerCard.emote.replace(/\~R/g, "");
EmoteTextAlign = "right";
}
if (PowerCard.emote.indexOf("~J") !== -1) {
PowerCard.emote = PowerCard.emote.replace(/\~J/g, "");
EmoteTextAlign = "justify";
}
// CREATE EMOTE DIV
if (SHOW_AVATAR) PowerCard.emote = "