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 .
×
May your rolls be merry + bright! 🎄
Create a free account

RecursiveTables-Script and roll-Modification

1592482797

Edited 1592483714
Hello, I use the RecursiveTables-Script from The Aaron and do it in nearly every campaign but I encountered now a problem, where I don't know if it is even possible to do with the script: Situation: The Players draw the initiative from a carddeck (1d66) which i made as a table. With the Script the players can just press a button, see a fancy card and the initiative-tracker does the rest: !rt[iconlabel:off|iconscale:100%] [[1t[ini] &{tracker}]] But here comes the Problem: Sometimes the players get a bonus on their initiative (can change) and thats seems not really possible to declare. My Goal is that they draw a regular card, which is displayed, and in the tracker it should add the modificator (so the card says 15 and the tracker get 16 with an boni of +1). I've tried two things: Makro: !rt[iconlabel:off|iconscale:100%] [[(1t[ini] + ?{Mod|0}) &{tracker}]] Table-Names: # Initiative (# = 1, 2, 3, ...) Will get the right turn-tracker but the card isn't displayed (just the number). Makro: !rt[iconlabel:off|iconscale:100%] [[1t[ini] &{tracker}]] Table-Names: [[(# + ?{Mod|0})]] Initiative - OR - Table-Names: [[(# + ?{Mod|0})d1]] Initiative Will just get an error: An error occured parsing this roll: [[(1 + ?{Mod|0})]] Initiative Error: Expected "(", ".", "[", "abs(", "ceil(", "d", "floor(", "round(", "t", "{", [ |\t], [+|\-], [+|\-|*|\/|%] or [0-9] but "?" found. I'm not sure if it is even possible with the script or I'm just not smart enough to find the solution (the roll20-Wiki is permanently down?). Maybe someone has a good idea for me
1592486635
The Aaron
Roll20 Production Team
API Scripter
Hmm.  I'll have to dig into this tonight.  The fact that &{tracker} is working is a side effect that isn't doing precisely what you might intend.  Since you're using RecursiveTable for the image display aspect, not the recursive aspect, it's working for you now, but it would only add the result of the inline roll on the command line to the Turn Order.  The recursive parts would happen in the API after the turn had been added.  Can you post a picture of what some of your Table Rows look like?  Am I right to assume that none of them contain inline rolls, they just have numbers for names?
1592487400

Edited 1592487488
Yeah, in this case I misuse the ability to just display the cards. Here is the Table for this problem: (funfact, if I would only name them like numbers ("11", "12", ...) the tracker would work but the chat would only get the numbers like my first try and not the cards)
1592488253
The Aaron
Roll20 Production Team
API Scripter
You could try putting them like: 11 [Initiative] and see if that works.
1592488292
The Aaron
Roll20 Production Team
API Scripter
Worst case, if all you need it for is showing the drawn card, I could probably write you a little one-off snippet that does that in a compatible fashion.
That doesn't seem to work either. Well, it would be nice but I don't want to waste your time. Adding a number to the tracker isn't that complicated, that you have to make a new script for it. I just hoped, that I would overlooked something ^^' But in any case, my warmest thanks!
1592513757
The Aaron
Roll20 Production Team
API Scripter
Can you drop me a screenshot of what your output looks like now, just in case I wanted to make something whilst gaming tonight... =D
Thank you very much! That's the output-variants I get (smaller test-table) The First one is the basic one which works as (not) intended. The Second and Fourth will accept the modification within the tracker but won't show the picture while the Third one just get me an error (which you already explained).
1592541140

