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

Script to retry roll

Sheet Author
Hello everyone, I try to write a script that rolls to pair of dice and checks if the first pair has more hits then the second. It should reroll until that happens and count the amount of tries. const rollAcq = (values) => {                 if(values.item == undefined || values.player == undefined){             sendChat(`Script`, Missing values`, null, {noarchive: true});         }         else {             values.tries += 1;             sendChat(`Script`, `[[ [[${values.player}d6>5sd!]]-[[${values.item}d6>5sd]] ]]`, function(result){                             let nethits = -1;                 sendChat(`Script`, `${result}`, null, {noarchive: true});                 if(values.result != undefined) {                     nethits = result[0].inlinerolls[0].results.rolls[0].results;                 }                             sendChat(`Script`, `${values.item} ${values.player} ${values.value} ${values.tries} ${values.result}`, null, {noarchive: true});                 if(nethits > -1) {                     let newMsg = 'Nach ' + values.tries + ' triesn wurden ' + nethits + ' nethits erzielt';                     sendChat(`Script`, `${newMsg}`, null, {noarchive: false});                 }                 else {                     rollAcq(values);                 }                         }, {noarchive: true})             return;         } With this code I get errors due to stack size. Anyone an idea what I did wrong? Or how to do it the right way? Thanks
API Scripter
You have a couple of things going wrong, there... though you don't show us how you call this function, so I can't be sure about some of them. First, you're missing the opening tick mark before Missing values in line 4. You're also missing the closing bracket, but I figure that was just a problem of copy/pasting and not getting it from your editor. Also, instead of the approximate-equality test for undefined, I would suggest doing a full equality check with a typeof argument everywhere you have it... so not: if(values.result != undefined) ...but... if(typeof values.result !== 'undefined') But the real kicker (and why you're getting the stack size error) is that you're calling this recursively (which is building the stack), but never letting it do anything OTHER than calling itself: You test values.result for undefined, but you never set values.result to anything...                 if(values.result != undefined) {                     nethits = result[0].inlinerolls[0].results.rolls[0].results;                 } If values.result IS undefined (which I'm assuming it starts at), then nethits will never have a new value assigned to it... meaning it will always stay -1, and you will call this function to create another recursion layer. Last, this is a preference thing... but I wouldn't want a bunch of intermediate messages (you're sending messages every recursion). I would much prefer just tracking the inlinerolls in the values object, then giving me all of the data once the conditions are satisfied and the recursion stops. That would look more like... const rollAcq = (values) => { //eslint-disable-line no-unused-vars     if (typeof values.item === 'undefined' || typeof values.player === 'undefined') {         sendChat(`Script`, `Missing values`, null, { noarchive: true });     } else {         sendChat(`Script`, `[[[[${values.player}d6 > 5sd!]] - [[${values.item}d6 > 5sd]]]]`, function (result) {             values.vallog = values.vallog || [];             values.vallog.push(result[0].inlinerolls);             if (parseInt(result[0].inlinerolls[2] <= 0) {                 setTimeout(rollAcq,0,values);                 return;             }             let rollReport;             if (libInline) {                 rollReport = => {                     let parsedrolls = libInline.getRollData(rolls);                     return `${parsedrolls[0].getRollTip()} - ${parsedrolls[1].getRollTip()} = ${parsedrolls[2].getRollTip()}`;                 });             } else {                 rollReport = => {                     return `${rolls[0]} - ${rolls[1]} = ${rolls[2]}`;                 });             }             let newMsg = `Nach ${values.vallog.length} triesn wurden ${result[0].inlinerolls[2]} nethits erzielt. Alle versuche:<br><br>${rollReport.join('<br>')}`;             newMsg += `<br><br>Item: ${values.item}, Player: ${values.player}`             sendChat(`Script`, `${newMsg}`, null, { noarchive: false });         }, { noarchive: true });         return;     } } You would have to call that with an initial object of something like {item: 3, player: 3}... but that will work. I leaned on libInline to get some nice hover tip output... you can install it from the one-click if you want that, too.
Sheet Author
The inline rolls every recursion was just for debugging purposes. The only message send in the end should be the newMsg. The call is filled with data parsed from the api command         const handleInput = (msg) => {         if (msg.type !== "api") {             return;         }                  let args = msg.content.split(/\s+/);                 if(args.shift() === '!acq'){             let values = {};             values.item = args[0];             values.player = args[1];             values.value = args[2];             values.tries = 0;             values.nethits = -1;             rollAcq(values)         }     }; I try to get your code snippet to run without libInline. Thanks