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 .
×
Advertisement Create a free account

Custom Roll Parsing for Character Sheets and RoleMaster d100OE Downrolls

1628181469

Edited 1628184218
Pantsworth
Pro
Sheet Author
I THINK the new Custom Roll Parsing for Character Sheets will now allow me to do a proper downroll as seen in RoleMaster d100OE rolls.  However, I can not really parse how to structure this. The basic structure for the roll I am modeling is an "if-then" die roll.  You roll a d100!>95 & if you roll less than 6 on this roll then subtract another d100!>95 from it.  After this is done, add in all the other bonuses and penalties. So I am thinking <script type="text/worker">     on('clicked:test', (info) => {         startRoll("&{template:test} {{name=Test}} {{roll1=[[ 1d100!>95-1d100!>95]]}}", (results) => {             const regularroll = dice[0]             const downroll = result             finishRoll(                 results.rollId,                 {                     if ( regularroll < 6 )                         { roll1: downroll }                     else { roll1: regularroll } ,                 }             );         });     }); </script> What I am struggling with is: How do I add in the skill bonuses so a player can hover over and see the results in the chat window? I think it has something to do with building the button macro within a script, but I am far out to sea here.
1628217965

Edited 1628219235
Oosh
Sheet Author
When you use a computed roll, you still only get the mouseover tooltip from the original roll - So you need to have all the info you want displayed in the original template supplied to startRoll(). There's a few ways to go about it: You can construct your roll without the inline brackets so it can be printed out before it's rolled to give the players clearer info. You can also initialise a couple of inline rolls to display conditional information. You can only display your computed results in an existing inline roll, so anywhere you want to display information needs to exist as an [[inline roll]] in the startRoll() template. This approach uses two version of the roll expression - one in {{roll1name}} is not wrapped in brackets and is to display above the roll, the other, {{roll1}} is wrapped in brackets so it does the actual roll. Obviously you need to add {{roll1name}} into your roll template HTML to have it displayed. let rollExpression = `1d100!>95 + @{skill_bonus}[Bonus] + @{skill_mod}[Mod]`; // Wrap the two @{attributes} in a [[subroll]] if they're taking up too much space let rollBase = `&{template:test} {{name=Test}} {{roll1=[[${rollExpression}]]}} {{downroll=[[0]]}} {{roll1name=${rollExpression}}} {{roll1mod=- [[1d100!>95]]}} {{roll1final=[[0]]}}`; startRoll(rollbase, (results) => { let downRoll = results.roll1mod.result; let origRoll = results.roll1.result; let dieRoll = results.roll1.dice[0]; let rollData = {}; // Holding the computed data in an object is a bit cleaner if your rolls get more complex if (dieRoll < 6) { rollData.downroll = 1; // This tells the roll template to display the mod & final sections rollData.roll1final = origRoll - downRoll } finishRoll(results.rollId, rollData); }); This approach needs a little bit of work done to the roll template, namely creating the {{roll1mod}} and {{roll1final}} divs, and only displaying them when we tell it to, via setting the computed value of {{downroll}} to anything but 0. Note that even if you don't do any computation on a roll, like downroll=[[0]], the roll template still receives the original result as the computed result for the purpose of the helper functions. So trying to selectively display a section with {{#computed::downroll}} won't work - as soon as you've initialised an inline roll with any value, it exists as a computed version as well. {{#^rollTotal() computed::downroll 0}} <div class="sheet-roll1mod sheet-result"> {{computed::roll1mod}} </div> <div class="sheet-roll1final sheet-result"> {{computed::roll1mod}} </div> {{/^rollTotal() computed::downroll 0}} This will allow the roll template to only display the downroll & the modified total when the original die was less than 6, and displaying them in separate areas will prevent the issue of having a roll total which doesn't match to tooltip - basically, if you replace the original roll with the computed one, you have no way to update the tooltip info (I believe this is an intentional design choice). We're using the {{downroll}} property as a computed flag for the roll template, this part is not displayed. There's still a couple of downsides - although the downroll isn't displayed in chat unless it's computed and sent to {{roll1mod}}, you'll still get the 3d die every time. You also have the original inline value tooltip popup for your computed results (Rolling 0=0), but you can use CSS to make these looks like normal text. You can also disable the tooltip entirely with: pointer-events: none; on any computed results where you don't want it displayed. There are some more complicated ways to go about this to avoid the limitation on what you can stuff into a computed roll, but they're probably above and beyond what you need. For example, you can throw out a fake roll with an API leader, startRoll(`! {{roll=[[1d100]]}}`), grab the result (not seen in chat), then do your actual roll with a rolled value already stored as a variable in your function before you construct your real template.
1628510726

