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

How to Access Rollable Tables with API?

October 15 (4 years ago)

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:


October 16 (4 years ago)
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. 

October 16 (4 years ago)
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.
October 16 (4 years ago)

Edited October 16 (4 years ago)

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 }
October 16 (4 years ago)
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: https://app.roll20.net/forum/permalink/7404879/ . You should be able to figure out how to proceed from there, but if not, ask away. 

October 16 (4 years ago)

The good news is I figured out how to get the vertical function to work.  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 <anonymous> (/home/node/d20-api-server/api.js:154:1), <anonymous>:65:16) at Object.publish (eval at <anonymous> (/home/node/d20-api-server/api.js:154:1), <anonymous>: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.  Should be changing id or should I be using some sort of .get function?

October 16 (4 years ago)
GiGs
Pro
Sheet Author
API Scripter

Can you post the code you are using?

October 17 (4 years ago)

Edited October 17 (4 years ago)

The code is nearly identical to what you shared.  I was just attempting to get it to work before incorporating it into my current code that horizontally flips.  All I changed was I turned attr into 1-2 to display the Front and Back images of the token.  The code fails when I attempt to lower health bar #1.


https://github.com/Varnell-VII/Roll20/blob/main/Flip%20Tokens

October 17 (4 years ago)

The code I've been editing is PlexSoup's:

https://gist.github.com/plexsoup/6fb407c51d3ded60119f914ea82781de

October 17 (4 years ago)

Edited October 17 (4 years ago)

This is the script I was attempting to run.  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:

    TOKENBAR: the token bar to use.

    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.

    You can also create an attribute and set an array of images to use. If this attribute exists, the imagemax above is ignored.

    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. 

    IMAGEARRAY: name of the attribute to use.

    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.

        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() {

    'use strict';

    // edit the following four bars if needed/

    var TOKENBAR = 1, // which bar you are using for health, or checking which image to use.

    IMAGEMAX = 0, // the images in the token to use (in order from lowest to highest), SET TO 0 to use all images

    IMAGEARRAY = 'damageLevels',

    IMAGEOFFSET = 1, // 0 if IMAGEARRAY entries starts at 0, 1 if it starts at 1.

    updateToken = function(o, prev) {

        const maxValue = parseInt(o.get(`bar${TOKENBAR}_max`));

        const curValue = parseInt(o.get(`bar${TOKENBAR}_value`));

        const oldValue = parseInt(prev[`bar${TOKENBAR}_value`]);

        

        if (!isNaN(maxValue) && !isNaN(curValue) && oldValue !== curValue) {

            

            let allSides = o.get("sides").split("|");

            let thisSide = o.get("currentSide") ;

            let numSides = IMAGEMAX === 0 ? allSides.length : Math.min(allSides.length, IMAGEMAX);

            let useSides = getImageList(o,IMAGEARRAY,IMAGEOFFSET); // useSides = 0 if no attribute

            let newSide;

            if( useSides && useSides.includes(parseInt(thisSide)) ) {

                newSide = useSides[getImageIndex(useSides.length, curValue,  maxValue)];

            } else if(  !useSides && thisSide < numSides  ) {

                newSide = getImageIndex(numSides, curValue,  maxValue);

            } else {

                return;

            }

            if (newSide !== thisSide) {

                let nextURL = setImg(o,newSide,allSides);

            }

        }

    },

    getImageIndex = function(numSides, curValue, maxValue) {

        return Math.min(numSides-1,Math.max(0,Math.ceil(curValue / maxValue * (numSides -1))));

        

    },

    getImageList = function(token, attr, imageOffset) {

        // this function returns an array of image indexes if an attribute lists them

        // returns 0 if no attribute exists

        

        var Char = getObj("character", token.get("represents"));

        var Attr = findObjs({name: 1-2,_type: "attribute", _characterid: Char.id}, {caseInsensitive: true})[0];  

        if(Attr) {

            // attr needs to be in the format 1-3, or 1,2,3,5, could be 1-3, 5

            let base = getAttrByName(Char.id,1-2).replace(/([^0-9-,]+)/gi, '');;

            let arr = [];

            base.split(',').forEach(item => {

                if(item.includes("-")) {

                    let temp = item.split('-');

                    for(let i = temp[0]; i <= temp[1]; i++) {

                        arr.push(Number(i) - imageOffset);

                    }

                } else {

                    arr.push(Number(item)  - imageOffset);

                }    

            })

            return (arr.length === 0 || arr[0] === -1) ? 0 : arr;

        } else {

            return 0;

        }

    },

    getCleanImagesrc = function (imgsrc) {

        var parts = imgsrc.match(/(.*\/images\/.*)(thumb|med|original|max)([^?]*)(\?[^?]+)?$/);

        if(parts) {

            return parts[1]+'thumb'+parts[3]+(parts[4]?parts[4]:`?${Math.round(Math.random()*9999999)}`);

        }

        return;

    },

report = function (o,img){

sendChat('ChangeTokenImage',`/w gm <div><img src="${img}" style="max-width: 3em;max-height: 3em;border:1px solid #333; background-color: #999; border-radius: .2em;"> Image not in User Library on token ${o.get('name')}</div>`);

},

    setImg = function (o,nextSide,allSides) {

        var nextURL = getCleanImagesrc(decodeURIComponent(allSides[nextSide]));

if(nextURL) {

o.set({

currentSide: nextSide,

imgsrc: nextURL

});

} else {

report(o,decodeURIComponent(allSides[nextSide]));

}

        return nextURL;

    },

    registerEventHandlers = function() {

        on('change:token', updateToken);

    };

    return {

        RegisterEventHandlers: registerEventHandlers,

    };

}());

on("ready",function(){

    'use strict';

    TokenImgHealth.RegisterEventHandlers();

});