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

Random token from table on drop?

October 26 (3 years ago)

Hello all! I am looking for a way to have a different token face appear from roll tables when I drop a token, for example my zombie token has eight different artworks of zombies on the roll table token, and I want it so that when I drag and drop a token on the field, it will randomly select a different one each time. 

October 26 (3 years ago)
The Aaron
Roll20 Production Team
API Scripter

That could be done with an API script. If you don't mind a single extra step, you can select all of them and run a TokenMod command:

!token-mod --set currentside|*



The Aaron said:

That could be done with an API script. If you don't mind a single extra step, you can select all of them and run a TokenMod command:

!token-mod --set currentside|*



Is there any way to get this command to fire whenever the token is dropped from the journal or whenever a token is copied and pasted?  Similar to how MHD rolls hitpoints on drop and paste?  I have a bestiary of like 1500 token images/sides and would love to have them drop randomized instead of having to do it all manually.  

October 26 (3 years ago)
The Aaron
Roll20 Production Team
API Scripter

Not with TokenMod directly, but it would be a pretty simple API script to write, let me see what I can do. 

October 26 (3 years ago)

Edited October 27 (3 years ago)
The Aaron
Roll20 Production Team
API Scripter

Give this a try.  Note that it will only work on non-marketplace images:

on('ready',()=>{

  const playerCanControl = (obj, playerid='any') => {
    const playerInControlledByList = (list, playerid) => list.includes('all') || list.includes(playerid) || ('any'===playerid && list.length);
    let players = obj.get('controlledby')
      .split(/,/)
      .filter(s=>s.length);

    if(playerInControlledByList(players,playerid)){
      return true;
    }

    if('' !== obj.get('represents') ) {
      players = (getObj('character',obj.get('represents')) || {get: function(){return '';} } )
        .get('controlledby').split(/,/)
        .filter(s=>s.length);
      return  playerInControlledByList(players,playerid);
    }
    return false;
  };

  const getCleanImgsrc = (imgsrc) => {
    let 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;
  };
  const isString = (s)=>'string'===typeof s || s instanceof String;

  let tokenIds = [];

  const saveTokenId = (obj) => {
    tokenIds.push(obj.id);
  };

  const setTokenRandomSide = (obj,prev,force=false) => {
    if(tokenIds.includes(obj.id) || force){
      tokenIds=tokenIds.filter(id => id !== obj.id);
      if( 'graphic' === obj.get('type') && 'token'   === obj.get('subtype') && ! playerCanControl(obj)){
        let sideText = obj.get('sides');
        if( sideText.length ){
          let sides = sideText.split(/\|/).map(decodeURIComponent).map(getCleanImgsrc).filter(isString);
          if(sides.length){
            obj.set({
              imgsrc: sides[randomInteger(sides.length)-1]
            });
          }
        }
      }
    }
  };

  on('add:graphic', saveTokenId);
  on('change:graphic', setTokenRandomSide);

});
Edit: Fixed crash when Marketplace Images are present.
October 26 (3 years ago)
The Aaron
Roll20 Production Team
API Scripter

Also, I set it up to only change non-PC tokens randomly.

Works perfectly.  Tested to make sure it wouldn't conflict with manual flips from tokenmod, wildshape api, or spawndefaulttoken and everything worked as intended and no conflicts.  
October 26 (3 years ago)

Edited October 26 (3 years ago)

Thanks for the the script! I tried it but I got an error...I'm not sure where it is, because reading the errors that showed up once I put it in, it has stuff that is not in what you made. Other API I am running are: Group Initiative, Token Mod, Token Action Maker, Monster Hit Dice, lib token markers, token name number, and namegen.


The error that I got looks like this.

API Output Console

Your scripts are currently disabled due to an error that was detected. Please make appropriate changes to your script's code and click the "Save Script" button. We will then attempt to start running the scripts again. More info... If this script was installed from the Script Library, you might find help in the Community API Forum.

For reference, the error message generated was: TypeError: Cannot read property 'substring' of undefined TypeError: Cannot read property 'substring' of undefined at TrackedObj._validateAttrs (/home/node/d20-api-server/api.js:933:27) at TrackedObj.set (/home/node/d20-api-server/api.js:1023:18) at setNumberOnToken (apiscript.js:7453:17) at eval (eval at <anonymous> (/home/node/d20-api-server/api.js:168:1), <anonymous>:65:16) at Object.publish (eval at <anonymous> (/home/node/d20-api-server/api.js:168:1), <anonymous>:70:8) at TrackedObj.set (/home/node/d20-api-server/api.js:1083:14) at updateLocalCache (/home/node/d20-api-server/api.js:1418:18) at /home/node/d20-api-server/api.js:1604: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)

My only guess is that your token images are not stored in your quota, even the default marketplace ones or external urls are going to fail in this script, everything must be in YOUR quota.  

October 26 (3 years ago)

Edited October 26 (3 years ago)

So having any tokens that use images from marketplace, or the freebies would break the script? That is gonna take me a long time to fix, since I have images for every creature on the SRD, many of them are from the marketplace, free assets, or 'from the web'

------

Edit

Did some testing with it, and ran the script again, this time dropping a token with a roll table with nothing but my own quota, and it worked just fine. Looks like I just need to remember which ones have rolltables with assets that are not my own.

October 26 (3 years ago)

Got it working, amazing work The Aaron! This would make an amazing addition to the script library!

October 27 (3 years ago)
The Aaron
Roll20 Production Team
API Scripter

Hmm.  It shouldn't crash like that, I'll track down the issue and update the code.


October 27 (3 years ago)
The Aaron
Roll20 Production Team
API Scripter

OK, fixed the code above, it won't crash like that now!