Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

[Script] Power Cards

1406840082

Edited 1419964688
Power Cards What are they? They are simply macro's formatted using tags that are interpreted by the script to apply html and css to contents of the macro. This string is then sent to the chat window via the API using /direct to allow the html and css formatting to work. What this is not! This is not a script meant to automate combat in any kind of RPG. It is simply a way to format the output of a macro in a more aesthetically pleasing manner and to facilitate multiple attack rolls within the same macro. This has the benefit of reducing the spam in the chat window (while admittedly creating a new kind of spam) and reduces the number of macros needed. Updates December 30th, 2014 ~ 1:40 pm eastern: Minor bugfix for sendChat issues and the random colon fix from earlier... December 30th, 2014 ~ 7:00 am eastern: Fixed the random colon appearing when using custom emotes. Added a version check into the script for bug tracking. Simply type !power_version in chat and the script will whisper you which version of the script your GM is currently using. October 18th, 2014 ~ 3:40 pm eastern: Added ability to parse URLS/Links Format: @@url||link text@@ Example: @@ <a href="http://www.google.com||Google@@" rel="nofollow">http://www.google.com||Google@@</a> You must enable this explicitly in the script itself using ALLOW_URLS and ALLOW_HIDDEN_URLS. This option is a use at your own risk kind of option since I'm not great at making sure input is sanitized or idiot proof. September 16th, 2014 ~ 9:00 am eastern: Minor but important bugfixes for indents. September 2nd, 2014 ~ 1:40 am eastern: Minor bugfix... indents no longer break the left hand side of the power card. If you want to fix this yourself without replacing the whole script, go to lines 219 and 221 and add the following in front of padding: 5px margin: 0px 0px 0px -10px; September 1st, 2014 ~ 4:30 pm eastern: Minor bugfix... avatars in custom emotes now work in chrome. September 1st, 2014 ~ 6:30 am eastern: Added a custom emote option that is triggered by adding --charid|@{character_id} to your emote. This will grab the avatar from your character sheet and prefix the contents of the --emote| tag with that image and format it without the colored background and italicize the text. See examples further down in this thread. If you want to use the new emote without an image, add a single ! exclamation mark at the start of the content of the emote tag to prevent the image from showing. Example: --emote|Leaps into the fray. shows the avatar of the character... --emote|!Leaps into the fray. does not show the avatar... Removed --lb| from list of tags. Do not use. Removed --desc| from list of tags. Do not use. August 21st, 2014 ~ 2:00 pm eastern: Bugfix... moved odd/even row default colors into the PowerCardScript.Process function to prevent macros from overriding these values and carrying over to other macros. August 21st, 2014 ~ 12:40 pm eastern: I have added four new tags... which let you further customize the appearance of the power cards. These colors can also be set for all power cards at the top of the script. --orowbg|#000 defines the background color of odd rows --orowtx|#000 defines the text color of odd rows --erowbg|#000 defines the background color of even rows --erowtx|#000 defines the text color of even rows August 20th, 2014 ~ 11:30 pm eastern: Tables now work... for one roll tables only. For example, a table named HitLocation would work if you used the following inline roll: [[ 1t[HitLocation ]] but would NOT work if you used [[ 2t[HitLocation] ]] August 17th, 2014 ~ 9:00 am eastern: Added a variety of new features. Most important however, is that --lb for line breaks is being deprecated and will be removed in the near future. The updates are as follows... --text| tag that can be used to display text only, without the tag. The text tag can also be used with multiple characters after the tag like: --text1|Stuff --text2|Stuff so that you can have multiple text tags in the same power card. Power Cards can now be sent via whispers to the person who triggers the card or the gm. --whisper|self will send the card to the person that triggers the macro. Anything else will send it to the gm instead. Line breaks are now handled inline instead of as a tag. Simply use ^^ to insert a line break. Double * (asterisk) around a word or set of words will bold those words. Double _ (underscore) will italicize words. ^* will insert a 1em space into the text. It could be used at the beginning of a paragraph to indent the first line. August 6th, 2014 ~ 11:45 pm eastern: The inline tag [NH] now works and disables highlighting of low and high rolls for that inline roll. August 2nd, 2014 ~ 3:30 am eastern: Added config options to set a default format for macros (this really only affects the attack/damage tags). Added an option to show Attack/Hit tags if show attack tag is true and format is dnd4e. No clue on how to fix the +[[#]] bug with multirolls yet (RobJ). Put in another config option to turn off inline roll highlighting completely for power cards. [NH] inline tag does not work still... August 1st, 2014 ~ 5:15 am eastern: Added options to define the colors for inline roll highlighting. These are global for all players and the GM. You can find them at the top of the script. The names should be pretty self explanatory. Number only inline rolls now work... [[3]] will show... 3! Am-aaaa-zing! I know. July 31st, 2014 ~ 10:30 pm eastern: Added config option to turn off roll highlighting globally. Added skeleton framework for defining custom highlighting colors. This is not fully implemented yet. Ran out of time during my break at work. Will update this during lunch. Using Tags The previous Power Card script was created specifically for Dungeons & Dragons 4th edition and did not allow for custom tags. This new version has many more features, including using custom names for tags and indenting tags. Tags will show up in the power card in the order of their use in the macro. There is one restriction... and that is that you cannot use the same tag name twice. Only the content of the second tag will be used. Tag Format - --Tag|Content This will show up as [ Tag: Content ] in the chat window. You MUST use this format or it will break your macro/api script. GOOD: --Effect|This is an effect. GOOD: --A Custom Tag|This is a custom tag. BAD: effect | This is a bad tag. BAD: -BadTag| This is also a bad tag. Reserved Tags - These tags are reserved for use by the script for various reasons and cannot be used as custom tags. --emote| If used, an emote will show up before the power card is displayed. This emote does NOT start with your Speaking As name. --name| Name of the power. It shows up on the title of the power card. --usage| Good for defining how often the power can be used. Ignored if both usage and action are not used. DEPRECATED: Use --leftsub| instead. --action| Defines the type of action it is. Ignored if both usage and action are not used. DEPRECATED: Use --rightsub| instead. --attack| Defines the attack roll. If you put a number after attack, such as --attack3| it will roll 3 attacks. You can use ?{Number of Attacks|1} as well. --defense| Defines the target number or defense of the attack. --damage| Creates a damage roll. You can now put a number after damage, such as --damage3| and it will roll three damage rolls now. --txcolor| Determines the color of the text in the title of the power card. --bgcolor| Sets the color of the background of the power card title. --leftsub| This tag sets the text to the left of the diamond in the title of the powercard. --rightsub| This tag sets the text to the right of the diamond in the title of the powercard. --desc| This tag should not be used with --emote| since it sends a blank /desc to the chat window before the power card. DEPRECATED! Do not use. --format| Use dnd4e dnd5e to tell the script what game rules you're using. It focuses entirely on --attack| output formatting for those editions of D&D --title| This tag sets a tooltip on the title of the power card --whisper| This tag sends the power card to the GM instead of the chat window. Use --whisper|self to send the powercard to your self instead. --orowbg| This tag sets the background color of odd rows in the power card. --orowtx| This tag sets the text color of odd rows in the power card. --erowbg| This tag sets the background color of even rows in the power card. --erowtx| This tag sets the text color of even rows in the power card. Inline Tags - These tags are used inside inline rolls with square brackets surrounding them. Example: [[[LR2] 1d6]] [LR#] - Highlights in RED any roll equal to or less than the number. [HR#] - Highlights in GREEN any roll greater than or equal to the number. [NH] - Disables highlighting of min/max rolls for this roll. Example: [[ [HR18] 1d20+1d20]] would highlight a roll of 18 or higher on the first d20 but not the second. To do that you would need to use another inline tag before the second roll like this... [[ [HR18] 1d20 + [HR18] 1d20]]. Inline Text Formatting - Use the following character combinations to indent a line or bold/italicize text. **Bold** __Italics__ ^*Indent Indenting - You can now indent a section by using ^ or ^# in front of a tag, such as --^1Secondary Attack|Make a second attack against a different enemy. The number determines the level of indenting up to a maximum of nine, though anything past three levels of indenting makes it difficult to read. If you want to remove the indenting for the next line, use ^0 in front of the tag (added by Rob J.). This indents entire sections of the powercard and all following sections. If you want to only indent one line, use ^* in the content instead of the tag. Contributors I'm sure I missed someone somewhere... but here is a short list of the people who have helped make this script a reality: Alex L., Chris N, Brian, Rob J., Aaron, and others (I'll add the rest when I have more time to look through the old thread and my private messages). The Script // VERSION INFO var PowerCards_Version = "1.0"; // VARIABLE & FUNCTION DECLARATIONS -- DO NOT ALTER!! var PowerCardScript = PowerCardScript || {}; var getBrightness = getBrightness || {}; var hexDec = hexDec || {}; // USER CONFIGUATION var POWERCARD_DEFAULT_FORMAT = ""; var POWERCARD_CUSTOM_EMOTE = true; var POWERCARD_USE_PLAYER_COLOR = false; var POWERCARD_SHOW_ATTACK_DAMAGE_TAGS = true; var POWERCARD_SHOW_ATTACK_DAMAGE_INFO = true; var POWERCARD_INLINE_ROLL_NO_HIGHLIGHT = false; var POWERCARD_INLINE_ROLL_COLOR_OVERRIDE = true; // ALLOW URLS IN POWERCARDS var ALLOW_URLS = false; var ALLOW_HIDDEN_URLS = false; // DEFINE SIZE & COLOR OF POWERCARD BORDER AND IF ROUNDED var POWERCARD_BORDER_SIZE = 1; var POWERCARD_BORDER_COLOR = "#000000"; var POWERCARD_ROUNDED_CORNERS = true; // DEFINE IF CORNER OF INLINE ROLLS ARE ROUNDED var POWERCARD_ROUNDED_INLINE_ROLLS = true; // DEFINE COLORS FOR STANDARD INLINE ROLLS var POWERCARD_INLINE_BASE_BORDER = "#87850A"; var POWERCARD_INLINE_BASE_BACKGROUND = "#FFFEA2"; var POWERCARD_INLINE_BASE_TEXT_COLOR = "#000000"; // DEFINE COLORS FOR MAXIMUM VALUE ROLLS var POWERCARD_INLINE_CRIT_BORDER = "#004400"; var POWERCARD_INLINE_CRIT_BACKGROUND = "#88CC88"; var POWERCARD_INLINE_CRIT_TEXT_COLOR = "#004400"; // DEFINE COLOR FOR MINIMUM VALUE ROLLS var POWERCARD_INLINE_FAIL_BORDER = "#660000"; var POWERCARD_INLINE_FAIL_BACKGROUND = "#FFAAAA"; var POWERCARD_INLINE_FAIL_TEXT_COLOR = "#660000"; // DEFINE COLORS FOR A ROLL WITH BOTH MINIMUM AND MAXIMUM VALUES IN THE ROLL var POWERCARD_INLINE_BOTH_BORDER = "#061539"; var POWERCARD_INLINE_BOTH_BACKGROUND = "#8FA4D4"; var POWERCARD_INLINE_BOTH_TEXT_COLOR = "#061539"; on("chat:message", function (msg) { // Exit if not an api command if (msg.type != "api") return; // Get the API Chat Command msg.who = msg.who.replace(" (GM)", ""); msg.content = msg.content.replace("(GM) ", ""); var command = msg.content.split(" ", 1)[0]; if (command === "!power") { PowerCardScript.Process(msg); } if (command === "!power_version") { sendChat("HoneyBadger", "/w " + msg.who + " You are using version " + PowerCards_Version + " of this script.") } }); PowerCardScript.Process = function(msg){ // DEFINE VARIABLES var n = msg.content.split(" --"); var PowerCard = {}; var DisplayCard = ""; var NumberOfAttacks = 1; var NumberOfDmgRolls = 1; var NumberOfRolls = 1; var Tag = ""; var Content = ""; var Character = ""; // MORE USER CONFIGURATION // DEFINE COLORS FOR ODD/EVEN ROWS var POWERCARD_ODD_ROW_BGCOLOR = "#CEC7B6"; // #CEC7B6 - Default light brown var POWERCARD_ODD_ROW_TXCOLOR = "#000000"; var POWERCARD_EVEN_ROW_BGCOLOR = "#B6AB91"; // #B6AB91 - Default darker brown var POWERCARD_EVEN_ROW_TXCOLOR = "#000000"; // SHOW AVATAR/IMAGE IN CUSTOM EMOTES var POWERCARD_SHOW_AVATAR = true; // SET THE DEFAULT FORMAT... Override with --format| in macro PowerCard.format = POWERCARD_DEFAULT_FORMAT; // CREATE POWERCARD OBJECT ARRAY n.shift(); n.forEach(function(token){ Tag = token.substring(0, token.indexOf("|")); Content = token.substring(token.indexOf("|") + 1); if (Tag.substring(0, 6).toLowerCase() === "attack") { var attacks = parseInt(Tag.substring(6)); if(attacks && attacks &gt;= NumberOfAttacks) { NumberOfAttacks = attacks; Tag = "attack"; } } else if (Tag.substring(0, 6).toLowerCase() === "damage") { var dmgs = parseInt(Tag.substring(6)); if(dmgs && dmgs &gt;= NumberOfDmgRolls) { NumberOfDmgRolls = dmgs; Tag = "damage"; } } else if (Tag.substring(0, 9).toLowerCase() === "multiroll") { var mrolls = parseInt(Tag.substring(9)); if(mrolls && mrolls &gt;= NumberOfRolls) { NumberOfRolls = mrolls; Tag = "multiroll"; } } else if (Tag.substring(0,5).toLowerCase() === "emote" && Content.charAt(0) === "!") { POWERCARD_SHOW_AVATAR = false; Content = Content.replace("!", ""); } // PARSE FOR INLINE FORMATTING var f; // LINE BREAK if (Content.indexOf("^^") != -1) Content = Content.replace(/\^\^/g, "&lt;br&gt;&lt;br&gt;"); // INDENT FIRST LINE if (Content.indexOf("^*") != -1) Content = Content.replace(/\^\*/g, "&lt;span style='margin-left: 1em;'&gt;&lt;/span&gt;"); // BOLD if (Content.indexOf("**") != -1) { // Do stuff... f = 1; while (Content.indexOf("**") != -1) { Content = (f % 2 == 1) ? Content.replace("**", "&lt;b&gt;") : Content.replace("**", "&lt;/b&gt;"); f++; } } // ITALICS if (Content.indexOf("__") != -1) { // Do stuff... f = 1; while (Content.indexOf("__") != -1) { Content = (f % 2 == 1) ? Content.replace("__", "&lt;i&gt;") : Content.replace("__", "&lt;/i&gt;"); f++; } } // URL if (Content.indexOf("@@") != -1 && ALLOW_URLS) { if (ALLOW_HIDDEN_URLS) { f = 1; while (Content.indexOf("@@") != -1) { Content = (f % 2 == 1) ? Content.replace("@@", "&lt;a href='") : Content.replace("@@", "&lt;/a&gt;"); if (f % 2 == 1) { Content = Content.replace("@@", "&lt;a href='"); Content = Content.replace("||", "' style='color:#000; text-decoration: underline;'&gt;"); } f++; } } else { while (Content.indexOf("@@") != -1) { Content = (f % 2 == 1) ? Content.replace("@@", "&lt;a&gt;") : Content.replace("@@", "&lt;/a&gt;"); f++; } } } PowerCard[Tag] = Content; }); // ERROR CATCH FOR EMPTY EMOTE if (PowerCard.emote === "") PowerCard.emote = '" "'; // CREATE CUSTOM EMOTE if (PowerCard.charid !== undefined && PowerCard.emote !== undefined && POWERCARD_CUSTOM_EMOTE) { Character = getObj("character", PowerCard.charid); if (POWERCARD_SHOW_AVATAR) { PowerCard.emote = "&lt;div style='display: table-cell; width: 50px;'&gt;&lt;img src='" + Character.get("avatar") + "' style='height: 50px; width: 50px;'&gt;&lt;/img&gt;&lt;/div&gt;&lt;div style='display:table-cell; width: calc(100%-50px); vertical-align: middle; font-size: 12px; font-style: italic; text-align: center;'&gt;" + PowerCard.emote + "&lt;/div&gt;"; } else { PowerCard.emote = "&lt;div style='display:block; width: 100%; vertical-align: middle; font-size: 12px; font-style: italic; text-align: center;'&gt;" + PowerCard.emote + "&lt;/div&gt;"; } } // CREATE WHISPER TARGET var WhisperTarget = ""; if (PowerCard.whisper !== undefined) { WhisperTarget = (PowerCard.whisper.toLowerCase() == "self") ? msg.who : "gm"; } // CREATE TITLE STYLE var TitleStyle = " font-family: Georgia; font-size: medium; font-weight: normal; letter-spacing: 0.25px; text-align: center; vertical-align: middle; padding: 2px 0px; margin: 0px 0px 0px -10px; border: " + POWERCARD_BORDER_SIZE + "px solid " + POWERCARD_BORDER_COLOR + ";"; // ROUNDED CORNERS ON TOP OF POWER CARD TitleStyle += (POWERCARD_ROUNDED_CORNERS) ? " border-radius: 10px 10px 0px 0px;" : ""; // LIST OF PRE-SET TITLE TEXT & BACKGROUND COLORS FOR D&D 4E var AtWill = " color: #FFF; background-color: #040;"; var Encounter = " color: #FFF; background-color: #400;"; var Daily = " color: #FFF; background-color: #444;"; var Item = " color: #FFF; background-color: #e58900;"; var Recharge = " color: #FFF; background-color: #004;"; // SET PowerCard.bgcolor TO PLAYER'S COLOR IF .bgcolor IS EQUAL TO PLAYER // THIS OVERRIDES TXCOLOR if (PowerCard.bgcolor == "player") { PowerCard.bgcolor = getObj("player", msg.playerid).get("color"); PowerCard.txcolor = (getBrightness(PowerCard.bgcolor) &lt; (255/2)) ? "#FFF" : "#000"; } // CHECK FOR PRESET TITLE COLORS if (!POWERCARD_USE_PLAYER_COLOR) { if (PowerCard.usage !== undefined && PowerCard.txcolor === undefined && PowerCard.bgcolor === undefined) { // PRESET TITLE COLORS TitleStyle += AtWill; if (PowerCard.usage.toLowerCase().indexOf("encounter") != -1) TitleStyle += Encounter; if (PowerCard.usage.toLowerCase().indexOf("daily") != -1) TitleStyle += Daily; if (PowerCard.usage.toLowerCase().indexOf("item") != -1) TitleStyle += Item; if (PowerCard.usage.toLowerCase().indexOf("recharge") != -1) TitleStyle += Recharge; } else { // CUSTOM TITLECARD TEXT & BACKGROUND COLORS TitleStyle += (PowerCard.txcolor !== undefined) ? " color: " + PowerCard.txcolor + ";" : " color: #FFF;"; TitleStyle += (PowerCard.bgcolor !== undefined) ? " background-color: " + PowerCard.bgcolor + ";" : " background-color: #040;"; } } else { // SET TITLE BGCOLOR TO PLAYER COLOR --- OVERRIDES ALL OTHER COLOR OPTIONS --- var PlayerBGColor = getObj("player", msg.playerid).get("color"); var PlayerTXColor = (getBrightness(PlayerBGColor) &lt; (255/2)) ? "#FFF" : "#000"; TitleStyle += " color: " + PlayerTXColor + "; background-color: " + PlayerBGColor + ";"; } // DEFINE .leftsub and .rightsub if (PowerCard.leftsub === undefined) PowerCard.leftsub = (PowerCard.usage !== undefined) ? PowerCard.usage : ""; if (PowerCard.rightsub === undefined) PowerCard.rightsub = (PowerCard.action !== undefined) ? PowerCard.action : ""; var PowerCardDiamond = (PowerCard.leftsub === "" || PowerCard.rightsub === "") ? "" : " ♦ "; // BEGIN DISPLAYCARD CREATION PowerCard.title = PowerCard.title ? PowerCard.title.split("|").join("&" + "#013;") : PowerCard.title; DisplayCard += "&lt;div style='" + TitleStyle + "' title='" + PowerCard.title + "'&gt;" + PowerCard.name; DisplayCard += (PowerCard.leftsub !== "" || PowerCard.rightsub !== "") ? "&lt;br&gt;&lt;span style='font-family: Tahoma; font-size: small; font-weight: normal;'&gt;" + PowerCard.leftsub + PowerCardDiamond + PowerCard.rightsub + "&lt;/span&gt;&lt;/div&gt;" : "&lt;/div&gt;"; // ROW STYLE VARIABLES if (PowerCard.orowbg !== undefined) POWERCARD_ODD_ROW_BGCOLOR = PowerCard.orowbg; if (PowerCard.orowtx !== undefined) POWERCARD_ODD_ROW_TXCOLOR = PowerCard.orowtx; if (PowerCard.erowbg !== undefined) POWERCARD_EVEN_ROW_BGCOLOR = PowerCard.erowbg; if (PowerCard.erowtx !== undefined) POWERCARD_EVEN_ROW_TXCOLOR = PowerCard.erowtx; var OddRow = " background-color: " + POWERCARD_ODD_ROW_BGCOLOR + "; color: " + POWERCARD_ODD_ROW_TXCOLOR + ";"; var EvenRow = " background-color: " + POWERCARD_EVEN_ROW_BGCOLOR + "; color: " + POWERCARD_EVEN_ROW_TXCOLOR + ";"; var RowStyle = " margin: 0px 0px 0px -10px; padding: 5px; border-left: " + POWERCARD_BORDER_SIZE + "px solid " + POWERCARD_BORDER_COLOR + "; border-right: " + POWERCARD_BORDER_SIZE + "px solid " + POWERCARD_BORDER_COLOR + "; border-radius: 0px;"; var RowBackground = OddRow; var RowNumber = 1; var Indent = 0; var KeyCount = 0; // KEY LOOP var Keys = Object.keys(PowerCard); var ReservedTags = "attack, damage, multiroll, text"; var IgnoredTags = "format, emote, name, usage, action, defense, txcolor, bgcolor, leftsub, rightsub, ddn, desc, crit, title, whisper, orowbg, orowtx, erowbg, erowtx, charid, playercolor"; Keys.forEach(function(Tag){ Content = PowerCard[Tag]; if (Tag.charAt(0) === "^") { Indent = (parseInt(Tag.charAt(1)) &gt;= 0) ? Tag.charAt(1) : 1; Tag = (parseInt(Tag.charAt(1)) &gt;= 0) ? Tag.substring(2) : Tag.substring(1); // Reset indent to 0 if ^0 is used... (Thanks to Rob J. on Roll20) if (Indent === "0") { RowStyle = " margin: 0px 0px 0px -10px; padding: 5px; border-left: " + POWERCARD_BORDER_SIZE + "px solid " + POWERCARD_BORDER_COLOR + "; border-right: " + POWERCARD_BORDER_SIZE + "px solid " + POWERCARD_BORDER_COLOR + "; border-radius: 0px;"; } else { RowStyle = " margin: 0px 0px 0px -10px; padding: 5px; border-left: " + POWERCARD_BORDER_SIZE + "px solid " + POWERCARD_BORDER_COLOR + "; border-right: " + POWERCARD_BORDER_SIZE + "px solid " + POWERCARD_BORDER_COLOR + "; border-radius: 0px; padding-left: " + (Indent * 1.5) + "em;"; } } // CHECK FOR RESERVED & IGNORED TAGS if (ReservedTags.indexOf(Tag) != -1) { // ATTACK ROLLS if (Tag.toLowerCase() == "attack") { for(var AttackCount = 0; AttackCount &lt; NumberOfAttacks; AttackCount++){ RowBackground = (RowNumber % 2 == 1) ? OddRow : EvenRow; RowNumber += 1; switch (PowerCard.format) { case "dnd4e": { if (AttackCount === 0) { PowerCard[Tag] = PowerCard[Tag].replace("]]", "]] vs " + PowerCard.defense + " "); DisplayCard += "&lt;div style='" + RowStyle + RowBackground + "'&gt;" + (POWERCARD_SHOW_ATTACK_DAMAGE_TAGS ? "&lt;b&gt;Attack:&lt;/b&gt; " : "") + PowerCard[Tag] + "&lt;/div&gt;"; } else DisplayCard += "&lt;div style='" + RowStyle + RowBackground + "'&gt;" + (POWERCARD_SHOW_ATTACK_DAMAGE_TAGS ? "&lt;b&gt;Attack:&lt;/b&gt; " : "") + "$[a" + AttackCount + "] vs " + PowerCard.defense + " &lt;/div&gt;"; break; } case "dnd5e": case "ddn": { DisplayCard += "&lt;div style='" + RowStyle + RowBackground + "'&gt;" + (POWERCARD_SHOW_ATTACK_DAMAGE_TAGS ? "&lt;b&gt;Attack:&lt;/b&gt; " : "") + PowerCard[Tag] + " vs Armor Class&lt;/div&gt;"; break; } default: { if (AttackCount === 0) DisplayCard += "&lt;div style='" + RowStyle + RowBackground + "'&gt;" + (POWERCARD_SHOW_ATTACK_DAMAGE_TAGS ? "&lt;b&gt;Attack:&lt;/b&gt; " : "") + PowerCard[Tag] + "&lt;/div&gt;"; else DisplayCard += "&lt;div style='" + RowStyle + RowBackground + "'&gt;" + (POWERCARD_SHOW_ATTACK_DAMAGE_TAGS ? "&lt;b&gt;Attack:&lt;/b&gt; " : "") + "$[a" + AttackCount + "]&lt;/div&gt;"; } } } } // DAMAGE ROLLS if (Tag.toLowerCase() == "damage") { for (var DamageCount = 0; DamageCount &lt; NumberOfDmgRolls; DamageCount++) { RowBackground = (RowNumber % 2 == 1) ? OddRow : EvenRow; RowNumber += 1; if (DamageCount === 0) DisplayCard += "&lt;div style='" + RowStyle + RowBackground + "'&gt;" + (POWERCARD_SHOW_ATTACK_DAMAGE_TAGS ? "&lt;b&gt;Hit:&lt;/b&gt; " : "") + PowerCard[Tag] + "&lt;/div&gt;"; else DisplayCard += "&lt;div style='" + RowStyle + RowBackground + "'&gt;$[d" + DamageCount + "]&lt;/div&gt;"; } } // MULTIROLLS if (Tag.toLowerCase() == "multiroll") { for (var MultiRoll = 0; MultiRoll &lt; NumberOfRolls; MultiRoll++) { RowBackground = (RowNumber % 2 == 1) ? OddRow : EvenRow; RowNumber += 1; if (MultiRoll === 0) DisplayCard += "&lt;div style='" + RowStyle + RowBackground + "'&gt;" + PowerCard[Tag] + "&lt;/div&gt;"; else DisplayCard += "&lt;div style='" + RowStyle + RowBackground + "'&gt;$[m" + MultiRoll + "]&lt;/div&gt;"; } } } else if (IgnoredTags.indexOf(Tag.toLowerCase()) != -1) { // Do nothing } else { if (Tag.toLowerCase().substring(0,4) == "text") { RowBackground = (RowNumber % 2 == 1) ? OddRow : EvenRow; RowNumber += 1; DisplayCard += "&lt;div style='" + RowStyle + RowBackground + "'&gt;" + Content + "&lt;/div&gt;"; } else { RowBackground = (RowNumber % 2 == 1) ? OddRow : EvenRow; RowNumber += 1; DisplayCard += "&lt;div style='" + RowStyle + RowBackground + "'&gt;&lt;b&gt;" + Tag + ":&lt;/b&gt; " + Content + "&lt;/div&gt;"; } } KeyCount++; }); // ADD ROUNDED CORNERS & BORDER TO BOTTOM OF POWER CARD if (POWERCARD_ROUNDED_CORNERS && KeyCount == (Keys.length)) DisplayCard = DisplayCard.replace(/border-radius: 0px;(?!.*border-radius: 0px;)/g, "border-radius: 0px 0px 10px 10px; border-bottom: " + POWERCARD_BORDER_SIZE + "px solid " + POWERCARD_BORDER_COLOR + ";"); if (!POWERCARD_ROUNDED_CORNERS && POWERCARD_BORDER_SIZE) DisplayCard = DisplayCard.replace(/border-radius: 0px;(?!.*border-radius: 0px;)/g, "border-bottom: " + POWERCARD_BORDER_SIZE + "px solid " + POWERCARD_BORDER_COLOR + ";"); // INLINE ROLLS REPLACEMENT if (msg.inlinerolls !== undefined) { // Process inline rolls... for (var i = 0; i &lt; msg.inlinerolls.length; i++){ var inlinerollValue = buildinline(msg.inlinerolls[i], PowerCard.crit); DisplayCard = DisplayCard.replace("$[[" + i + "]]", inlinerollValue); } // Process multirolls... var content = PowerCard.attack; var idx = content ? content.substring(content.indexOf("$[[") + 3, content.indexOf("]]")) : false; var exp = idx && msg.inlinerolls[idx] ? msg.inlinerolls[idx].expression : undefined; var attExp = buildExpression(NumberOfAttacks, "a", exp); content = PowerCard.damage; idx = content ? content.substring(content.indexOf("$[[") + 3, content.indexOf("]]")) : false; exp = idx && msg.inlinerolls[idx] ? msg.inlinerolls[idx].expression : undefined; var dmgExp = buildExpression(NumberOfDmgRolls, "d", exp); content = PowerCard.multiroll; idx = content ? content.substring(content.indexOf("$[[") + 3, content.indexOf("]]")) : false; exp = idx && msg.inlinerolls[idx] ? msg.inlinerolls[idx].expression : undefined; var mltExp = buildExpression(NumberOfRolls, "m", exp); // Process multiroll results... var rollExp = attExp + ";" + dmgExp + ";" + mltExp; sendChat("", rollExp, function(m){ var i; var inlinerollValue; for (i = 1; i &lt; NumberOfAttacks; i++){ inlinerollValue = buildinline(m[0].inlinerolls[i], PowerCard.crit); DisplayCard = DisplayCard.replace("$[a" + i + "]", inlinerollValue); } var dIndex = 1; for (i = NumberOfAttacks; i &lt; NumberOfAttacks + NumberOfDmgRolls-1 ; i++){ inlinerollValue = buildinline(m[0].inlinerolls[i], PowerCard.crit); DisplayCard = DisplayCard.replace("$[d" + dIndex++ + "]", inlinerollValue); } var mIndex = 1; for (i = NumberOfAttacks + NumberOfDmgRolls-1; i &lt; NumberOfAttacks+NumberOfDmgRolls+NumberOfRolls-2 ; i++){ inlinerollValue = buildinline(m[0].inlinerolls[i], PowerCard.crit); DisplayCard = DisplayCard.replace("$[m" + mIndex++ + "]", inlinerollValue); } // SEND OUTPUT TO CHAT if (PowerCard.whisper !== undefined) { if (PowerCard.emote !== undefined && PowerCard.charid !== undefined && POWERCARD_CUSTOM_EMOTE) { sendChat("", "/desc "); sendChat("", "/direct " + PowerCard.emote); } else if (PowerCard.emote !== undefined) { sendChat(msg.who, "/emas " + PowerCard.emote); } sendChat("Power Card Script", "/w " + WhisperTarget + " " + DisplayCard); } else { if (PowerCard.emote !== undefined && PowerCard.charid !== undefined && POWERCARD_CUSTOM_EMOTE) { sendChat("", "/desc "); sendChat("", "/direct " + PowerCard.emote + DisplayCard); } else if (PowerCard.emote !== undefined) { sendChat(msg.who, "/emas " + PowerCard.emote); sendChat("", "/direct " + DisplayCard); } else { sendChat("", "/direct " + DisplayCard); } } }); } else { // NO INLINE ROLLS if (PowerCard.whisper !== "no" && PowerCard.whisper !== undefined) { if (PowerCard.emote !== undefined && PowerCard.charid !== undefined && POWERCARD_CUSTOM_EMOTE) { sendChat("", "/desc "); sendChat("", "/direct " + PowerCard.emote); } else if (PowerCard.emote !== undefined) { sendChat(msg.who, "/emas " + PowerCard.emote); } sendChat("Power Card Script", "/w " + WhisperTarget + " " + DisplayCard); } else { if (PowerCard.emote !== undefined && PowerCard.charid !== undefined && POWERCARD_CUSTOM_EMOTE) { sendChat("", "/desc "); sendChat("", "/direct " + PowerCard.emote + DisplayCard); } else if (PowerCard.emote !== undefined) { sendChat(msg.who, "/emas " + PowerCard.emote); sendChat("", "/direct " + DisplayCard); } } } }; function buildinline(inlineroll){ var InlineBorderRadius = (POWERCARD_ROUNDED_INLINE_ROLLS) ? 5 : 0; var InlineColorOverride = ""; var values = []; var critRoll = false; var failRoll = false; var critCheck = false; var failCheck = false; var highRoll = false; var lowRoll = false; var noHighlight = false; inlineroll.results.rolls.forEach(function(roll){ var result = processRoll(roll, critRoll, failRoll, highRoll, lowRoll, noHighlight); if (result.value.toString().indexOf("critsuccess") != -1) critCheck = true; if (result.value.toString().indexOf("critfail") != -1) failCheck = true; values.push(result.value); critRoll = result.critRoll; failRoll = result.failRoll; highRoll = result.highRoll; lowRoll = result.lowRoll; noHighlight = result.noHighlight; }); // Overrides the default coloring of the inline rolls... if (POWERCARD_INLINE_ROLL_COLOR_OVERRIDE) { if (critCheck && failCheck) { InlineColorOverride = " background-color: " + POWERCARD_INLINE_BOTH_BACKGROUND + "; border-color: " + POWERCARD_INLINE_BOTH_BORDER + "; color: " + POWERCARD_INLINE_BOTH_TEXT_COLOR + ";"; } else if (critCheck && !failCheck) { InlineColorOverride = " background-color: " + POWERCARD_INLINE_CRIT_BACKGROUND + "; border-color: " + POWERCARD_INLINE_CRIT_BORDER + "; color: " + POWERCARD_INLINE_CRIT_TEXT_COLOR + ";"; } else if (!critCheck && failCheck) { InlineColorOverride = " background-color: " + POWERCARD_INLINE_FAIL_BACKGROUND + "; border-color: " + POWERCARD_INLINE_FAIL_BORDER + "; color: " + POWERCARD_INLINE_FAIL_TEXT_COLOR + ";"; } else { InlineColorOverride = " background-color: " + POWERCARD_INLINE_BASE_BACKGROUND + "; border-color: " + POWERCARD_INLINE_BASE_BORDER + "; color: " + POWERCARD_INLINE_BASE_TEXT_COLOR + ";"; } } // Temporary kludge to get table result... if (inlineroll.results.rolls[0].table !== undefined) inlineroll.results.total = inlineroll.results.rolls[0].results[0].tableItem.name; var rollOut = '&lt;span style="text-align: center; vertical-align: text-middle; display: inline-block; min-width: 1.75em; border-radius: ' + InlineBorderRadius + 'px; padding: 0px 2px; ' + InlineColorOverride + '" title="Rolling ' + inlineroll.expression + ' = ' + values.join(""); rollOut += '" class="a inlinerollresult showtip tipsy-n'; rollOut += (critCheck && failCheck ? ' importantroll' : (critCheck ? ' fullcrit' : (failCheck ? ' fullfail' : ''))) + '"&gt;' + inlineroll.results.total + '&lt;/span&gt;'; return rollOut; } function buildExpression(numRolls, tag, expression){ var rolls = []; for (var i = 1; i &lt; numRolls; i++){ rolls.push("[[" + expression +"]]"); } return tag + ":" + rolls.join(" "); } function processRoll(roll, critRoll, failRoll, highRoll, lowRoll, noHighlight){ if (roll.type === "C") { return {value: " " + roll.text + " "}; } else if (roll.type === "L") { if (roll.text.indexOf("HR") != -1) highRoll = parseInt(roll.text.substring(2)); else highRoll = false; if (roll.text.indexOf("LR") != -1) lowRoll = parseInt(roll.text.substring(2)); else lowRoll = false; if (roll.text.indexOf("NH") != -1) { // Blocks highlight on an individual roll... noHighlight = true; } // Remove inline tags to reduce clutter... roll.text = roll.text.replace(/HR(\d+)/g, ""); roll.text = roll.text.replace(/LR(\d+)/g, ""); roll.text = roll.text.replace(/NH/g, ""); if (roll.text !== "") roll.text = " [" + roll.text + "] "; return {value: roll.text, highRoll:highRoll, lowRoll:lowRoll, noHighlight:noHighlight}; } else if (roll.type === "M") { roll.expr = roll.expr.toString().replace(/\+/g, " + "); return {value: roll.expr}; } else if (roll.type === "R") { var rollValues = []; roll.results.forEach(function(result){ if (result.tableItem !== undefined) { rollValues.push(result.tableItem.name); } else { // Reset critRoll and failRoll for next roll... critRoll = false; failRoll = false; // Turn off highlighting if true... if (POWERCARD_INLINE_ROLL_NO_HIGHLIGHT || noHighlight) { critRoll = false; failRoll = false; } else { if (highRoll !== false && result.v &gt;= highRoll || result.v === roll.sides) critRoll = true; else if (lowRoll !== false && result.v &lt;= lowRoll || result.v === 1) failRoll = true; } result.v = "&lt;span class='basicdiceroll" + (critRoll ? ' critsuccess' : (failRoll ? ' critfail' : '')) + "'&gt;" + result.v + "&lt;/span&gt;"; rollValues.push(result.v); } }); return {value: "(" + rollValues.join(" + ") + ")", critRoll:critRoll, failRoll:failRoll, highRoll:highRoll, lowRoll:lowRoll, noHighlight:noHighlight}; } else if (roll.type === "G") { var grollVal = []; roll.rolls.forEach(function(groll){ groll.forEach(function(groll2){ var result = processRoll(groll2, highRoll, lowRoll, noHighlight); grollVal.push(result.value); critRoll = critRoll || result.critRoll; failRoll = failRoll || result.failRoll; highRoll = highRoll || result.highRoll; lowRoll = lowRoll || result.lowRoll; noHighlight = noHighlight || result.noHighlight; }); }); return {value: "{" + grollVal.join(" ") + "}", critRoll:critRoll, failRoll:failRoll, highRoll:highRoll, lowRoll:lowRoll, noHighlight:noHighlight}; } } function getBrightness(hex) { hex = hex.replace('#', ''); var c_r = hexDec(hex.substr(0, 2)); var c_g = hexDec(hex.substr(2, 2)); var c_b = hexDec(hex.substr(4, 2)); return ((c_r * 299) + (c_g * 587) + (c_b * 114)) / 1000; } function hexDec(hex_string) { hex_string = (hex_string + '').replace(/[^a-f0-9]/gi, ''); return parseInt(hex_string, 16); }
Reserved for examples and such...
1406842694
Nick S.
Pro
Marketplace Creator
Translator
Thank you!! I'll be testing it in a little while :)
This an new updated version? You should put some version info in there somewhere.
I suppose. I'm not real big on tracking version numbers lol.
Updated with some config options to turn off highlighting for all power cards and laid the groundwork for defining custom colors for highlighted rolls. This doesn't work yet, but will soon.
1406865703