Edited 1628522386
Pantsworth
Pro
Sheet Author
OK - This is great!  Now how do I tie this into a button click? Right now I have the following: < button  type = "roll"  class = "button-roll"  name = "roll_test"  title = "perceptioncheck"  value = "[[1d100!>95]]  +[[@{perception}]] +?{Other bonus/penalty?|0} " ></ button > But that doesn't seem to work. Should I just pass through the variables, and build the roll in the javascript variable statement let rollExpression =
1628569011
Oosh
Sheet Author
You'll need to change the button to an action button: <button type="action" name="act_test">Click Me</button> and add an event listener to your code that either contains your roll function, or points to it. You'll generally want to log everything while you're testing as well. on('clicked:test', (event) => { console.log(event); testRoll(); }); const testRoll = () => { <all the startRoll() stuff goes here> }
1628586283
Andreas J.
Forum Champion
Sheet Author
Translator
<a href="https://wiki.roll20.net/Button#Roll_Parsing" rel="nofollow">https://wiki.roll20.net/Button#Roll_Parsing</a> is still very barebones, but at least the base example shows the button to be action one. I'll try to keep linking to these threads on the page so info and examples are easier to find.
1628601650
Pantsworth
Pro
Sheet Author
Oosh said: You'll need to change the button to an action button: Excellent.&nbsp; And so with the added ability to loop through the HTML attributes, I can genericise the rolls by building a string from the HTML to reference the correct character attribute and call the roll variables from the javascript!
1628626778

Edited 1628781134
Pantsworth
Pro
Sheet Author
Argh.&nbsp;&nbsp; I can't even see the action in the console.&nbsp; Any idea what I am doing wrong here? Button: &lt;button type="action" name="act_test" class="button-roll"&gt;Percep&lt;/button&gt; Script Worker: &lt;script type="text/worker"&gt; on('clicked:test', (event) =&gt; { console.log("In Clicked Test"); //this does not get logged &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(event); //this does not get logged testRoll(); //this does not fire }); const testRoll = () =&gt; { let rollExpression = '1d100!&gt;95'; //+ @{perception}&nbsp;+?{Other&nbsp;bonus/penalty?|0} // + @{skill_bonus}[Bonus] + @{skill_mod}[Mod]'; // Wrap the two @{attributes} in a [[subroll]] if they're taking up too much space let rollBase = '&amp;{template:test} {{name=Test}} {{roll1=[[${rollExpression}]]}} {{downroll=[[0]]}} {{roll1name=${rollExpression}}} {{roll1mod=- [[1d100!&gt;95]]}} {{roll1final=[[0]]}}'; startRoll(rollbase, (results) =&gt; { let downRoll = results.roll1mod.result; let origRoll = results.roll1.result; let dieRoll = results.roll1.dice[0]; let rollData = {}; // Holding the computed data in an object is a bit cleaner if your rolls get more complex if (dieRoll &lt; 6) { rollData.downroll = 1; // This tells the roll template to display the mod &amp; final sections rollData.roll1final = origRoll - downRoll } finishRoll(results.rollId, rollData); }); } //Other scripts go here &lt;/script&gt; Any idea on what I may have done (or not done)?
1628781113
Pantsworth
Pro
Sheet Author
Update: It seems no events are firing, so I think I will start a new thread to investigate this.
1628785284
GiGs
Pro
Sheet Author
API Scripter
If no events are firing, remove all other sheet workers and test with just this one, and see if your log fires. It's possible an error in one of your sheet workers is crashing the entire sheet worker sandbox. Also is the above worker in a repeating section? If so you need a different syntax.
1628951526
Pantsworth
Pro
Sheet Author
It is a shame you can't add (or delete) a die from a roll, and change the expression when you do.&nbsp; It would make this much easier.
1628952125

Edited 1628952761
Pantsworth
Pro
Sheet Author
Anyway, here is the code I ended up with: &lt;script type="text/worker"&gt; // A Big thanks to GiGs for lots of help on streamlining the Sheetworkers!!!! const int = (value, error = 0) =&gt; parseInt(value) || 0; const float = (value, error = 0) =&gt; parseFloat(value) || 0; on('clicked:test', (info) =&gt; { testRoll(info.htmlAttributes.title); }); const testRoll = (skillname) =&gt; { let rollExpression = '1d100!&gt;96cf&lt;5cs&gt;96'; let rollmodifiers = '@{skillname}'; rollExpression = rollExpression + ' + ' + rollmodifiers //+ '[TotalBonus]' console.log(rollmodifiers); // Wrap the two @{attributes} in a [[subroll]] if they're taking up too much space let rollBase = '&amp;{template:RmuStdRolltest} {{roll1=[['+ rollExpression +']]}} {{isdownroll=[[0]]}} {{name=@{character_name}\'s&nbsp;skillname check}} {{skillflag=true}} {{check= skillname (@{skillnameranks}&nbsp;ranks):&nbsp;}} {{roll1name=${rollExpression}}} {{roll1mod=[[(1d100!&gt;95cf&lt;101cs=0)]]}} {{roll1final=[[0]]}}'; rollBase = rollBase.replace(/skillname/g, skillname) console.log(rollBase); startRoll(rollBase, (results) =&gt; { let downRoll = results.results.roll1mod.result; let origRoll = results.results.roll1.result; let dieRoll = results.results.roll1.dice[0]; console.log(dieRoll); let rollData = results.results; // Holding the computed data in an object is a bit cleaner if your rolls get more complex rollData = Object.assign(results); if (dieRoll &lt; 6) { rollData.isdownroll = 1; // This tells the roll template to display the mod &amp; final sections rollData.roll1final = origRoll - downRoll; console.log('Roll Final With Downroll: ' + rollData.roll1final); } finishRoll(results.rollId, rollData); }); } This will do quite well for now - and is tantalizing close to what I want.&nbsp; Thanks for all the help.
1628956917
GiGs
Pro
Sheet Author
API Scripter
It is possible to grab attributes from a sheet, and you have some ability to modify the expression. Imagine you could do anything you wanted - how would you want it to work? How should the expression change and what do you need an extra roll to do?
1628965682

