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 .
Advertisement Create a free account Compendium in Game, Join Today

How to Access Rollable Tables with API?

1602803075
I want to access Front/Back facing sprites automatically as I move my tokens.  I already have a script that horizontally flips the token as I move it left and right.  How would I access rollable tables to use front and back when moving my token up and down? This is an excerpt of the left/right script: traveller.changeDirection = function() {  traveller.direction *= -1; var token = getObj("graphic", traveller.tokenID); if (token !== undefined ) { token.set("fliph", !token.get("fliph") ); } This is an example of my rollable tables:
1602809581
GiGs
Pro
Sheet Author
API Scripter
Once you create a token from a rollable table, the token has no connection to the table any more. You can access the token's images using the currentside property, IIRC. 
1602809908
So all three images of the token are bound to currentside property?  I'm not sure what that is, but I'll look into it.  Thank you.  This explains why I haven't had much luck in accessing rollable tables via script.
1602810361

Edited 1602810392
It looks like I found a chunk of The Aaron's code thar relates to currentside. !token-mod {{ --set ?{Choose Form|Revert Humanoid,currentside#1 represents#@{Bob|character_id} width#70 height#70 |Dire Wolf,currentside#3 represents#@{Dire Wolf|character_id} width#[[2*70]] height#[[2*70]] |Brown Bear,currentside#2 represents#@{Brown Bear|character_id} width#[[2*70]] height#[[2*70]] } bar1_link|hp bar2_link|npc_ac bar3_link|npc_speed showname|yes }} As for how to call it using my token format I would have something like: {|Ball,currentside#1 |Front,currentside#2 |Back,currentside#3 }
1602812096
GiGs
Pro
Sheet Author
API Scripter
If you are using tokenMod, instead of writing your own script, its very easy - tokenmod supports changing the image. If you want to do it in your own code, tokens have a sides property and a currentSide property, you need to access those to change the image. Here's a script i posted a long time ago based on Aaron's work: <a href="https://app.roll20.net/forum/permalink/7404879/" rel="nofollow">https://app.roll20.net/forum/permalink/7404879/</a> &nbsp;. You should be able to figure out how to proceed from there, but if not, ask away.&nbsp;
1602863520
The good news is I figured out how to get the vertical function to work.&nbsp; The bad news I'm getting the following errors when using the code you linked: TypeError: Cannot read property 'id' of undefined TypeError: Cannot read property 'id' of undefined at getImageList (apiscript.js:1167:79) at updateToken (apiscript.js:1144:28) at eval (eval at &lt;anonymous&gt; (/home/node/d20-api-server/api.js:154:1), &lt;anonymous&gt;:65:16) at Object.publish (eval at &lt;anonymous&gt; (/home/node/d20-api-server/api.js:154:1), &lt;anonymous&gt;:70:8) at TrackedObj.set (/home/node/d20-api-server/api.js:1057:16) at updateLocalCache (/home/node/d20-api-server/api.js:1345:18) at /home/node/d20-api-server/api.js:1529:11 at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:560 at hc (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:39:147) at Kd (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:546) I changed attr to 1-2 and I'm still getting the same error.&nbsp; Should be changing id or should I be using some sort of .get function?
1602884736
GiGs
Pro
Sheet Author
API Scripter
Can you post the code you are using?
1602893362

Edited 1602893482
The code is nearly identical to what you shared.&nbsp; I was just attempting to get it to work before incorporating it into my current code that horizontally flips.&nbsp; All I changed was I turned attr into 1-2 to display the Front and Back images of the token.&nbsp; The code fails when I attempt to lower health bar #1. <a href="https://github.com/Varnell-VII/Roll20/blob/main/Flip%20Tokens" rel="nofollow">https://github.com/Varnell-VII/Roll20/blob/main/Flip%20Tokens</a>
1602893572
The code I've been editing is PlexSoup's: <a href="https://gist.github.com/plexsoup/6fb407c51d3ded60119f914ea82781de" rel="nofollow">https://gist.github.com/plexsoup/6fb407c51d3ded60119f914ea82781de</a>
1602969120

Edited 1602969252
This is the script I was attempting to run.&nbsp; Once I get this working I don't anticipate too much trouble incorporating it into PlexSoup's script. /* If you have a character token made from Rollable Token, this script will change the image displayed based on the value of a token bar. So you could have the image change automatically based on damage, or just if you just want to use a bar to quickly change the token's image. The top four constants areset the behaviour of the script: &nbsp; &nbsp; TOKENBAR: the token bar to use. &nbsp; &nbsp; IMAGEMAX: if you want to limit the token selection to, say, the first 3 images, set IMAGEMSX = 3. If 0, it uses all the token images. &nbsp; &nbsp; You can also create an attribute and set an array of images to use. If this attribute exists, the imagemax above is ignored. &nbsp; &nbsp; The attribute can have values like 1,2,3,4 or 2-4, or 1,3-5,7. Only numbers, commas and hyphens are used.&nbsp; &nbsp; &nbsp; IMAGEARRAY: name of the attribute to use. &nbsp; &nbsp; IMAGEOFFSET: programmers often use 0 as the first entry. If you prefer to have 1 as the first image, set this as 1, otherwise 0. &nbsp; &nbsp; &nbsp; &nbsp; so if 1-3 refers to the first 3 images, IMAGEOFFSET = 1; if 0-2 refers to the first 3 images, IMAGEOFFSET = 0. */ var TokenImgHealth = TokenImgHealth || (function() { &nbsp; &nbsp; 'use strict'; &nbsp; &nbsp; // edit the following four bars if needed/ &nbsp; &nbsp; var TOKENBAR = 1, // which bar you are using for health, or checking which image to use. &nbsp; &nbsp; IMAGEMAX = 0, // the images in the token to use (in order from lowest to highest), SET TO 0 to use all images &nbsp; &nbsp; IMAGEARRAY = 'damageLevels', &nbsp; &nbsp; IMAGEOFFSET = 1, // 0 if IMAGEARRAY entries starts at 0, 1 if it starts at 1. &nbsp; &nbsp; updateToken = function(o, prev) { &nbsp; &nbsp; &nbsp; &nbsp; const maxValue = parseInt(o.get(`bar${TOKENBAR}_max`)); &nbsp; &nbsp; &nbsp; &nbsp; const curValue = parseInt(o.get(`bar${TOKENBAR}_value`)); &nbsp; &nbsp; &nbsp; &nbsp; const oldValue = parseInt(prev[`bar${TOKENBAR}_value`]); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!isNaN(maxValue) &amp;&amp; !isNaN(curValue) &amp;&amp; oldValue !== curValue) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let allSides = o.get("sides").split("|"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let thisSide = o.get("currentSide") ; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let numSides = IMAGEMAX === 0 ? allSides.length : Math.min(allSides.length, IMAGEMAX); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let useSides = getImageList(o,IMAGEARRAY,IMAGEOFFSET); // useSides = 0 if no attribute &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let newSide; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( useSides &amp;&amp; useSides.includes(parseInt(thisSide)) ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newSide = useSides[getImageIndex(useSides.length, curValue,&nbsp; maxValue)]; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if(&nbsp; !useSides &amp;&amp; thisSide &lt; numSides&nbsp; ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newSide = getImageIndex(numSides, curValue,&nbsp; maxValue); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (newSide !== thisSide) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let nextURL = setImg(o,newSide,allSides); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, &nbsp; &nbsp; getImageIndex = function(numSides, curValue, maxValue) { &nbsp; &nbsp; &nbsp; &nbsp; return Math.min(numSides-1,Math.max(0,Math.ceil(curValue / maxValue * (numSides -1)))); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; getImageList = function(token, attr, imageOffset) { &nbsp; &nbsp; &nbsp; &nbsp; // this function returns an array of image indexes if an attribute lists them &nbsp; &nbsp; &nbsp; &nbsp; // returns 0 if no attribute exists &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var Char = getObj("character", token.get("represents")); &nbsp; &nbsp; &nbsp; &nbsp; var Attr = findObjs({name: 1-2,_type: "attribute", _characterid: Char.id}, {caseInsensitive: true})[0];&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(Attr) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // attr needs to be in the format 1-3, or 1,2,3,5, could be 1-3, 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let base = getAttrByName(Char.id,1-2).replace(/([^0-9-,]+)/gi, '');; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let arr = []; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; base.split(',').forEach(item =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(item.includes("-")) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let temp = item.split('-'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for(let i = temp[0]; i &lt;= temp[1]; i++) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; arr.push(Number(i) - imageOffset); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; arr.push(Number(item)&nbsp; - imageOffset); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return (arr.length === 0 || arr[0] === -1) ? 0 : arr; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 0; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, &nbsp; &nbsp; getCleanImagesrc = function (imgsrc) { &nbsp; &nbsp; &nbsp; &nbsp; var parts = imgsrc.match(/(.*\/images\/.*)(thumb|med|original|max)([^?]*)(\?[^?]+)?$/); &nbsp; &nbsp; &nbsp; &nbsp; if(parts) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return parts[1]+'thumb'+parts[3]+(parts[4]?parts[4]:`?${Math.round(Math.random()*9999999)}`); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; }, report = function (o,img){ sendChat('ChangeTokenImage',`/w gm &lt;div&gt;&lt;img src="${img}" style="max-width: 3em;max-height: 3em;border:1px solid #333; background-color: #999; border-radius: .2em;"&gt; Image not in User Library on token ${o.get('name')}&lt;/div&gt;`); }, &nbsp; &nbsp; setImg = function (o,nextSide,allSides) { &nbsp; &nbsp; &nbsp; &nbsp; var nextURL = getCleanImagesrc(decodeURIComponent(allSides[nextSide])); if(nextURL) { o.set({ currentSide: nextSide, imgsrc: nextURL }); } else { report(o,decodeURIComponent(allSides[nextSide])); } &nbsp; &nbsp; &nbsp; &nbsp; return nextURL; &nbsp; &nbsp; }, &nbsp; &nbsp; registerEventHandlers = function() { &nbsp; &nbsp; &nbsp; &nbsp; on('change:token', updateToken); &nbsp; &nbsp; }; &nbsp; &nbsp; return { &nbsp; &nbsp; &nbsp; &nbsp; RegisterEventHandlers: registerEventHandlers, &nbsp; &nbsp; }; }()); on("ready",function(){ &nbsp; &nbsp; 'use strict'; &nbsp; &nbsp; TokenImgHealth.RegisterEventHandlers(); });