Edited 1406866338
HoneyBadger, In an effort to make the cards look more like the actual D&D4E power cards do in say, the builder, I made a small edit to the script which made --attack and --damage output Attack: Hit: Like this. Now, I probably did it in a really bad way because I know next to nothing about these kinds of scripts. Do you think you could include an official option for it? I didn't actually change the --damage tag, I just made it say hit so that it wouldn't break my players macros. Edit: You have some typos on the last couple lines of the custom tags.
1406876557

Edited 1406878942
Thought I would share how my custom cards are looking. I really like the update, and thanks Honeybadger, the parser is working much better. Pathfinder ruleset. We can see a possible crit here, and for this player's sake I hope it is because its max crit damage, but if not its minimum weapon damage. Great roll... I combine this with a simple macro to roll a crit confirmation roll. I'll post a few more later in an edit. Thanks again, I love how the print out looks. Although now I can not represent static numbers because of the crit set feature, they seem to need to be driven by some math now. Before I would use [[30]] just to represent a static number for range so now I have to so something like [[10*3]] just to represent static numbers. I like expressing anything that is a number with the inline function as the colors pop and your eye catches them. This is not a major issue, but I thought I would mention it in case anyone else used the power cards this way.
Michael P. said: Although now I can not represent static numbers because of the crit set feature, they seem to need to be driven by some math now. Before I would use [[30]] just to represent a static number for range so now I have to so something like [[10*3]] just to represent static numbers. I like expressing anything that is a number with the inline function as the colors pop and your eye catches them. This is not a major issue, but I thought I would mention it in case anyone else used the power cards this way. My players do this too.
1406882592

