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

ReferenceError: Can't find variable: randomInteger

Hi,  I can't get randomInteger() to work. I need an array of 5d20. When I run the code I get the message on console: ReferenceError: Can't find variable: randomInteger any suggestions how to fix it? var d20 = [randomInteger(20), randomInteger(20), randomInteger(20), randomInteger(20), randomInteger(20)];
1642200998

Edited 1642201066
Finds
API Scripter
I don't think a function can execute inside of an array (stop me if I'm wrong), if you defined the rolls outside the array like var a = randomInteger(20); and so on then build the array var d20 = [a,b,c,d,e]; it should work. You can call functions that are stored in an array but not with the inputs inside the array so that's not really helpful for you.
1642201172

Edited 1642201214
Which console are you running that in? randomInteger() is an API function so must be in an API script; it won't work from the web browser console.
Finds said: I don't think a function can execute inside of an array (stop me if I'm wrong), if you defined the rolls outside the array like var a = randomInteger(20); and so on then build the array var d20 = [a,b,c,d,e]; it should work. You can call functions that are stored in an array but not with the inputs inside the array so that's not really helpful for you. I tried outside an array, and still does not work. Jim R. said: Which console are you running that in? randomInteger() is an API function so must be in an API script; it won't work from the web browser console. How can I trigger a function on the API by clicking in a button? On the HTML I have: < script type = "text/worker" > on("clicked:roll_dice", function() {
Ah a sheet worker. According to this thread randomInteger() doesn't work in sheet workers, but Math.random() does. Not sure if that's still the case, might want to ask over in the Character Sheets & Compendium forum, or maybe someone else will confirm.
Jim R. said: Ah a sheet worker. According to this thread randomInteger() doesn't work in sheet workers, but Math.random() does. Not sure if that's still the case, might want to ask over in the Character Sheets & Compendium forum, or maybe someone else will confirm. How can a code everything on the api and just call the function when a button is pressed?
1642218754

Edited 1642219078
Oosh
Sheet Author
API Scripter
Is there any particular reason for using randomInteger, out of interest? It doesn't use the Quantum roll server, it's just uses the vanilla JS Math library to generate a number. I honestly don't know enough math to have any idea if the Roll20 one is any better than just calling Math.random(), but they look reasonably similar to me. Math.random(): function random () {   // Closure to return a random double:   var n = arc4 . g ( chunks );             // Start with a numerator n < 2 ^ 48   var d = startdenom ;                 //   and denominator d = 2 ^ 48.   var x = 0 ;                           //   and no 'extra last byte'.   while ( n < significance ) {           // Fill up all significant digits by     n = ( n + x ) * width ;               //   shifting numerator and     d *= width ;                       //   denominator and generating a     x = arc4 . g ( 1 );                     //   new least-significant-byte.   }   while ( n >= overflow ) {             // To avoid rounding up, before adding     n /= 2 ;                           //   last byte, shift everything     d /= 2 ;                           //   right using integer math until     x >>>= 1 ;                         //   we have exactly the desired bits.   }   return ( n + x ) / d ;                 // Form the number within [0, 1). } ...and the function called by Roll20's randomInteger: function randomInt ( n ) {         if ( n < 0 ) {     throw \ "n must be non-negative \"   }   // Determine the number of counts needed to generate a the number, minimum is 1   var counts = Math . max ( Math . ceil ( Math . log ( n ) / Math . log ( width )), 1 );     // If counts is greater than 6 then maxRand is greater than 2^53 which is the   // largest safe int in JavaScript. This library cannot generate random ints larger   // than width^chunks   if ( counts > chunks ) {     throw \ "n cannot be greater than \" + width + \" ^ \" + chunks ;   }   // Calculate the maximum random number possible for the counts   var maxRnd = Math . pow ( width , counts );       // Calculate the maximum valid random number to prevent uneven distribution       var maxValid = n * Math . floor ( maxRnd / n );   var rnd ;   var pass = 0 ;   do {       rnd = arc4 . g ( counts );       pass ++;   } while ( rnd >= maxValid && pass < 100 );     // Ignore numbers that are outside of the valid range     return rnd % n ; } You may as well just roll your own from Math.random(), rather than make your sheet dependent on an API function for the sake of one line of code. You can even throw a default range variable in for bonus points, if you're usually rolling a d20: const randomInteger = ( range = 20 ) => ( range > 0 ) ? Math . ceil ( Math . random ()* range ) : null ; Someone with some proper math knowledge might be able to suggest whether the randomInt() function is significantly better than Math.random() - if it is, you can just substitute it for the Math.random() call. If you're looking to use the Quantum roller, you'll need to activate it from chat with a [[1d20]] or with Custom Roll Parsing. You could use the API instead via sendChat(), it's just the long way around from the sheet sandbox, and again, means your sheet won't work without the API.
1642221958
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Jonny, perhaps if you explained what exactly you're trying to do? Building a sheet that relies on API scripts is generally a bad idea, and with the advent of custom roll parsing there's very little on the character sheet itself that you need an API for. From the basic code you've shared, I'm guessing you want your sheet to roll several d20's and do something with those results. This is pretty much exactly what CRP is for: <button type='action' name='act_roll'></button> <rolltemplate class="sheet-rolltemplate-test"> <div> {{roll1}} => {{computed::roll1}} {{roll2}} => {{computed::roll2}} {{roll3}} => {{computed::roll3}} {{roll4}} => {{computed::roll4}} {{roll5}} => {{computed::roll5}} </div> </rolltemplate> <script type='text/javascript'> const intiateRoll = async function(event){ let roll = await startRoll(`&{template:test} ${_.range(5).map((n)=>`{{roll${n+1}=[[1d20]]}}`)}`); const computedObj = {}; _.range(5).forEach((n)=>computedObj[`roll${n+1}`] = roll.results[`roll${n+1}`].result / 2); //Can also do things with these results like store them in the sheet or modify attributes based on their rolls finishRoll(roll.rollId,computedObj); }; on('clicked:roll',initiatieRoll); </script> Bonus here is you get to use the quantum roll random number generator which is quite a bit better than basic JS RNG.
Thank you Scott and Oosh I had everything as a sheetwork, but then I could not send messages to chat. So I migrated everything to the API. I figure a way for a button to trigger the API. Scott C. said: Jonny, perhaps if you explained what exactly you're trying to do? Building a sheet that relies on API scripts is generally a bad idea, and with the advent of custom roll parsing there's very little on the character sheet itself that you need an API for. From the basic code you've shared, I'm guessing you want your sheet to roll several d20's and do something with those results. This is pretty much exactly what CRP is for: <button type='action' name='act_roll'></button> <rolltemplate class="sheet-rolltemplate-test"> <div> {{roll1}} => {{computed::roll1}} {{roll2}} => {{computed::roll2}} {{roll3}} => {{computed::roll3}} {{roll4}} => {{computed::roll4}} {{roll5}} => {{computed::roll5}} </div> </rolltemplate> <script type='text/javascript'> const intiateRoll = async function(event){ let roll = await startRoll(`&{template:test} ${_.range(5).map((n)=>`{{roll${n+1}=[[1d20]]}}`)}`); const computedObj = {}; _.range(5).forEach((n)=>computedObj[`roll${n+1}`] = roll.results[`roll${n+1}`].result / 2); //Can also do things with these results like store them in the sheet or modify attributes based on their rolls finishRoll(roll.rollId,computedObj); }; on('clicked:roll',initiatieRoll); </script> Bonus here is you get to use the quantum roll random number generator which is quite a bit better than basic JS RNG. Why it is not a good practice to use API? And how can I send chat message from the character sheet? Thank you all.
1642304013

Edited 1642304088
GiGs
Pro
Sheet Author
API Scripter
It's not good practice to use the API, because then only GMs who have Pro subscriptions can use the sheet. And that's a very small number. (If the sheet's just for your use, then that doesn't matter, and the API is fine to use.) Regarding sending a chat message: startRoll lets you take a message (which can include queries) and finishRoll sends it to a rolltemplate, which then prints to chat. Scott's code should do what you asked - if there's more you need the worker to do, you need to describe it fully.
1642308423

Edited 1642308567
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Yep, as GiGs said. That code should demo the basic premise you had in your OP code. I wrote it in a rush and forgot to comment with explanations. Here's that code with those explanations: <button type='action' name='act_roll'></button><!-- Our Action button to trigger the roll --> <rolltemplate class="sheet-rolltemplate-test"><!-- A very generic roll template that is barebones for showing how CRP works --> <div> {{roll1}} => {{computed::roll1}} {{roll2}} => {{computed::roll2}} {{roll3}} => {{computed::roll3}} {{roll4}} => {{computed::roll4}} {{roll5}} => {{computed::roll5}} </div> </rolltemplate> <script type='text/worker'><!-- Note that I had erroneously put text/javascript here in the original copy. It should be text/worker . const intiateRoll = async function(event){//Note this is an async function. MDN has a great outline of what you can do with async/await, but we're going to be doing very barebones stuff with it let roll = await startRoll(`&{template:test} ${_.range(5).map((n)=>`{{roll${n+1}=[[1d20]]}}`)}`);//Send our roll to chat. The _.range(5).map stuff is just so I didn't have to write out each roll separately. Note that we tell JS to "await" the result of startRoll. The function will pause while startRoll resolves const computedObj = {};//An object to store our modifications to the rolls in. Note you can only modify fields that 1) existed in the original message and 2) already had a roll in them _.range(5).forEach((n)=>computedObj[`roll${n+1}`] = roll.results[`roll${n+1}`].result / 2);//A random math operation on our rolls to show what the modified output looks like //Can also do things with these results like store them in the sheet or modify attributes based on their rolls finishRoll(roll.rollId,computedObj);//Complete the roll and apply our modifications to the results which will show up in the computed:: fields. Note that if your script takes longer than 5 seconds before calling finishRoll, the roll will be resolved using the original roll values. This is orders of magnitude more time than should be needed. }; on('clicked:roll',initiatieRoll);// Our listener for when our action button gets clicked. It calls the above function </script>