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

Look Up Tables

I am trying to figure out a way to roll a die, apply modifiers, and look up a result on a table and output the result cleanly into chat to players or as GM Whisper. I am aware of Rollable Tables and The Aaron's script that polishes the output. I like those options but, I do love to see and hear the actual dice roll* over just the text output and I'd like to be able to add modifiers. For example, lets say I want to have a poison called rotters juice that my characters will come across fairly often. I would build a response table based on a d20 and wanted to modify it with a players constitution.  The table might be something like: 1 Instant Death 2-3 Unconscious, zero HP, start death saves 4-6 Unconscious, zero HP, stable 7-12 Stunned for 1 minute 13-15 blurred vision, disadvantage on Dex and Attack rolls for the next hour. 16-19 Nausea, disadvantage on CON saves for the next hour. 20 No effect A character with a CON modifier of +2 triggers the trap and rolls an 11 and adds his CON MOD for a final roll of 13 so he has a vision problem for a while. Ideally, I'd like to be able to create a table and feed it the die result. In this case, I might have a table called poison and a macro called lookup. I could then type #lookup poison 13. I know I probably break a few rules here, but this is conceptual for illustrative purposes.  Thoughts and ideas appreciated. * dice rolls - I still love to watch the dice roll across the table and have that moment of suspense on a close roll or when you see a number you need but a second die bumps it.  Roll20 replicates dice rolls quite well and is one of my favorite things about the system. 
1508253644

Edited 1508253681
Silvyre
Forum Champion
It is possible to have a single macro roll the 3D die and output the corresponding text; doing so requires the creation of multiple Rollable Tables, one for each piece of text. For example, [[ 1t[[[ {1,2,4,7,13,16,20}<[[1d20 + @{target|constitution_mod}]] ]]-Rotters-Juice] ]] This macro should do what you want. It requires the creation of 7 Rollable Tables, e.g. named "1-Rotters-Juice" through "7-Rotters-Juice": Due to the nature of this macro, the exact die result cannot be seen without having 3D Dice enabled.
1508253936
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
You may be able to adapt  this rollable table workaround to sort of do what you want (note this is sort of what Silvyre is showing). Otherwise, you'll need a custom api script. I have a modded version of Recursive Tables that allows the application of mods to the roll, although I wouldn't want to share it just yet as I haven't used it in a while, and I remember there being some bugs that Aaron and I were tracking down.
so, in short, I would have to create a 'table' for each entry. Creative solution for one table but I don't see it scaling well. I'd bet there is a way to do a script; alas, I haven't touched a lick of code in more than a decade and that was C++. Oh well, I suppose I can make look up tables in a db app and query it from another app on another screen. Was hoping for something inline. Thanks for the input and advice.  
Scott C. said: You may be able to adapt  this rollable table workaround to sort of do what you want (note this is sort of what Silvyre is showing). Otherwise, you'll need a custom api script. I have a modded version of Recursive Tables that allows the application of mods to the roll, although I wouldn't want to share it just yet as I haven't used it in a while, and I remember there being some bugs that Aaron and I were tracking down. that is going to take some thinking on my part to decypher. Thanks...I'll start poking my brain after another cup of joe.
1508255111
The Aaron
Pro
API Scripter
Getting the 3d dice is the hard part, as it turns out.  Inline rolls passed to API commands don't trigger the roll, so to do this with an API script would require monitoring the non-api messages an issuing a message when a roll is on a given table, probably using a syntax like: /w gm some message [[1d20+@{selected|con} [table:rottersjuice]]] Which would then send the results of a lookup to the GM and player (if not a gm) and to everyone if it wasn't whispered.
1508255416
The Aaron
Pro
API Scripter
Lookups is actually very easy: In chat !lookup poison [[1d20+@{selected|con}]] Whispered to gm and player !glookup poison [[1d20+@{selected|con}]] Whispered only to the gm, notice to the player about a blind roll: !blookup poison [[1d20+@{selected|con}]] Script: on('ready',()=>{     const rollableTable = (function( ){         let tables = {},             IDtoTableName = {};         const nullTableRoller = function(){             return '';         },         buildTableRoller = function(tablename){             let tobj = _.first(findObjs({                 type: 'rollabletable',                 name: tablename             }));             tables[tablename]=nullTableRoller;             if(tobj){                 IDtoTableName[tobj.id]=tablename;                 tables[tablename] = (function(){                     let values = _.reduce(                         findObjs({                             type: 'tableitem',                             rollabletableid: tobj.id                         }),                         function(m,e){                             IDtoTableName[e.id]=tablename;                             _.times(e.get('weight'),function(){m.push(e.get('name'));});                             return m;                         },                         []                     );                     return function(num){                         return values[Math.min(values.length,Math.max(1,num))-1];                     };                 }());             }         },         handleItemChange = function(obj){             if(IDtoTableName[obj.get('rollabletableid')]){                 buildTableRoller(IDtoTableName[obj.get('rollabletableid')]);             }         },         handleTableChange = function(obj){             if(IDtoTableName[obj.id]){                 buildTableRoller(IDtoTableName[obj.id]);             }         };         on('change:rollabletable',handleTableChange);         on('change:tableitem',handleItemChange);         on('add:tableitem',handleItemChange);         on('destroy:tableitem',handleItemChange);         return function( tablename ){             if(!tables[tablename]){                 buildTableRoller(tablename);             }                          return (function(tab,nam){                 return function(n){                     return tab[nam](n);                 };             }(tables,tablename));         };     }());     const outer = (contents) => `<div style="margin-bottom: .3em;border:1px solid #999;background-color: #ffe;padding: .2em; border-radius:.2em;">${contents}</div>`;     const result = (contents) => `<div style="display:inline-block;font-size: 1.5em; border: 1px solid #999; background-color: #fef; font-weight: bold; border-radius: .2em; padding: .4em .2em;margin-right: .2em;">${contents}</div>`;     on('chat:message',(orig_msg)=>{         if(/![gb]?lookup\b/i.test(orig_msg.content)){             let msg=_.clone(orig_msg);             if(_.has(msg,'inlinerolls')){                 msg.content = _.chain(msg.inlinerolls)                     .reduce(function(m,v,k){                         var ti=_.reduce(v.results.rolls,function(m2,v2){                             if(_.has(v2,'table')){                                 m2.push(_.reduce(v2.results,function(m3,v3){                                     m3.push(v3.tableItem.name);                                     return m3;                                 },[]).join(', '));                             }                             return m2;                         },[]).join(', ');                         m['$[['+k+']]']= (ti.length && ti) || v.results.total || 0;                         return m;                     },{})                     .reduce(function(m,v,k){                         return m.replace(k,v);                     },msg.content)                     .value();             }             let args=msg.content.split(/\s+/);             let table=args[1]||'';             let num=args[2]||1;             let text=rollableTable(table)(num);             let blind=/^!b/i.test(msg.content);             let whisper=/^!g/i.test(msg.content);             let who=(getObj('player',orig_msg.playerid)||{get:()=>'API'}).get('_displayname');             let output=outer(`${result(num)} <b>${table}</b>:${text}`);             if(blind || whisper){                 sendChat(who,`/w gm ${output}`);                 if(!playerIsGM(msg.playerid)){                     if(whisper){                         sendChat('',`/w "${who}" ${output}`);                     } else {                         sendChat('',`/w "${who}" ${outer('Blind roll sent to GM')}`);                     }                 }             } else {                 sendChat('',output);             }         }     }); });
1508255442
The Aaron
Pro
API Scripter
Unfortunately, that won't show the 3d dice since it's passing the inline roll to an API command.
1508255565