Edited 1406883219
Hrm. I will look into the math only issue and see why it doesn't work. edit - Figured it out. I just need to add a .toString() to three spots because numbers by themselves are an actual integer and not a string, which throws an error in the script. I'm sure there's some other way I could figure it out, but this works. Will have an updated script shortly.
1406884595

Edited 1406892742
UPDATED August 1st, 2014 ~ 5:15 am eastern: Added options to define the colors for inline roll highlighting. These are global for all players and the GM. You can find them at the top of the script. The names should be pretty self explantory. Also... number only inline rolls work now. Totally forgot to mention that.
Thanks for the newest itteration HB!
Sexy
Don't forget to thank everyone else that helped.
Absolutely - awesome job to the lollipop kids behind the curtain making this oz-like love-child happen!
I'm new to these API scripts, and like the enhancement that !power offers... I have been working on what seems to be a simple card to make but have ran into errors with the following. !power --name|Sneak Attack --damage|[[@{sneak-formula}d6]] where =&gt; Attribute: sneak-formula = [[ceil(@{rogue-level}/2})]] The error sent to chat is: Could not determine result type of: [{"type":"M","expr":"ceil(1/2)"},{"type":"C","text":"d6"}] I understand what the error message is stating, but cannot figure out how to correct the problem. Any help would be appreciated. Thank you to everyone for your wonderful scripts and assistance.
1406907839

