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

Roll20 Tips and Tricks (Innovative Solutions to Common Problems)

Toggleable template fields, an update on reusing rolls Following on from the earlier toggleable template fields post : Attempting to reuse rolls in a hide-able section would prevent that section from being hidden. However this problem can be avoided by using HTML entities to partially escape any roll reference. So $[[0]] becomes $[[0]]. Reusing a roll this way doesn't interact with the rest of the roll parsing making it safe to use for our purposes here. (Note: It only works when using roll templates) Toggleable template fields, roll controlled Those familiar with reusing rolls know that trying to reuse a roll before it happens breaks any roll it was nested inside of. This behaviour can be used to control if a set of template fields is inside a working roll or not, since a "broken" roll won't hide the fields but a working roll will. By using a dynamic roll reference to conditionally reference a nested roll within a hide-able section. That hide-able section can then be hidden or shown based on a roll result. A single section example In this example 2d4 is rolled and on double one will show "Snake Eyes!" after the roll plus a "Bonus Section" $[[$[[1]]]] [[[ [[ {0,[[2d4]]}=2*2 ]] ]]] &{template:default} {{2d4=$[[0]]}} [[[0 [[0]] {{2d4=$[[0]] Snake Eyes!}} {{Bonus Section}}]]] A multi section example In this example a d6 is rolled that highlights a roll of 1 and a roll of 6 with bonus d6 $[[$[[1]]]] [[[ [[ {1,6,6}=[[d6]]*2 ]] ]]] &{template:default} {{d6=$[[0]]}} [[[0 [[0]] {{d6=$[[0]] One!}} ]]] [[[0 [[0]] {{d6=$[[0]] Six!}} {{Bonus d6=$[[5]]}} ]]] [[d6 Bonus]]
1718225889
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
You never cease to astound, Rainbow Encoder!
1721308921

