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

Help get die roll from API message

I made an API script for Starfinder to see what CR of creatures are shaken from Intimidate and for how long. It works fine if I call it using a number, like so: !demoralize 20 But I want to call it using a macro that rolls for me, like this: !demoralize [[1d20+@{Dave|intimidate}+?{modifier|0}]] And the script (which will be included below) is not able to find a number in this. I read that I have to use JSON.parser if the message is of the type rollresult. But it is not, the type is "api". And the parser gives an error because of the "!" it contains. (Note that I have very little experience with JavaScript and have never used JSON parser before, and don't really know how.) This is the function: on ( "chat:message" ,  function (msg) {      if  ( msg . type   ==   "api"   &&   msg . content . indexOf ( "!demoralize" )  !==   - 1 ) {          dieRoll   =   findDieRoll  ( msg . content )          sendChat  ( msg . who ,  msg . who   +   " rolled a "   +   dieRoll   +   " to demoralize." )          if  ( dieRoll < 16 ) {              sendChat  ( msg . who ,  "That's a fail." )              return         }          var   rounds   =   1 ;          var   maxCR   =   20 ;          while  ( dieRoll   >=   16 ) {              maxCR   =   Math . floor  (( dieRoll - 16 ) / 1.5 )  +   1 ;              sendChat  ( msg . who ,  "Creatures of CR **"   +   maxCR   +   "** or less are shaken for **"   +   rounds   +   "** rounds." )              dieRoll   -=   5 ;              rounds   +=   1 ;         }     } }); (The FindDieRoll function just extracts a number from a string.) log (msg.content) results in: "!demoralize $[[0]]" log (msg) results in: {"content":"!demoralize $[[0]]","inlinerolls":[{"expression":"1d20+24+0","results":{"resultType":"sum","rolls":[{"dice":1,"results":[{"v":15}],"sides":20,"type":"R"},{"expr":"+24+0","type":"M"}],"total":39,"type":"V"},"rollid":"-Md4IAIZ8K3iRf0zR-qV","signature":"46953488a84ac4845ee5661423882c62fb9e9ad565550b7b748f3cc73b0a9667552f00fabdc688ee6731b90766117d396aa2d73a1941097793bfd6747c9c3f6b"}],"playerid":"-MEtffmOWjMRieB0jFW0","type":"api","who":"Liz D. (GM)"} This is the part I seem to need: "total":39 How do I get it?
1624663353
timmaugh
Forum Champion
API Scripter
Hey Liz... welcome to the world of scripting! You don't actually need a JSON parser to get at the data... it's already in an object. You just have to know where to look. You have a couple of options: You can use the tried and true "processInlineRolls" which is discussed and broken down here . (The actual function is under the heading "As Utilized"...) It basically takes the result of the roll and subs in the value to each roll marker (ie, $[[0]]) that it finds in the command line. You can read through the explanation of the process to see where the data is in the roll and how it gets returned to the command line. Another option is the libInline library... which gives you a lot more fine control over what you return from each inline roll, but it probably overkill for your application... I just wanted to include it for completeness.
timmaugh, I confess that I did not understand the post that you linked to. However, your comment that the data was already in an object helped, and with some trial and error I realized I could get to the value I wanted with msg.inlinerolls[0].results.total. Thanks!
1624716094
timmaugh
Forum Champion
API Scripter
No worries, Liz. I'm glad you got it working. If I'd had more time when I posted, I probably could have just explained that this is the code you're looking for (taken from the link at the "As Utilized" header): msg.content = _.chain(msg.inlinerolls) .reduce(function(m,v,k){ m['$[['+k+']]']=v.results.total || 0; return m; },{}) .reduce(function(m,v,k){ return m.replace(k,v); },msg.content) .value(); If you drop that into your code, it will basically handle any number of inline rolls. For instance, right now your roll result can be found at the 0th roll, because you only have one. If someone offers an even slightly more complex roll, that can break: [[ [[1d4]]d10]] In this roll, the 1d4 will be the 0th roll, while the outside roll (the roll you're actually looking to get the result from) will be the 1st roll. The above code will take this into account, because it is basically saying "whenever I see a roll marker ($[[0]], $[[1]], etc.) in the command line (the content property), go get the value from the inlinerolls array. No matter how complex the roll is, Roll20 will only put the marker for the outside-most roll in the command line, so the above code always gets the right value to sub in. Using it can be as simple as just dropping it into the middle of your other code, then parsing your line to retrieve it: MACRO TEXT !demoralize [[1d20+@{Dave|intimidate}+?{modifier|0}]] VALUES SUPPLIED !demoralize [[1d20+5+3]] COMMAND LINE AFTER DIE ROLL !demoralize 22 Code to test/parse the line: on('ready', () => {   on("chat:message", function(msg) {     if (!(msg.type === "api" && msg.content.indexOf("!demoralize") !== -1)) return;     // command line is currently: !demoralize $[[0]]     // process inline rolls     msg.content = _.chain(msg.inlinerolls)         .reduce(function(m,v,k){             m['$[['+k+']]']=v.results.total || 0;             return m;         },{})         .reduce(function(m,v,k){             return m.replace(k,v);         },msg.content)         .value();     // command line is now !demoralize 22     [api,dieRoll] = msg.content.split(/\s+/);     // api is now !demoralize     // dieRoll is 22     // ...     // ... do things with dieRoll...     // ...   }); // end chat handler }); // end ready handler