Edited 1406909478
Just been testing out the new version of the cards and they look very good, however I think I broke it... Take the following power !power --format|dnd4e --attack2|[[1d20+@{power-1-attack}]] --defense|@{power-1-def} (+1 if none of your allies are closer to the target) This now outputs the attack line of 23 vs AC (+1 if none of your allies are closer to the target) 26 vs AC (+1 if none of your allies are closer to the target) However if I run the card as it used to be (with the +[[1]] instead of the +1 to make it stand out) !power --format|dnd4e --attack2|[[1d20+@{power-1-attack}]] --defense|@{power-1-def} (+[[1]] if none of your allies are closer to the target) you get some interesting responses. First up PowerCardScript: Error occured and the output that is spat out is 8 vs AC (+1 if none of your allies are closer to the target) 15 vs AC (+$$[[1]] if none of your allies are closer to the target) If you increment the number of attacks the number in the $$[[x]] in the error output increments by 1 so I am assuming that this should be $$[[0]] to make the output work, but don't know where this is being generated. I also vote for the Attack lines to be added to the 4e power cards - I did modify my previous version of the code to include that (but with incrementing numbers after the attack on a real multi attack roll i.e. when number of attacks was greater than 1), but forgot to post it here. I will PM HoneyBadger with the code that I used for this.
I'm leaving to go watch Guardians of the Galaxy here shortly, but when I get back home I will try to sort out these issues. As for the +[[#]] ... I'd just say don't do that for now... personal preference, that's a bit overkill visually. But that's just me, though I have used the (+# if...) technique before.
Thanks again for all your hard work. This is excellent. ( And guardians of the galaxy was better then what I had hoped for. ;) )
Guardians of the Galaxy is fucking amazing!
1406957737

