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 .
×

Processing Die Rolls in A Mod - I May Have Written Myself into a Corner

1779930421

Edited 1779930466
This is for AD&D 1e, but the buttons I want to click on are for processing, hopefully, a die roll. If successful, I'd like to roll other dice. I'm not sure the lengthy script I've written needs to be listed here, but it does - so far - produce the black background Turn Undead chat shown here after clicking the Undead Button in the previous chat result.  I'm not sure I can do what I described above. Derp on me. A little more detail follows after the screenshot. Yes, this is for turning undead. Yes, the character sheet for AD&D 1e can handle this, but I'm not comfortable with how it works (it rolls the turning dice and the effects if successful all at once).  Most importantly, some of my players are dumb as ditch dirt (dear old friends from as far back as the 60s and 70s). :-) What I'm trying to do with the buttons that have a number instead of T or D, is to have the Mod I am working on roll a d20 if clicked. If the result is equal to or greater than the number showing on the button, I'd like to indicate success on a further chat that then rolls both a d12 (for number of the undead type affected) and 3d4 (for the number of minutes or rounds the the turning lasts). If the roll is less than the number indicated on the button, I want to indicate failure to turn the indicated undead. I'm not sure I can do this in a Mod. Oh dear. Any hints? Thanks for any help or a straight out blowing away any expectation of doing this. I'd like to stay away from ScriptCards (which I have as one of the scripts in this game), if possible,  because I don't know how to make a scriptCard in anything but a macro.
1779936137
timmaugh
Pro
API Scripter
It's all good, Tim. You've got plenty of room to do what you want to do. To be clear, though, when you speak of "script" I am understanding you to have written some amount of javascript code that you are invoking by some text handle through chat. For instance: !thereAreSomeWhoCallMe_Mod If that's the case, then your mod script has already built the above panel... which means that it knows the value of each of the undead types (like that "Vampire" is a 4). Now, while you can do this with ScriptCards or metascripts through chat, you indicated that you wanted to do this in your script, so let's stay there. Also, a script cannot generate the 3D dice on the game board, so you don't *have* to do it as a die roll (you can call the randomInteger() function with the size of die you want to roll: randomInteger(20) ...and assign it to a variable you use for your calculations. But you said "script" and you said "roll", so let's do it. There are two things you have to do to handle the dice you roll: locate the roll in your command line extract the value from the inline roll If you already know how to do the former, skip to the section on the latter. Locating the Roll What you're going to want is a way to break your command line down so you can read the various data components. Once you have that, you can construct the command line of the buttons so that they will send an appropriately formatted message. While you could format your command line however makes sense to you (you just have to be able to "encode" AND "decode" it, or "build" and "read" it), it really comes down to a handful of levers you can pull, in this case... something like: !undeadify --Vampire --[[1d20]] !undeadify --type=Vampire --roll=[[1d20]] !undeadify --type=Vampire --target=4 --roll=[[1d20]] The data is divided to segments separated by "white space plus a double hyphen". That let's us split the command line to read the data. After that, it's a matter of answering questions: Is the line going to ALWAYS be built the same (that is, will it only ever be run from your menu, built by your script, so you know the order of arguments will never change)? Is the target number for the undead type ALWAYS going to be the same? Or is it generated by some in-game effect (ie, this time the Vampire target might be 4, but next time it might be 5, or 8)? What other command pathways are you going to have to handle beyond this success check? (For instance, would there be a follow up menu with more buttons to click depending on situation?) Just for demonstration, let's say that your answer to #1 is YES (your command line will always be constructed the same way), and the answer to #2 is also YES/FIXED (a fixed value that is the same every time you roll against a Vampire type). Since you mentioned that the further roll of the 1d12 and the 3d4 should be automatic based on success of the first 1d20, I'm not seeing that as another button that the user has to click, so for now the answer to #3 is NA (there are no other commands you have to handle). That means that your command line can be the simplest (the one at the top): !undeadify --Vampire --[[1d20]] Importantly, your script is going to see that as referring to data: !handle --undeadType --checkRoll So now you can split the line on the white-space-double-hyphen, and reference the parts as necessary: let args = msg.content.split(/\s*--/); // args[0] is the "handle": !undeadify // args[1] is the "undeadType": Vampire // args[2] is the "checkRoll": $[[0]] Alternatively, this is functionally the same, but gives you named variables for the parts: let [handle, undeadType, checkRoll] = msg.content.split(/\s*--/); // handle: !undeadify // undeadType: Vampire // checkRoll: $[[0]] Extract the Value from the Roll If you can locate the roll in your command line, you're halfway there. Now you have to extract the value. There are a couple of ways to do that. First, some verbiage. The roll is implemented above (ie, [[1d20]] ) is an inline roll . When it goes through the Roll20 parsers, you're left with a roll marker , which is a formation like: $[[0]] ...where the number between the double brackets is the roll index . All of the data for an inline roll (as long as your not using a beacon sheet like the 2024 sheet) is on the message object in the inlinerolls property. The property contains an array where each roll is ordered according to its roll index (so $[[0]] refers to the first roll in the array, $[[1]] refers to the second, etc.). All of the roll data is there, but it's a bit... "WHERE'S THE SOIL?!" It's a bit everywhere. So your first option is to process the rolls in the command line down to their values right in the command line... If the d20 rolled a 14 and was assigned the roll index of 0 (the first roll), then processing the rolls in the command line would replace every instance of $[[0]] with 14. Then, when you went to parse the line and retrieve the "checkRoll" value (the result of the d20 roll), the text would already have been changed to be 14 rather than $[[0]]. The Aaron shared a code snippet that does that. He might have updated it from this version (to handle extended edge cases), but for what you're doing, this will work: const escapeRegExp = (string) => { return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); }; const processInlinerolls = (msg) => {   if (msg.inlinerolls && msg.inlinerolls.length) {     return msg.inlinerolls       .reduce((m, v, k) => {         let ti = v.results.rolls.reduce((m2, v2) => {           if (v2.hasOwnProperty('table')) {             m2.push(v2.results.reduce((m3, v3) => [...m3, (v3.tableItem || {}).name], []).join(", "));           }           return m2;         }, []).join(', ');         return [...m, { k: `$[[${k}]]`, v: (ti.length && ti) || v.results.total || 0 }];       }, [])         .reduce((m, o) => m.replace(new RegExp(escapeRegExp(o.k), 'g'), o.v), msg.content);   } else {     return msg.content;   } }; The processInlineRolls function takes the message object, and returns the modified command line string with the values from the dice swapped into their places. That means you can swap it into your line parsing: let args = processInlineRolls(msg).split(/\s*--/); ...OR... let [handle, undeadType, checkRoll] = processInlineRolls(msg).split(/\s*--/); ...and now wherever you would refer to the roll, you are no longer reading the roll marker ($[[0]]), you are reading the value of the roll. Your other option for getting the data from the roll would be to use something like libInline (a library script you can install and reference as a dependency). That option does make for simpler code, but it's a bit like bringing a nuke to a knife fight, for this application, so I'll just include the link to the original write up of its usage and let you decide what you want to do. Post back if any of this isn't clear or you have more questions.
1779940921

Edited 1779941022
Gauss
Forum Champion
I am a little unclear as to why this needs a mod. Couldn't this be done with templated rolls? A success/failure check can be used to zero out the effects if successful after the turn check.  Example (not accurate, just an example):  &{template:default} {{name=Test}} [[[[[[1d20]]>11]]*2d6]] {{Check=$[[0]]}} {{Effect=$[[2]]}} It will display the d20 roll, then it will display either a 0 (failure) or the result of 2d6 (success).  Could go a step further and have a success/failure statement by using a Rollable Table. Again, this is an example, I don't fully remember the AD&D1e system for turning undead.