Edited 1508255676
Silvyre
Forum Champion
The Aaron said: Getting the 3d dice is the hard part, as it turns out. Yeah, otherwise I would have suggested PowerCards. Scott C. said: You may be able to adapt  this rollable table workaround to sort of do what you want This technique unfortunately will not be able to provide 3D Dice. If you are okay with using two macros consecutively, this technique (which requires the installation of the PowerCards API Script ) may "scale" better: /roll 1d20 !power {{ --Roll|?{Roll|13} --?? ?{Roll} == 1 ?? !Effect|Instant Death --?? ?{Roll} >= 2 AND ?{Roll} <= 3 ?? !Effect|Unconscious, zero HP, start death saves --?? ?{Roll} >= 4 AND ?{Roll} <= 6 ?? !Effect|Unconscious, zero HP, stable --?? ?{Roll} >= 7 AND ?{Roll} <= 12 ?? !Effect|Stunned for 1 minute --?? ?{Roll} >= 13 AND ?{Roll} <= 15 ?? !Effect|blurred vision, disadvantage on Dex and Attack rolls for the next hour. --?? ?{Roll} >= 16 AND ?{Roll} <= 19 ?? !Effect|Nausea, disadvantage on CON saves for the next hour. --?? ?{Roll} == 20 ?? !Effect|No effect }}
Thanks both! I will have to sit down and see if I can decipher and understand all that, but a quick answer to the text...I would be very cool with the player rolling a check - in my example Gronk the Dwarf clicks his CON save - to get the dice roll and mods. If I could then take that output and type !lookup poison 12 it would be pretty bonzer. Yea, I would be okay with two macro's consecutively. Let me try to filter through all the technical stuff above and see what I can figure out. That will take some time.
1508256534
The Aaron
Pro
API Scripter
Oh, you can do that just fine:  !lookup poison 12 will give you the 12th entry in the table (or the top entry if there are fewer than 12).
The Aaron said: Oh, you can do that just fine:  !lookup poison 12 will give you the 12th entry in the table (or the top entry if there are fewer than 12). you mean using hte script you posted above so steps are basically: 1. save above script in my game sandbox with the name lookup.js 2. create a poison table 3. use as above. That said, sounds like my table would have to have an entry for each die roll rather than a range... 7 - stunned for 1 minute 8 - stunned for 1 mintue 9 - stunned for 1 minute 10 - blind for 1 minute 11 - blind for 1 minute 12 - projectile barfing for 1 minute 13 - porjectile barfing for 1 minute 14 - you are doing just fine mate.
1508257525

Edited 1508257540
The Aaron
Pro
API Scripter
Almost.  1) Save the above script and put it in your sandbox (but the name is unimportant). 2) create tables with names that don't have spaces in them, like poison or RottersJuice (Case is important). 3) perform the lookup as above with the 1st argument the name of the table (Case is important) and the second argument is an integer specifying the value. When creating tables, the weight is expanded to give the right number of rows: 1w: Instant Death 2w: Unconscious, zero HP, start death saves 3w Unconscious, zero HP, stable 5w: Stunned for 1 minute 3w: blurred vision, disadvantage on Dex and Attack rolls for the next hour. 4w: Nausea, disadvantage on CON saves for the next hour. 1w: No effect !lookup RottersJuice 12 would give you "blurred vision, disadvantage on Dex and Attack rolls for the next hour."  (1+2+3+5) < 12
Bonzer! That works great!  Thanks!