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

Proper Roll Evaluation on a Custom Sheet

Good morning! I'm not sure exactly what to type in the search bar for this, so I'll go ahead and just lay out what I'm looking at with my custom sheet. Just this month (December 2022) Mongoose sent out their PDF rulebook for Paranoia: Perfect Edition. I've been building a character sheet to accommodate these new rules, as they adapt pretty easily from their previously published Red Clearance Edition. I have a mostly functional sheet right now, but I'm struggling with getting my rolls to evaluate in a way that produces proper results for a negative NODE. For context, in Paranoia Perfect and Red Clearance Editions, a NODE is "Number Of DicE" rolled, which is derived from adding together a stat and a skill for a total NODE. In this case, I've got the roll set up to add the stat and the skill plus relevant modifiers (a custom number input plus wounds) to determine the total NODE. But between having negative stats, skills, and wound penalties, sometimes a NODE can end up negative. Now, it would be a simple thing to state that there must be a minimum of one dice rolled, but that isn't the case for Paranoia when it comes to negative NODEs. RAW, when a negative NODE is rolled, a player rolls the absolute value of their NODE, and any rolls that aren't successes subtract from the total number of successes (eg. if the NODE is -3, a player rolls 3 dice; their results are 5, 6, and 3, so they end up getting 1 success because the 3 removes one of the three successes they'd otherwise generate). There's an additional fiddly bit with the computer dice, but that doesn't actually factor into this problem so I'm not going to go over it. The computer dice is working perfectly (as it should, since it comes directly from Your Friend the Computer). Here's my dice rolling button right now: <button type="roll" value="\n **NODE Successes:** [[(@{skillpick} + @{statpick} + @{wounds} + @{modifier})d6>5 &noerror]]\n **Computer Dice:** [[1d6>@{flags} &noerror]]" name="roll_NODE"></button> Full code can be found in the github repository here . When I try to extract absolute values or use a minimum evaluator in this line, the roller breaks entirely. I would appreciate some assistance with this if there's any to be had. Thank you and happy holidays!
1671652556

Edited 1671652781
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
I don't think you're going to be able to do this with basic roll buttons. You could do it with custom roll parsing  in a sheetworker (aka javascript). Something like this: <input type="number" name="attr_sleight_of_hand"> <input type="number" name="attr_strength"> <select name="attr_skill_pick"><!-- Using snake_case as it is easier to read than nocase --> <!-- Note that the values of these selects are equal to the attribute names of the skill/stat --> <option value="sleight_of_hand" selected>Sleight of Hand</option> </select><select name="attr_stat_pick"> <option value="strength" selected>Strength</option> </select> <input type="number" name="attr_wounds"> <input type="number" name="attr_modifier"> <input type="number" name="attr_flags"> <button type="action" name="act_node">Roll NODE</button> <rolltemplate class="sheet-rolltemplate-paranoia"> <h2>{{skill}}</h2> <h2>{{stat}}</h2> <span> <h3>NODE</h3> <span>{{computed::node}}</span> </span> <span> <h3>computer</h3> <span>{{computer}}</span> </span> </rolltemplate> <script type="text/javascript"> // A list of the skills that can be selected for use in our javascript const skills = ['sleight_of_hand']; // A list of the stats that can be selected for use in our javascript const stats = ['strength']; // listen for someone to click on the action button on('clicked:node',()=>{ // get the attribute values for all of the attributes we might possibly need getAttrs([...skills,...stats,'wounds','modifier','stat_pick','skill_pick','flags'],async (attributes) => { // The async keyword above tells javascript that we will be pausing execution of this code to wait on something that may take some time (the startRoll function). // Convert the skill/stat values to numbers const skillValue = +attributes[attributes.skill_pick] || 0; const statValue = +attributes[attributes.stat_pick] || 0; // calculate the total dice that should be rolled const totalDice = skillValue + statValue + (+attributes.wounds || 0) + (+attributes.modifier || 0); // convert the dice number to a positive number of dice const actualDice = Math.abs(totalDice); // assemble our roll message. Note that CRP requires that you use a roll template. const message = `&{template:paranoia} {{skill=${attributes.skill_pick}}} {{stat=${attributes.stat_pick}}} {{node=[[${actualDice}d6]]}} {{computer=[[1d6>${attributes.flags || 0}]]}}`; // Send the roll const roll = await startRoll(message); // an object that we'll accumulate our modifications to the roll results in. const computeObj = {}; // calculate the number of successes including for if there are negative dice computeObj.node = roll.results.node.dice.reduce((successes,die) => { if(die < 5 && totalDice < 0){ successes--; }else if(die >= 5){ successes++; } return successes; },0); // Tell roll20 to release the roll to chat with our modified results. finishRoll(roll.rollId,computeObj); }); }) </script> Not sure what paranoia's skills/stats are so I just put some generic ones in for testing.
Wow, I really appreciate that! I didn't understand exactly what sheetworkers is but now I know what it can be used for that gives me enough context to put this advice to use after reading the documentation. Thank you so much for the quick reply!