Edited 1406958018
Keith N. said: I'm new to these API scripts, and like the enhancement that !power offers... I have been working on what seems to be a simple card to make but have ran into errors with the following. !power --name|Sneak Attack --damage|[[@{sneak-formula}d6]] where =&gt; Attribute: sneak-formula = [[ceil(@{rogue-level}/2})]] The error sent to chat is: Could not determine result type of: [{"type":"M","expr":"ceil(1/2)"},{"type":"C","text":"d6"}] I understand what the error message is stating, but cannot figure out how to correct the problem. Have you tried using that formula outside of a powercard script? I couldn't get it to work even when I entered it directly into the chat window using @{name|attribute}. Example: [[@{thief|sneak-formula}d6]]
For DND In the scenario of an attack roll that results in a crit which the script understands, is there a method of displaying the max damage only and not the regular damage? Something like a conditional eval on the damage string that replaces xdx with x*x when the attack crit value is reached.
Melkir L. said: For DND In the scenario of an attack roll that results in a crit which the script understands, is there a method of displaying the max damage only and not the regular damage? Something like a conditional eval on the damage string that replaces xdx with x*x when the attack crit value is reached. No and that is outside of the scope of this script. I refuse to put in any kind of combat automation like that, simply due to the fact there are way too many methods by which a crit can be reduced to a normal hit or entirely negated. Easier to just add the crit damage as a label inside the roll [[1d10+4 [14 if crit]]].
1406965343

