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

Having some trouble with a rollable table

Hello everyone, so this has two questions in it. First: Is there a better way to use a rollable table other than using SendToChat? So far, that seems to be the only way I've found that works, however, it spams my chat with the rolls, which I don't want. Assuming that is true, I need some help on squelching that output. I've tried 2 different fixes. First, I've tried adding the noarchive = true option to my send to chat, however, that didn't seem to do anything. Second, I tried using a callback function with SendToChat, this is what the end result looked like, although I tried various things,such as setting, or not setting the entire statement to a variable: var results = sendChat("API", "/roll 1t[Encounter-Types]",function(ops){tableResults = ops[0];return tableResults} ); log("Encounter type is " + results) What I found is that the code block is working, as expected, and I can manipulate tableResults within that block, however the return statement isn't doing what I'm expecting of it. Any other ideas?
1560370781

Edited 1560372951
GiGs
Pro
Sheet Author
API Scripter
If youre doing some kind of tabulated data in a script, you are generally better off building the table in a data variable in the script itself. RollableTables are terrible, and limited. If you avoid them, you will avoid the sendChat problem you are having. That said, the problem you are running into is due to the asynchronous nature of scripting in an internet environment. I dont do much async scripting, so cant help you much in getting it working, but knowing the nature of the issue might help you find answers yourself. I think you need to either get the rest of the script to wait for the results of that script, or do the rest of your script inside the callback function. As I said though, you can avoid this issue by building your table in a data object inside your script, and avoiding the async function altogether. You dont need to build the table from scratch - you can grab its contents from the tables object.  To grab the table contents, first grab the table itself const table =  findObjs ({                               name: 'whatever the table is called', _type: "rollabletable" , })[0]; //findObjs returns an array: [0] ensures you grab the first (and only) table in the array Using that, you can grab all the table items: const tableItems =  findObjs ({                               _rollabletableid: table.id, _type: "tableitem" , }); You now have an array of the table item objects. Each object has a name property (the text in the table item), and a weight. If every item in your table is 1, you can convert this into a simple array like so: const tableRows = []; tableItems.forEach(item => {        tableRows.push(item.get('name')); }); this is the same as the one-liner: const tableRows = tableItems.map(item => item.get('name')); You now have an array, tableRows, which is an array of the text values of the table items. You can then use randomInteger( tableRows.length() )-1  to get a result from the table. If the rows in the table have varying weights, there are a couple of ways to handle it, but the simplest is just to to create extra entries in the table for each weight. This should work: const tableRows = []; tableItems.forEach(item => { const weight = +item.get('weight') || 1; // get weight as a number, with a default value of 1. for(let i = 0; i < weight; i++) { // add one row for each weight            tableRows.push(item.get('name'));         } }); Then you can use the same randomInteger trick above to get a value off the table, like so: let tableResult = tableRows[randomInteger( tableRows.length() ) -1]; PS: noarchive just means the output isnt saved to the external chat archive. It doesnt affect the in-game chat. PPS: just realised I used const and let in place of var here, by habit. const is for variables that never change, and let is for everything else. You can use var in place of either of these if you are more comfortable with them. There are technical reasons for preferring them over var (they can help avoiding certain types of errors), but its not a big deal which you use. PPPS: just noticed my for loop had an error in it - it's been awhile since I used one of those, lol. Fixed it.
1560371615
GiGs
Pro
Sheet Author
API Scripter
By the way, another of adventures of managing your table rolls inside your script, is you can use modifiers, which rollableTables don't support. You just have to be careful not to let your rolls exceed the bounds of the table range.
Thanks for this detailed walk-through. I had an inkling it might be something like this, I tried to do a get-obj earlier though, and didn't get any results back. Not sure why that would be but I'll go through your info and take another look. I'm guessing it's because i didn't explicitly name the type.
ok, one more question. It doesn't make sense for this to be run every time I try to roll on the table, right? I should have this declared in advanced and just pass it along I'm thinking. However when I try to add it to the top of my namespace function, I'm not able to access it in other functions, even if I explicitly pass it along The following gives me undefined for table: var RandomEncounters = RandomEncounters || (function () { // note the open bracket before the word function here 'use strict'; var version = '1.0' const table = findObjs({ name:"Encounter-Types", _type: "rollabletable", })[0], handleInput = function (msg,table) { log(table);
1560376623

Edited 1560377557
GiGs
Pro
Sheet Author
API Scripter
Funny you should ask - I liked the concept of this, so I made it into a function. You do need to build it at run time, because if the sandbox crashes it needs to be run again, and you might want to use multiple different encounter tables. Also you might edit the table, which means the script wont have the right values. You could declare it at script start up (you would do that in the on(ready) section of the code, but the resources required to scan and build the table are negligible, and you'd need special handling to account for things like editing the table. So here's a function you can use in your script, just slot it in like so: var RandomEncounters = RandomEncounters || (function () { // note the open bracket before the word function here 'use strict'; var version = '1.0', buildTable = function(tableName) { const table = []; const tableFound = findObjs({ name: tableName, _type: "rollabletable", })[0]; if(tableFound) { const tableItems = findObjs({ _rollabletableid: tableFound.id, _type: "tableitem", }) || []; tableItems.forEach(item => { _.times(+item.get('weight'), () => table.push(item.get('name')) ); }); } return table; }, handleInput = function(msg) { I tweaked it a bit, but now you can use it in your script to return the items from any table. If you give it the name of a table that doesnt exist, it'll return an empty array []. Call it like this let thetable = buildTable('table-name'); let result = thetable[randomInteger(thetable.length -1 )]; This would allow you to pass the table name in your macro as an argument, making your script more flexible.
1560377326

Edited 1560377375
Yea, I think I'm going to turn it into a function as well (although I'll make mine a "proper" function and not inline like it looks like you did.I think I'm going to change this from being a text based command to a macro one, maybe... edit: no, i was wrong, that wasn't inline. I'm just not entirely used to seeing functions defined like variables lol
1560377636

Edited 1560377757
GiGs
Pro
Sheet Author
API Scripter
That took a while for me to grasp too :) But yes, in javascript its very common to define functions like variables, and especially in this kind of script format. By the way, there's no difference between text and macro-based scripts. All macros do is send text to the chat window, you just have the advantage of having the text set up ahead of time. 
The big advantage is (i think) i can pre-set a number of possibilities for use through the gui, as opposed to doing it in a chat window. of course, i could also make a macro that lets me select the things, and then says the command string....