Edited 1721320164
Collapsing rows and Bleeding CSS to next row in a template As it's been noted, using CSS styling in a standard template can be a bit tricky, because the template uses = as a separator in the content rows. But, by some clumsy experimentation, I accidentally managed to break the rows to allow CSS to be applied to the left side of the equation (with a caveat I'll get to). Here's how: First, we make our CSS row - this row needs not have content, though it can have some - what we care about is the end: {{=[placeholder](#" style=" whatever style declarations you want; class="showtip" title=)}} You'll notice the empty tooltip trick at the end - this is important. Next, the content row: {{[the left side, with the CSS styling from above](#)=The right side}} Putting it all together... &{template:default} {{=[placeholder](#" style=" color: white; text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; background-image: linear-gradient(to right, red,orange,yellow,green,blue,indigo,violet; class="showtip" title=)}} {{[Rainbow](#)=Not Rainbow!}} Ta-dah! The first row has disappeared (or more specifically, collapsed into the second, but the broken link is not displayed - if there's other content on that row, it'll replace the left  side of the bottom row, either as a normal left side entry, if left of the =, or as an indented, stylable right-left - I haven't fully explored what you can do with that), and the CSS styling has been applied to the left side of the second row! Now, you'll notice the caveat I mentioned - there's a very noticeable indent on the left side of the template - the left side starts at about the same position as the right would in a normally partitioned template. However, the left side is still fully functional as a row name, meaning you can use overwrite trick to all kinds of clever effects, from hiding the name fields with a display:none;  to shifting around the CSS bleed rows, to maybe even more clever things with the row-collapsing trick. Go wild! EDIT: You can even add a tooltip to the left-side field using this trick, by placing the whole tooltip trick before the collapse trick: &{template:default} {{=[placeholder](#" style=" color: white; text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; background-image: linear-gradient(to right, red,orange,yellow,green,blue,indigo,violet; " class="showtip" title= boop class="showtip" title=)}} {{[Rainbow](#)=Not Rainbow!}} Relatedly, you can daisy chain collapsed rows to turn multiple rows into files on a single row instead, like so: &{template:default} {{[=Let's go![collapser](#" style=" display: none; class="showtip" title=)}} {{[1](#)=first file content goes here[ collapser ](#" style=" display: none; class="showtip" title=)}}{{[2](#)=second file content goes here [ collapser ](#" style=" display: none; class="showtip" title=)}}{{[3](#)=third file content goes here [ collapser ](#" style=" display: none; class="showtip" title=)}} {{[4](#)=fourth file content goes here}} Though the template dimensions can get pushed out of the right side of the chat if there's too many too wide files. If you do not hide the left elements, they appear at the end of the file to the left of its content (think of them as an index starting with 0, with 0 being the empty file at the left). EDIT: I figured out how to solve the indent issue (or rather, how to apply the trick to the actual first row name) - it's as simple as putting the collapser at the end of the name space, like so: &{template:default} {{name=testing stuff[placeholder](#" style=" display: none; class="showtip" title=)}}{{[0](#)=[first file content goes here](#" style=" font-weight: normal; display: block; color: white; text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; background-image: linear-gradient(to right, red,orange,yellow,green,blue,indigo,violet;)[placeholder](#" style=" display: none; class="showtip" title=)}} {{[1](#)=second file content goes here[placeholder](#" style=" display: none; class="showtip" title=)}}{{[2](#)=third file content goes here[placeholder](#" style=" display: none; class="showtip" title=)}}{{[3](#)=fourth file content goes here}} The text defaults to bold in the first file, but you can use CSS styling to make it look however you like - it's content on the left side of the = on its row, so if you like, you can style every single letter differently. This also means you can make a full width text field in a template , where you can style individual segments as you wish. TLDR; this tech 1. collapses a template row (but not the namespace) into the next row 2. applies the CSS declarations to the name (left side) of the next row and 3. allows you to place the content of a row where the name of the row would be, or vice versa, and create extra files in the row.
1721315515
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
Thanks for breaking that long dry spell, Tuo, with a real whizbanger!
Health Bars in Chat Given an attribute with a known maximum, such as health in most games, you can make use of reusing rolls to display them as bars, by overlaying elements with position: absolute;, anchoring the elements to the left (or right, if you prefer) side of the chat with left: 0px; and using the reused roll containing the desired value, divided by the max value and multiplied by 100, for width: %;, and the original "roll" is hidden by placing it outside template rows, like so: &{template:default}{{name=[ ](#" style=" background-color: black; padding: 10px 0px 10px; margin-top: -5px; display: block; width: 100%;  position: absolute; left: 0px)[ ](#" style=" background-color: green; padding: 10px 0px 10px; margin-top: -5px; display: block; width: $[[0]]%;  position: absolute; left: 0px)}} [[ [[?{health out of 100?}/100*100]] ]] (example of multiple simple green bars placed in chat one after another) With that basic format, you can adjust the declarations to your heart's content, add new elements and variables to make more complex and fancier bars. Here's a much more complex example, featuring health bar changing color as it gets lower, and supporting multiple health bars laid on top of each other, using @{hp} character attribute, max hp defined in @{Cinematic Weight|hp} (due to the game I wrote this macro for), @{bars} and it's sheet-defined max for the bar count (accessed through some nested attribute calls, because calling max values in abilities is needlessly complicated if you want to use the exact same macro across multiple sheets without changing attribute references). &{template:default}{{name=[ ](#" style=" background-color: black; padding: 10px 0px 10px; margin-top: -5px; display: block; width: 100%;  position: absolute; left: 0px; z-index: 1)[ ](#" style=" opacity: $[[19]]%; padding: 10px 0px 10px; margin-top: -5px; display: block; width: 110%;  position: absolute; left: 0px; z-index: 1; background-image: linear-gradient(#995400, #995400, #eb7900, #eb7900, #eec890)[ ](#" style=" opacity: $[[18]]%; padding: 10px 0px 10px; margin-top: -5px; display: block; width: 110%;  position: absolute; left: 0px; z-index: 1; background-image: linear-gradient(#636300, #636300, #c7b000, #c7b000, #eded91)[ ](#" style=" opacity: 30%; padding: 10px 0px; border-left: 4px solid lightgrey; margin-top: -5px; display: block; width: $[[20]]%;  position: absolute; right: 0px; z-index: 2; background-image: linear-gradient(to right, black, transparent, transparent)[ ](#" style=" opacity: 30%; padding: 10px 0px; border-left: 4px solid lightgrey; margin-top: -5px; display: block; width: $[[21]]%;  position: absolute; right: 0px; z-index: 2; background-image: linear-gradient(to right, black, transparent, transparent, transparent)[ ](#" style=" padding: 10px 0px; margin-top: -5px; display: block; width: $[[12]]%;  position: absolute; left: 0px; z-index: 2; background-image: linear-gradient(darkred, darkred, red, red, #ee9090)[ ](#" style=" opacity: $[[1]]%; padding: 10px 0px; margin-top: -5px; display: block; width: $[[13]]%;  position: absolute; left: 0px; z-index: 3; background-image: linear-gradient(darkgreen, darkgreen, green, green, lightgreen)[ ](#" style=" opacity: $[[7]]%; padding: 10px 0px; margin-top: -5px; display: block; width: $[[14]]%;  position: absolute; left: 0px; z-index: 3; background-image: linear-gradient(#636300, #636300, #c7b000, #c7b000, #eded91)[ ](#" style=" opacity: $[[11]]%; padding: 10px 0px; margin-top: -5px; display: block; width: $[[15]]%;  position: absolute; left: 0px; z-index: 3; background-image: linear-gradient(#995400, #995400, #eb7900, #eb7900, #eec890)[ ](#" style=" opacity: 85%; padding: 5px 0px; margin-top: -5px; display: block; width: $[[16]]%;  position: absolute; left: 0px; z-index: 3; background-image: linear-gradient(white, transparent, transparent)[ ](#" style=" opacity: 60%; padding: 10px 0px; margin-top: -5px; display: block; width: $[[17]]%;  position: absolute; left: 0px; z-index: 3; background-image: linear-gradient(to bottom left, white, transparent, transparent, transparent)[ ](#" style=" border-left: 4px ridge lightgrey; border-right: 4px ridge lightgrey; padding: 10px 0px; margin-top: -5px; display: block; position: absolute; left: 0px; right: 0px; z-index: 3; background-color: transparent)[@{hp}/@{Cinematic Weight|hp}](#" style=" cursor: default; text-decoration: none; color: white; background-color: transparent; padding: 6px 0px 3px 5px; margin-top: -8px; display: block; width: 110%;  position: absolute; left: 0px; z-index: 4)[ ](#" style=" cursor: pointer; opacity: 0%; padding: 10px 0px 12px; margin-top: -5px; display: block; width: 110%;  position: absolute; left: 0px; z-index: 5)}}$[[1]] $[[7]] $[[11]] $[[18]] $[[19]] $[[12]] $[[13]] $[[14]] $[[15]] $[[16]] $[[17]] opacity1_1[[  [[@{hp}/@{Cinematic Weight|hp}*200*[[{@{bars}-@{atrtag}|bars|max}+1,0}kh1]]]] ]] opacity2_7[[  [[[[@{hp}/@{Cinematic Weight|hp}*200]]*[[floor(1/[[abs([[[[@{bars}-@{atrtag}|bars|max}]]+1]])+1]])]]]] ]] opacity3_11[[ [[[[@{hp}/@{Cinematic Weight|hp}*200]]*[[floor([[abs(@{bars}-@{atrtag}|bars|max})]]/2)]]]] ]] width_12[[ [[@{hp}/@{Cinematic Weight|hp}*100]] ]] width_13[[ [[@{hp}/@{Cinematic Weight|hp}*100]] ]] width_14[[ [[@{hp}/@{Cinematic Weight|hp}*100]] ]] width_15[[ [[@{hp}/@{Cinematic Weight|hp}*100]] ]] width_16[[ [[@{hp}/@{Cinematic Weight|hp}*100]] ]] width_17[[ [[@{hp}/@{Cinematic Weight|hp}*100]] ]] yellow_backbar_18[[ [[{@{bars}-@{atrtag}|bars|max}+1,0}kh1*{@{bars}-1,1}kl1*100]] ]] orange_backbar_19[[ [[{@{atrtag}|bars|max}-2,1}kl1*{@{bars}-1,1}kl1*100]] ]] inverse-width_20[[ [[99-@{hp}/@{Cinematic Weight|hp}*100]] inverse-width_21[[ [[99-@{hp}/@{Cinematic Weight|hp}*100]]
1721753692
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
That could make for a very nice party readout for a healer character. Very impressive!