Edited 1406965354
Updated! August 2nd, 2014 ~ 3:30 am eastern: Added config options to set a default format for macros (this really only affects the attack/damage tags). Added an option to show Attack/Hit tags if show attack tag is true and format is dnd4e. No clue on how to fix the +[[#]] bug with multirolls yet (RobJ). Put in another config option to turn off inline roll highlighting completely for power cards. [NH] inline tag does not work still...
1406991063

Edited 1406991288
Never mind, I found what I was looking for.
HoneyBadger said: Keith N. said: I'm new to these API scripts, and like the enhancement that !power offers... I have been working on what seems to be a simple card to make but have ran into errors with the following. !power --name|Sneak Attack --damage|[[@{sneak-formula}d6]] where =&gt; Attribute: sneak-formula = [[ceil(@{rogue-level}/2})]] The error sent to chat is: Could not determine result type of: [{"type":"M","expr":"ceil(1/2)"},{"type":"C","text":"d6"}] I understand what the error message is stating, but cannot figure out how to correct the problem. Have you tried using that formula outside of a powercard script? I couldn't get it to work even when I entered it directly into the chat window using @{name|attribute}. Example: [[@{thief|sneak-formula}d6]] From the chat window, I can get /r @{thief|sneak-formula}d6 to work, but not [[@{thief|sneak-formula}d6]], it throws a SyntaxError: Expected "]" or [^\]] but end of input found. This does not seem related directly to powercard script, but I was not sure if there was a work around or if this is even an error to report.
1407020382
The Aaron
Roll20 Production Team
API Scripter
Can you rename the attribute as sneak_formula? Could the - be misinterpreted here?
@Keith N. The new version of the script uses the inline results as given by the roll20 message processor. As such, any inline expression must work as a normal macro before it can be used in this script. That being said, I nor HoneyBadger have tested every combination of inline roll results, but if one is found simply post it and i'm sure adding compatibility should be quick and easy. As for the static numbers not working, I never actually thought to test that. I too do use those so I should have had it in my test suite.
1407064368
Lithl
Pro
Sheet Author
API Scripter
Aaron said: Can you rename the attribute as sneak_formula? Could the - be misinterpreted here? Attributes are expanded before the API gets the message, so sneak-formula vs. sneak_formula wouldn't make any difference.
I think you are running into the same problem that I was running into with one of my formulas. You are using: Attribute: sneak-formula = [[ceil(@{rogue-level}/2})]] !power --name|Sneak Attack --damage|[[@{sneak-formula}d6]] Which after substitution it ends up as: [[[[ceil(@{rogue-level}/2})]]d6]] which is a problem due to the nested inline rolls that roll20 can't handle. If you swapped the inline roll in the power card to just [[(ceil(@{rogue-level}/2}))d6]] as a single roll it might work (I can't test it since I'm at work today). I ran into a similar problem with one of my functions I was trying to do which ended up working after expanding it out and not using the second attribute.
wait, doesn't this work: Attribute: sneak-formula = ceil(@{rogue-level}/2}) // please note: doesn't have the roll brackets. !power --name|Sneak Attack --damage|[[ ( @{sneak-formula} ) d6]] if this is an issue with the character sheets, you need to add a second variable. I use sneak-formula's max to keep track of it, like this attribute:attr_sneak-formula = ceil(@rogue-level}/2}) attribute:attr_sneak-formula_max = [[@{sneak-formula}]] then you can have sneak-formula calculated directly and display it by calling sneak-formula_max, and use sneak-formula in your macros without worrying about nexting brackets. not tested for this exact example, but use this technique for sneak attacking in my own 3.5 game
Michael H. said: wait, doesn't this work: Attribute: sneak-formula = ceil(@{rogue-level}/2}) // please note: doesn't have the roll brackets. !power --name|Sneak Attack --damage|[[ ( @{sneak-formula} ) d6]] if this is an issue with the character sheets, you need to add a second variable. I use sneak-formula's max to keep track of it, like this attribute:attr_sneak-formula = ceil(@rogue-level}/2}) attribute:attr_sneak-formula_max = [[@{sneak-formula}]] then you can have sneak-formula calculated directly and display it by calling sneak-formula_max, and use sneak-formula in your macros without worrying about nexting brackets. not tested for this exact example, but use this technique for sneak attacking in my own 3.5 game Still getting the same results: Could not determine result type of: [{"type":"M","expr":"(ceil(1/2))"},{"type":"C","text":"d6"}] I am just hard coding the numbers for now. A big thanks to everyone for helping.
Yeah, I tried getting those to work and couldn't... not even pasting them directly into chat. Minor update to the script. [NH] will block highlighting of low/high rolls.
Anyone have any requests for the power card script? That does not involve automating combat.
I think everything is working fine for me - apart from the ++[[#]] bug on multirolls. And just in case it isn't said enough - awesome script :)
1407397571

Edited 1407398674
Not really a request for change - but more a system that I use to organize the buttons - if you like it; take it! As my players are creeping up on paragon level their token macros are starting to read like a small novel. In order to help them organize this - i generally, after i import their updated characters, go through all their token macros and add AW- ; E- ; D- tags to the front of them; then just organized them into those groups. So all their at-wills are together, encounters, and dailies. just so they can skim through easy and pick what they need out a bit faster. Of course the BEST thing would be if we could actually COLOR the token macros - but i think that may require more than user scripting. Now if this was something automated, all the powers were grouped and tagged thus -directly after importing; it would be awesome. However, your work (and your collaborators') has made 4th ed into a manageable system and if nothing ever changed on your script it still be the best DM tool I use out there! EDIT: in retrospec this should have probably gone in under the character importer thread &gt;.&lt; Button macro tag Example: HERE
Rob J. said: I think everything is working fine for me - apart from the ++[[#]] bug on multirolls. And just in case it isn't said enough - awesome script :) Not sure what's going on with that bug... it's rather odd. I can't seem to find why it would be doing that. And thank you. Just glad people are finding a use for it.
Love the script, I don't have any other requests. Do you have plans to work on your two importer scripts?
Yeah. Though I'm not really liking the character sheets, damping my enthusiasm for updating the script to match.
1407405951

Edited 1407407651
Future prospects with dnd 5e? With the new d&d tools about to go into BETA do you have any plans to create importers for the new itteration of DnD or sticking it out with 4th? Or perhaps waiting for the dust to settle before thinking of making the switch?
1407424852
Tom F.
Pro
API Scripter
I love the power cards. It increases legibility so much that I use the power cards for all sorts of things, in all sorts of games (as a header for Edge of the Empire Rolls, using the EotE Dice Roller Script). The only things I can think are cosmetic...maybe the ability to change the table colours, not the bgcolor, and txcolor but the brown table itself? Maybe on a line-by line basis? I'm not sure what this would involve. The script is truly marvelous, and brings a great aesthetic to the Roll20 chat window. Here's a sample of how I use the cards in EotE...it makes everything so much easier (for me) to read.
1407425297
The Aaron
Roll20 Production Team
API Scripter
Suggestion: Character specific color overrides My macros using power cards all have this in common: --bgcolor|#@{BGColor} --txcolor|#@{FGColor} example: !power --format|ddn --emote|@{selected|token_name} extends his hand and a blast of arctic frost sprays forth! --bgcolor|#@{BGColor} --txcolor|#@{FGColor} --name|Ray of Frost --leftsub|50 ft --rightsub|Evocation Cantrip --attack|[[1d20+@{Int}+@{Proficiency}]] | [[1d20+@{Int}+@{Proficiency}]] --damage|[[1d8]] cold damage and target's speed is reduced by 10ft until @{selected|token_name}'s next turn. Having the script check the calling character for some defaults would be a nice enhancement from my perspective. Obviously you'd have to pass something like --asCharacter|&lt;character_id&gt; but that's not a deal breaker for me. =D
1407425556
The Aaron
Roll20 Production Team
API Scripter
Suggestion: Leverage the power of underscore.js's _.template() function Since most people are calling the same power command over and over, you could take a hash of the command string (should be the same regardless of inline roll values), and use that to cache the generated format. Then if you see it again, you can just stuff in the rolls as needed. Store the cached versions in a variable on the powerCardScript object so they only persist until the next sandbox restart. You can store metadata as well so as to speed up interpreting what rolls need to be performed.
Kenny T. said: Future prospects with dnd 5e? With the new d&d tools about to go into BETA do you have any plans to create importers for the new itteration of DnD or sticking it out with 4th? Or perhaps waiting for the dust to settle before thinking of making the switch? Since I won't be playing 5th edition, I won't be creating an importer. I simply prefer the more dynamic nature of combat in 4th edition and the feel of the game in general. With 4th, you have powers and you know how they work. 5th edition has gone back to the "mother may I" style of DM'ing and it sucks, imo.
1407444774
Actoba
Pro
Sheet Author
Not so much a request for a power card feature but the thread i just posted in the suggestions forum was partially inspired by looking over the latest and greatest updates and discussions here so thought i'd jump in and say keep up the good work! :)
1407481765

Edited 1407481782
Nice HB! stick to your guns! I totally feel you and for the most part have the same mentality as you - just i am deeply concerned about the future of the now "legacy 4e tools" they are such a crutch for me that whenever they may stop working i would be up SH#@'s creek. Having never purchased a single 4e book (outside of a campaign setting" and just pulling whatever i need form the tools/glossary when a rule discrepancy came up" - needless to say i am not well equiped to handle DM'ing with out that life support. however if they made a 1 time purchase DL'd tool - well that's a different story...
Sooooo..... any bugs... problems... requests? (non-automated stuff that is...)
1407763466
The Aaron
Roll20 Production Team
API Scripter
Did you consider my suggestions as automation?
Hrm, could've sworn I posted a reply. Maybe I started one and didn't finish it on my phone at work. I'm not big on the template thing. That would require me to learn more javascript... lol. And the colors... I can easily make a change to where you can specify the two colors, but to be able to individually color every line would be nightmarish.
1407764856
Wes
Sheet Author
Is it possible to get the inline dice roller to out put a table roll? I would really like to call rolls from a table in this script but it won't do it currently, unless I missed something. Whenever I have tried I believe it returns a 0(zero).
Have you tried it recently since the updated script?