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

James the DM said: HoneyBadger , or any other big brain code monkeys that sees the Matrix. A while back you had posted about having the "monsters status cards" show up in the chat, have you or anyone else came up with away to do this? All I see in the matrix is green lines of code, but it looks like HB's power card script could be modified to display the monster status in chat. I have a DDI account and could export the ".monster files" and have for many of the monsters I use, but it"s very mouse click based and slow. I all so have all the DDI power cards and creature cards in html format and love to have an importer for the format if it possible? Jim You could certainly convert the monster information into powercard format, but that's not something I have any interest in doing. It would take a lot of work.
I'm using the bio and detail sections of my character sheet to whisper the DM/GM all the info for creatures, but as Honey Badger is stating it is a lot of work. In total it is just the relevant information. To the point you shouldn't have to access the Monster Manual.
I put all the monster info into my rollable tables as the name, set up the power card to randomly pick one, whisper it to me. I have my random encounter and all my info I need right there. Similar to what Wes did above with his random effects/wild surges. Traps and Magic Item/Treasure determination are next.
Bryan K. said: I'm using the bio and detail sections of my character sheet to whisper the DM/GM all the info for creatures, but as Honey Badger is stating it is a lot of work. In total it is just the relevant information. To the point you shouldn't have to access the Monster Manual. I am not a script writer, not in any sense of the word... I almost have the monster importer scraping the .monster file for the link to the Compendium, but it is one step forward two back at this point. Hope to have somthing soon.
OldSchoolChris said: I put all the monster info into my rollable tables as the name, set up the power card to randomly pick one, whisper it to me. I have my random encounter and all my info I need right there. Similar to what Wes did above with his random effects/wild surges. Traps and Magic Item/Treasure determination are next. Very cool.
No matter what I script, none of my cards seem to show up Here is some sample code: !power --emote|@{selected|token_name} rams his dagger home --name|Short Sword --leftsub|Melee --rightsub|Main Hand --attack| 1d20+10 --defense|AC --damage| 1d4+9 --dmgtype|piercing Even this doesn't show up. Can anyone tell me why?
You have to be in a campaign where the GM is a mentor and has installed this api script.
--attack|[[1d20r>18+?{Ranged|2}]] rerolls, but doesn't highlight, any ideas? Sorry, but I'm still new to the whole macro scripting
You need to add [HR18] in front of the roll you're wanting to highlight. For example... --attack|[[ [HR18] 1d20r>18+?{Ranged|2}]]
1414073903
The Aaron
Roll20 Production Team
API Scripter
Based on that other thread discussion.... You could change this: 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); if(command == "!power") { PowerCardScript.Process(msg); } }); To this: on("chat:message", function (msg) { // Exit if not an api command if (msg.type != "api") return; var command = msg.content.split(" ", 1); if(command == "!power") { // Get the API Chat Command var pMsg = _.clone(msg); pMsg.who = pMsg.who.replace(" (GM)", ""); pMsg.content = pMsg.content.replace("(GM) ", ""); PowerCardScript.Process(pMsg); } });
1414259288
vÍnce
Pro
Sheet Author
I know we can insert url's with hyperlinked text now, which sadly --whisper seems to ignore... Is it possible to create a link within a poswercard to open a handout. I tried using single brackets around my handout name [handout] but it just printed the text. Would --whisper also "mess" with this ability? Thanks
Nope. Handout links inside the chat window do not work.
1414261833
vÍnce
Pro
Sheet Author
Thanks HB. I'm currently just pasting the handouts "ugly" URL and that works with w/out --whisper One other question, I noticed that if I have a long block of text with carriage returns (paragraphs), anything after the first return is shown outside of the card... Other than making a custom tag per paragraph is there another method of showing the text with carriage returns? Thanks
Yeah. Use ^^ to create a carriage return.
1414264719
vÍnce
Pro
Sheet Author
Thank you and thanks for your powercard script. Introducing my players to it for the first time tonight.
I see that rerolls can be done by adding an r? after the die roll like this: --damage|[[ 2d10r1 + 9 ]], but is there a way to set the value to a fixed number if you roll a number that qualifies to be rerolled? Here's why: Avenging Resolution Heroic Tier Prerequisite : Avenger, oath of enmity power Benefit : When you attack a target of your oath of enmity with a weapon attack, treat all rolls of a 1 or 2 on the damage dice as though the result were a 3 on the die. Thanks!
1414350977
The Aaron
Roll20 Production Team
API Scripter
You can setup a rollable table for each die type and roll those. I actually have a script that does this: <a href="https://app.roll20.net/forum/post/950142/script-we" rel="nofollow">https://app.roll20.net/forum/post/950142/script-we</a>... So, the idea is you'd setup a rollable table with the numbers 3,3,3,4,5,6 for a 1d6 with a minimum of 3. For a single die, you can just use something like [[{d6,3}kh1]], but that doesn't work for multiple dice.
1414561216
Falcon
Pro
Sheet Author
HB - Been using your PowerCards for everything. I ran into a weird error in the latest version. It won't let me use the --^0. Well I mean it works but when I use --^0attack or --^0damage it comes up as -undefined. I can use --^0 on custom tags though. For example test this: !power --whisper| --emote|@{selected|token_name} fires his Longbow at @{target|token_name} --charid|@{selected|character_id} --name|@{selected|token_name} --leftsub|Longbow --rightsub|Range Attack --Target|@{target|token_name} --^Location|[[1t[Hit-Location]]] --^0attack|[[[HR 20] 1D20+@{RANGE BNS} + ?{Att Mods|0}]] vs. AC [[@{target|AC}]] --defense|[[@{target|AC}]] --^1Attack Modifier|[[?{Att Mods}]] --^0damage|[[1D8+@{DMG BNS}+ ?{Dmg Mods|0}]] of Piercing Damage --Critical|^* **20, x3** --^Damage Modifier|[[?{Dmg Mods}]] --Powers Applied|None
1414561706
Falcon
Pro
Sheet Author
Also - what does --defense do? Is there any attack vs defense checking within the script??? I notice that --defense doesn't show anything in my above script.
1414562075
The Aaron
Roll20 Production Team
API Scripter
--defense is intended for listing which of the 4 defenses the attack targets. It's a DnD 4th Edition thing. Would be one of: Def, Ref, Will, Fort
1414562872
Falcon
Pro
Sheet Author
Got it. Thanks Aaron. Too bad. Because It would be awesome to have an attack (skill) roll and then a defense (target #) checking. if it rolls the number or higher then the --damage| is displayed (or even other custom tags) otherwise it doesn't show it. That would lower the size of the power scripts in the message box substantially. You didn't hit? Then it's a 2 line Power Card. If you Hit - well here's the full script.
1414563004
Falcon
Pro
Sheet Author
You could probably do that with a special tag. So -- is the standard tag identifier. For success you can have a --& or whatever to signify that those only show up if the success number is reached. Just one simple if/then could really make a difference.
1414563621
The Aaron
Roll20 Production Team
API Scripter
For the ^0attack problem, it's because when he's storing the lookup (Line 157) for the attack line, it has the ^0 on the front: {"format":"","^0attack":"$[[0]]","leftsub":"","rightsub":""} but when he's looking it up (Lines 270, 271, 277, 281,293 and 303) he has stripped it off and so he's looking for the key 'attack', not '^0attack' and not finding it. For the other commands, he has pre fetched it into the content local variable (Line 248) and so has the correct data when he's building the line later (Line 313 and 317). Here's a patched version with the attack. ( Note: This does not fix it for multi attacks, since the matching is based on the first 6 characters of the tag (Line 91). Same goes for damage (line 97), multiroll (Line 103), and emote (Line 109). ) // 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 = false; 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); if(command == "!power") { PowerCardScript.Process(msg); } }); 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) { Content = Content.replace("]]", "]] vs " + PowerCard.defense + " "); DisplayCard += "&lt;div style='" + RowStyle + RowBackground + "'&gt;" + (POWERCARD_SHOW_ATTACK_DAMAGE_TAGS ? "&lt;b&gt;Attack:&lt;/b&gt; " : "") + Content + "&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; " : "") + Content + " 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; " : "") + Content + "&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; " : "") + Content + "&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;" + Content + "&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 !== "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); } else if (PowerCard.emote !== undefined) { sendChat(msg.who, "/emas " + PowerCard.emote); } 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); } 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); }
1414563670
The Aaron
Roll20 Production Team
API Scripter
Black Falcon said: You could probably do that with a special tag. So -- is the standard tag identifier. For success you can have a --& or whatever to signify that those only show up if the success number is reached. Just one simple if/then could really make a difference. You could, but HB is pretty anti-automation.
The Aaron said: You can setup a rollable table for each die type and roll those. I actually have a script that does this: <a href="https://app.roll20.net/forum/post/950142/script-we" rel="nofollow">https://app.roll20.net/forum/post/950142/script-we</a>... So, the idea is you'd setup a rollable table with the numbers 3,3,3,4,5,6 for a 1d6 with a minimum of 3. For a single die, you can just use something like [[{d6,3}kh1]], but that doesn't work for multiple dice. Aaron, I installed your script for weighted dice and created the tables, and they roll manually in the chat window like you described (/r 2t[d4min3]). Nice! So, is there a way I can substitute that roll in a power card macro? For example, if I had --damage|[[ 2d4 +2 ]] and wanted to use the 2t[d4min3] roll in place of the 2d4? When I do a straight substitution, I get 3, even though the mouseover of the result shows (3 + 3) + 2. How do you use rollable tables for inline rolls? Or is that even possible? Thank you!
1414649329
Falcon
Pro
Sheet Author
The Aaron said: Black Falcon said: You could probably do that with a special tag. So -- is the standard tag identifier. For success you can have a --& or whatever to signify that those only show up if the success number is reached. Just one simple if/then could really make a difference. You could, but HB is pretty anti-automation. I can understand the desire for anti-automation - we don't want to do too much and make it a video game. But I think finding ways to shorten the output would be something of desire. My powercards are already running the full size of the chat window. And thanks for the update. I don't use the multi-attack option so don't need to worry about it.
1414649892
The Aaron
Roll20 Production Team
API Scripter
Scott B. said: The Aaron said: You can setup a rollable table for each die type and roll those. I actually have a script that does this: <a href="https://app.roll20.net/forum/post/950142/script-we" rel="nofollow">https://app.roll20.net/forum/post/950142/script-we</a>... So, the idea is you'd setup a rollable table with the numbers 3,3,3,4,5,6 for a 1d6 with a minimum of 3. For a single die, you can just use something like [[{d6,3}kh1]], but that doesn't work for multiple dice. Aaron, I installed your script for weighted dice and created the tables, and they roll manually in the chat window like you described (/r 2t[d4min3]). Nice! So, is there a way I can substitute that roll in a power card macro? For example, if I had --damage|[[ 2d4 +2 ]] and wanted to use the 2t[d4min3] roll in place of the 2d4? When I do a straight substitution, I get 3, even though the mouseover of the result shows (3 + 3) + 2. How do you use rollable tables for inline rolls? Or is that even possible? Thank you! Hmm... Good question. I hadn't even considered the inline roll on a powercard might be different. I'll have to try it tomorrow and see... Sorry about that.
1414702805
The Aaron
Roll20 Production Team
API Scripter
Ok. I took a look at this. There's a line near the bottom that will take the first text label for a table item an use that instead of the die roll. I modified it in this version to work with tables regardless of if they are numeric or not: So, for this call: !power --name|test --dice|[[2d6]] --Tables with Text|[[ 3t[Druid] ]] --Numeric Tables|[[ 2t[d6min4]+2t[d8min5] ]] Tables with a numeric value as well as a text value get summed: It's a little rough, and it might make more sense to Group Rolls from the same table together, or from the same inline roll. Discuss. =D Modified source code: // 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 = false; 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); if(command == "!power") { PowerCardScript.Process(msg); } }); 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 !== "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); } else if (PowerCard.emote !== undefined) { sendChat(msg.who, "/emas " + PowerCard.emote); } 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); } 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... inlineroll.results.tableentries=_.chain(inlineroll.results.rolls) .filter(function(r){ return _.has(r,'table'); }) .reduce(function(memo,r){ _.each(r.results,function(i) { i=i.tableItem; if( ! /^[+\-]?(0|[1-9][0-9]*)([.]+[0-9]*)?([eE][+\-]?[0-9]+)?$/.test(i.name)) { memo.push({ name: i.name, weight: i.weight, table: r.table }); } }); return memo; },[]) .value(); 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;'; rollOut= (inlineroll.results.total === 0 && inlineroll.results.tableentries.length) ? '' : rollOut; rollOut+=_.map(inlineroll.results.tableentries,function(l){ return '&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="Table: '+l.table+' '+'Weight: '+l.weight+'" class="a inlinerollresult showtip tipsy-n"&gt;'+l.name+'&lt;/span&gt;'; }).join(''); 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); }
So Aaron, the inline rolls with rollable tables now work perfectly. However, the script no longer highlights high or low rolls (especially high rolls), even if I add [HR10] to a roll like this: --damage|[[ [HR10] 2t[d10min3] +5 ]] In addition, the --charid|@{selected|character_id} now no longer puts the picture of the selected token in the chat window next to the emote text on any of the powercards. Did you possibly edit an older copy of HB's script, or was your change something that could have affected those other features? Thanks, Scott
1414824747
vÍnce
Pro
Sheet Author
Can a player whisper a powercard to another player and if so, how? Also, is there a way to show the sender's name to the recipient without the sender having to select their own token and inserting @{selected|token_name} or equivalent in the powercard? For example when using /w the sender's name is shown to the recipient. BTW I learned that you can use an attribute as a custom tag within a powercard, ex. --@{selected|token_name}| This is new to me and a pleasant discovery.
1414850797
The Aaron
Roll20 Production Team
API Scripter
Scott B. said: So Aaron, the inline rolls with rollable tables now work perfectly. However, the script no longer highlights high or low rolls (especially high rolls), even if I add [HR10] to a roll like this: --damage|[[ [HR10] 2t[d10min3] +5 ]] In addition, the --charid|@{selected|character_id} now no longer puts the picture of the selected token in the chat window next to the emote text on any of the powercards. Did you possibly edit an older copy of HB's script, or was your change something that could have affected those other features? Thanks, Scott Hmm. I'll have to check. It's hard editing other people's scripts. =D
Custom emotes stopped working for you Scott, because the config variable var POWERCARD_CUSTOM_EMOTE is set to false in the edit Aaron posted.
The highlighted rolls using [HR#] stopped working because the numbers are generated in a function and the necessary variables aren't being passed to it (I think). Gotta go get ready for work. Might have time to work on this tomorrow.
Oh, right! Good catch, thank you. That was an easy fix. And also thank you for looking into the highlighted rolls when you get the chance. I saw a lot of your effort earlier in this thread on those rolls.
Yeah, not gonna get to this today or this week. Picked up some overtime tonight and have board game night at a friends house tomorrow night.
Hello, I am the user of a free account. How do I use these for me and my players? Do I need to be a subscriber?
1415194852
The Aaron
Roll20 Production Team
API Scripter
Hi Raul, You need to be a Mentor Level Subscriber to get access to the API, then you can install this and other scripts and make use of them.
1415214049
vÍnce
Pro
Sheet Author
Can a player whisper a powercard to another player and if so, how? Also, is there a way to show the sender's name to the recipient without the sender having to select their own token and inserting @{selected|token_name} or equivalent in the powercard? For example when using /w the sender's name is shown to the recipient. Bump
1415214869
The Aaron
Roll20 Production Team
API Scripter
Those are not currently features of the script but would be possible via the API.
1415217998
vÍnce
Pro
Sheet Author
Roger that. Thanks Aaron.
Are multirolls broken? <a href="http://puu.sh/cEHgG/73446d6f3e.png" rel="nofollow">http://puu.sh/cEHgG/73446d6f3e.png</a>
1415232090
The Aaron
Roll20 Production Team
API Scripter
He's using the --attack#| syntax.
1415242228

Edited 1415242418
vÍnce
Pro
Sheet Author
The Aaron said: He's using the --attack#| syntax. I'm too eager to help, but not knowledgeable enough to do so. :-)
1415243252
The Aaron
Roll20 Production Team
API Scripter
=D no worries! I missed it the first time and had to go back and look. =D
1415257800

Edited 1415258024
It's basically the same thing as --attack?{Number of Attacks|1}|[[1d20]] it just doesn't have the roll prompt. Edit: I did --attack3|[[d20]] instead of --attack?{Number of Attacks|1}|[[1d20]] to simplify the macro, to eliminate as many potential reasons for the problem as I could.
Vince said: Can a player whisper a powercard to another player and if so, how? Also, is there a way to show the sender's name to the recipient without the sender having to select their own token and inserting @{selected|token_name} or equivalent in the powercard? For example when using /w the sender's name is shown to the recipient. Bump Been busy with work... sorry. I haven't implemented whispers to anyone other than the GM or yourself at the moment. I will at some point.
1415277154

Edited 1415277485
Jarret B. said: Are multirolls broken? <a href="http://puu.sh/cEHgG/73446d6f3e.png" rel="nofollow">http://puu.sh/cEHgG/73446d6f3e.png</a> Not as far as I know... !power --name|Multiroll Test --attack3|[[1d20]] produced three attack rolls for me. Edit - Found the culprit... --format|dnd5e or setting var POWERCARD_DEFAULT_FORMAT = ""; to dnd5e is not working with multi-rolls. I think I did this /skipped adding it intentionally since multiattacks in D&D 5e roll damage for each attack. I should probably re-write the whole multi-roll stuff anyway and get rid of the autoformats. They're just confusing and make things more difficult.
I am trying to get Josh 's "Conditions and Status Tracker" to work with HoneyBadger 's "Power Cards" each script works alone but not together. anyone have any thoughts on how to get them to work together, or maybe another Conditions and Status Tracker that will work with "Power Cards" Thanks for making roll20 even better! Jim
1415287173
The Aaron
Roll20 Production Team
API Scripter
I'd be happy to jump in and see if I can figure out the issue if you wanna PM me a join link.