Edited 1628967457
Pantsworth
Pro
Sheet Author
Well.&nbsp; I guess I am assuming that changing the expression would change the hover over the die roll aspect in chat.&nbsp; Is that true? If it is, then what would be perfect is the expression would in an array, and a trait of the die roll.&nbsp; That way deleting (or adding) a die would change the expression, and therefore the chat tooltip display.&nbsp; Possibly this is what Oosh was hinting at when he talked about a 'fake roll with an API leader'.&nbsp; In this way, I could do something like this (not complete code): let rollExpression = '1d100!&gt;96cf&lt;5cs&gt;96'; let rollmodifiers = '@{skillname}'; rollExpression = rollExpression + ' + ' + rollmodifiers let rollBase = '&amp;{template:RmuStdRolltest} {{roll1=[['+ rollExpression +']] - [[1d100!&gt;96]]}} {{isdownroll=[[0]]}} {{name=@{character_name}\'s&nbsp;skillname check}} {{skillflag=true}} {{check= skillname (@{skillnameranks}&nbsp;ranks):&nbsp;}} {{roll1name=${rollExpression}}} {{roll1mod=[[(1d100!&gt;95cf&lt;101cs=0)]]}} {{roll1final=[[0]]}}'; rollBase = rollBase.replace(/skillname/g, skillname) startRoll(rollBase, (results) =&gt; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//Cut out not relevant code let dieRoll = results.results.roll1.dice[0]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//current expression is something like: 1d100!&gt;96cf&lt;5cs&gt;96 + 25 - 1d100!&gt;95 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//also hover tool tip should read something like: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 1d100!&gt;96cf&lt;5cs&gt;96 + 25 - 1d100!&gt;95 = &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 1) (3) + 25 - 46 for a downroll &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 2) (96+57) + 25 - 46 for an uproll &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 3) (51) + 25 - 46 for a non exploding roll if (dieRoll &gt; 5) { results.results.roll1.dice.splice(2, 1) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//expression should now read: 1d100!&gt;96cf&lt;5cs&gt;96 + 25 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//also hover tool tip should read something like: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 1d100!&gt;96cf&lt;5cs&gt;96 + 25 - 1d100!&gt;95 = &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 1) (3) + 25 - 46 for a downroll (note you should not get here for a downroll) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 2) (96+57) + 25 for an uproll &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 3) (51) + 25 for a non exploding roll } finishRoll(results.rollId, results); }); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//To be 100% consistent, ideally the rolls would read like this: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 1) (3-46) + 25 for a downroll &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 2) (96+57) + 25 for an uproll &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// 3) (51) + 25 for a non exploding roll &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//But I get that won't change unless they add to the dice roll functionality. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
1628966934
GiGs
Pro
Sheet Author
API Scripter
Forget about the code. Describe how you would want to work in English, if we were playing at the table, without using code.
1628968673

Edited 1628968802
Pantsworth
Pro
Sheet Author
It would handle a die roll where you can roll down or roll up, and add in all the relevant bonuses from stats, skills, external effects, and (potentially) opponent's defenses and armor.&nbsp; Furthermore, you could hover over the dice results and get a complete breakdown of all the parts of your roll, including the downroll portion added in and displayed as part of the initial downroll. So I would see something like this on a skill that has an item bonus: For a downroll (lets say where they rolled high enough on the downroll to roll again so a 3, then a 96, and then 14): Pat's&nbsp;perception check: -65&nbsp; a mouseover the -65 would display 1d100!&gt;96* + 32 + 10 = (3-(96+14)) + 32 [skill bonus] + 10 [Item Bonus] For an uproll: Pat's&nbsp;perception check: 167 a mouseover the 167 would display 1d100!&gt;96* + 32 + 10 = (100+25) + 32 [skill bonus] + 10 [Item Bonus] For a non exploding roll: Pat's&nbsp;perception check: 119&nbsp; a mouseover the 119 would display 1d100!&gt;96* + 32 + 10 = 77+ 32 [skill bonus] + 10 [Item Bonus] *Probably not what the dice roll expression would be, but I will use it as a placeholder for now Also there would be more whistles and bells to the template, but they are not relevant for this discussion.