Edited 1592541281
The Aaron
Roll20 Production Team
API Scripter
Ok, here's a rough first pass version.  Run it with: !table-init <TABLE NAME> [ bonus ] Example, given a table named Init-Cards: !table-init Init-Cards For each selected token, roll on the table Init-Cards picking 1 entry at random respecting the weighting and set the token's initiative to the value of that table entry.  It will also display the chosen entry's image in chat. !table-init Init-Cards 3 As above, but add 3 to the result. Some possible output: Some enhancement ideas: Add the image of the token being rolled to the output Add the number "rolled" to the output Whisper the output This doesn't have much in the way of error handling, so it will try to output an image even if there isn't one.  That shouldn't cause it to crash anything but the output in chat might be broken.  Let me know if you have any other thoughts or enhancements! Code: on('ready',()=>{ const sread = (o,p) => { let v = o; while(undefined !== v && p.length) { v = v[p.shift()]; } return v; }; const getTurnArray = () => ( '' === Campaign().get('turnorder') ? [] : JSON.parse(Campaign().get('turnorder'))); const addTokenTurn = (id, pr) => Campaign().set({ turnorder: JSON.stringify( [...getTurnArray(), {id,pr}]) }); const removeTokenTurn = (tid) => Campaign().set({ turnorder: JSON.stringify( getTurnArray().filter( (to) => to.id !== tid)) }); const s = { container: `display:inline-block;border:1px solid #999;border-radius:.2em; padding: .1em;background-color:white;`, img: `max-width: 5em;max-height:7em;display:inline-block;overflow:auto;background-color:transparent;` }; const f = { container: (d) => `<div style="${s.container}">${d}</div>`, item: (d)=>`<img src="${d}" style="${s.img}">` }; const RollToken = (token,table,bonus) => { sendChat('',`[[1t[${table}] + (${bonus})]]`,(r)=>{ let entry = sread(r,[0,'inlinerolls',0,'results','rolls',0,'results',0,'tableItem']); let pr = sread(r,[0,'inlinerolls',0,'results','total']); if(entry){ let rowObj = getObj('tableitem',entry.id); removeTokenTurn(token.id); addTokenTurn(token.id,pr); sendChat(`${token.get('name')}`,f.container(f.item(rowObj.get('avatar')))); } }); }; on('chat:message',msg=>{ if('api'===msg.type && /^!table-init(\b\s|$)/i.test(msg.content) && playerIsGM(msg.playerid)){ // let who = (getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname'); let tokens = (msg.selected || []) .map(o=>getObj('graphic',o._id)) .filter(g=>undefined !== g) ; let args = msg.content.split(/\s+/); let tableName = args[1]; let bonus = parseFloat(args[2]||'0'); const roll = (t) => RollToken(t,tableName,bonus); tokens.forEach(roll); } }); });
Hey, it's awesome! I modfied  the follow things for me: deleted "&& playerIsGM(msg.playerid)" with the intend, that every player should be able to roll scaled the picture up editet the post-command to post just the picture with a random prayer "sendChat(`${token.get('name')}`,'<br>*' + '[[1t[ini-prayer]]]' + '*' + f.item(rowObj.get('avatar')));" I've tried a few things to let the prayer be a roll from a different table but the best I could do was "[[1t[ini-prayer]]]" which gives a random text but in the ugly yellow-output - I'm definitely not good enough to do this^^' I've got no crash when the params weren't true (non existable table, or no token selected) - just nothing happens in the chat. If the table-element got no picture it will post an empty message (or in my case just the prayer). So that would be my enhacement-suggestions (beside what your already write): let it roll everyone adjustable image-size with and without the container possibilty for posting another table or message with it Best regards and much much thanks!
1592571910
The Aaron
Roll20 Production Team
API Scripter
Ah, nice!  Good catch on the playerIsGM().  Whoops! =D  That's part of my template for making Script Snippets and I forgot to remove it for this one. =D Here's a version with what you listed above.  It's still formatting using the functions and styles I had in there—I wasn't sure if you wanted those but didn't know how to fit the prayer text in, or didn't—but since you know how to remove them, I left them with the text just in case. I added an optional third argument which is the name of a table to roll for additional text (called "quoteTable" in the code).   Roll like this: !table-init <TABLE NAME> [ bonus ] [ quote table name ] Examples: Using the Init table with a +1 bonus and a table called Quotes: !table-init Init 1 Quotes Using the Init table, no bonus, and the table called Quotes: !table-init Init 0 Quotes Using the Init table and a -1: !table-init Init -1 Here's what the output looks like with the Quote table: New Code: on('ready',()=>{ const sread = (o,p) => { let v = o; while(undefined !== v && p.length) { v = v[p.shift()]; } return v; }; const getTurnArray = () => ( '' === Campaign().get('turnorder') ? [] : JSON.parse(Campaign().get('turnorder'))); const addTokenTurn = (id, pr) => Campaign().set({ turnorder: JSON.stringify( [...getTurnArray(), {id,pr}]) }); const removeTokenTurn = (tid) => Campaign().set({ turnorder: JSON.stringify( getTurnArray().filter( (to) => to.id !== tid)) }); const s = { container: `display:inline-block;border:1px solid #999;border-radius:.2em; padding: .1em;background-color:white;`, img: `max-width: 8em;max-height:8em;display:block;overflow:auto;background-color:transparent;margin-left:auto;margin-right:auto;`, quote: `font-weight: bold;font-style:italic;padding:.3em;` }; const f = { container: (d,q) => `<div style="${s.container}">${d}${q}</div>`, item: (d)=>`<img src="${d}" style="${s.img}">`, quote: (q)=>q?`<div style="${s.quote}">${q}</div>`:'' }; const RollToken = (token,table,bonus,quoteTable) => { sendChat('',`[[1t[${table}] + (${bonus})]]${quoteTable?`[[1t[${quoteTable}] ]]`:''}`,(r)=>{ let entry = sread(r,[0,'inlinerolls',0,'results','rolls',0,'results',0,'tableItem']); let pr = sread(r,[0,'inlinerolls',0,'results','total']); let quote = sread(r,[0,'inlinerolls',1,'results','rolls',0,'results',0,'tableItem','name']); if(entry){ let rowObj = getObj('tableitem',entry.id); removeTokenTurn(token.id); addTokenTurn(token.id,pr); sendChat(`${token.get('name')}`,f.container(f.item(rowObj.get('avatar')),f.quote(quote))); } }); }; on('chat:message',msg=>{ if('api'===msg.type && /^!table-init(\b\s|$)/i.test(msg.content)){ let tokens = (msg.selected || []) .map(o=>getObj('graphic',o._id)) .filter(g=>undefined !== g) ; let args = msg.content.split(/\s+/); let tableName = args[1]; let bonus = parseFloat(args[2]||'0'); let quoteTableName = args[3]; const roll = (t) => RollToken(t,tableName,bonus,quoteTableName); tokens.forEach(roll); } }); });
1592571952
The Aaron
Roll20 Production Team
API Scripter
Also thank YOU for what you sent me!  Not necessary or expected, but definitely appreciated!!
1592584291

Edited 1592584363
Thanks again - it works like a charm even with ?{Modification|0} ! For the especially smart players i added after " tokens.forEach(roll); " the lines: if(tokens.length <= 0){ sendChat('Ikonen','/w "' + msg.who + '" Erst den Token auswählen!', null, {noarchive:true}); } Now it should be safe to use for all my players :D My final state (after a few container adjustments):
1592588046
The Aaron
Roll20 Production Team
API Scripter
Awesome!!  That looks really good. =D