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

Token Side change Macro/API?

1509060248
Nox
Translator
Hi all, i'd like to have a simple macro or script to swap the face of a token. I set up a rollable table with two image (one blue-ish and one Red-ish, that represent the Idle and the Combat stance of a golem of one of my players). I'd like to give the player the chance to change his golem's token from a macro or a script without having to right click it and manually select. Any way I can accomplish this?
1509062379
The Aaron
Pro
API Scripter
Change Token Image does that.  Here's how you get the help screen: !change-token-img --help Here's the version I've tweaked: // By:       Christopher Buchholz //           with heavy copying from, I mean use of as a Pattern, TokenMod var ChangeTokenImg = ChangeTokenImg || (function() {     'use strict';     var version = '0.1.32',     lastUpdate = 1499262126,     observers = {         tokenChange: []     },     showHelp = function(id) {         var who=getObj('player',id).get('_displayname').split(' ')[0];         sendChat('',             '/w '+who+' <div style="border: 1px solid black; background-color: white; padding: 3px 3px">'             + '<div style="padding-bottom:5px">'             + '<span style="font-size:130%;border-bottom:1px;font-weight:bold">ChangeTokenImg v'+version+ '</span>'             + '</div><div style="padding-left:10px;padding-right:10px;padding-bottom:5px">'             + 'Changes the image for selected token IF the tokens are from a Rollable Table.'             + '<span style="color:#FF0000;">Currently works <b>ONLY</b> if images are in your personal library!</span>'             + '</div><div>'             + '<span style="border-bottom:1px;font-weight:bold">Usage:</span>'             + '</div><div style="padding-left:10px;padding-right:10px;padding-bottom:5px">'             + 'select token(s) to change, then type '             + '<br/><b>!change-token-img</b> '             + '<br/>with one of the following options.'              + '</div><div>'             + '<span style="border-bottom:1px;font-weight:bold">Type of change:</span>'             + '</div><div style="padding-left:10px;padding-right:10px;padding-bottom:5px">'             + '<b>--flip</b> Flips image between 0 and 1 '             + '<br/><b>--set</b> Set the image index, must be followed by a space and a number: --set 3 sets the token to the 4th image in the rollable table. '             + '<br/><b>--incr</b> Increments the token to the next image in the rollable table '             + '</div><div>'             + '<br/><span style="border-bottom:1px;font-weight:bold">Modifiers:</span>'             + '</div><div style="padding-left:10px;padding-right:10px;padding-bottom:5px">'             + 'These can be used with any of the above options:'             + '<br/><b>--notsame</b> Asserts scripts should NOT assume all tokens have same rollable table of images. Default is '             + 'script assumes all selected tokens use same images.'             + '</div><div>'             + '<br/><span style="border-bottom:1px;font-weight:bold">Examples:</span>'             + '</div><div style="padding-left:10px;padding-right:10px;padding-bottom:5px">'             + '<b>!change-token-img --set 2 --notsame</b> change all tokens to image in index 2 (3rd image) of rollable table. For each token, '             + 'check the rollable table for images, do NOT assume all tokens are the same.'             + '<br/><b>!change-token-img --flip</b> for all selected tokens, check their current image displayed. If it is the first image, flip '             + 'token to the second image. If it is set to the second image, then flip token to the first image. All tokens have the same rollable table of images.'             + '<br/><b>!change-token-img --set 0</b> Set all tokens to the first image, assume they are all the same.'             + '</div>'         );     },     showError = function(id,n,tname,errortype) {         var who=(getObj('player',id)||{get:()=>'API'}).get('_displayname');         var errorstr = 'ChangeTokenImg: ';         if (errortype == 'SIDES') {             var sidestr='s';             if (n == 1) {                 sidestr='';             }             errorstr = tname+' has only ' + n + ' side'+sidestr+'!';         } else if (errortype == 'EMPTY') {             errorstr = 'You must pick --flip, --set or --incr';         } else if (errortype == 'ARG') {             errorstr = n + ' is not a valid value for set parameter';                     }         sendChat('', `/w "${who}" <div>${errorstr}</div>`);     },         getCleanImagesrc = function (imgsrc) {         var parts = imgsrc.match(/(.*\/images\/.*)(thumb|max)(.*)$/);         if(parts) {             return parts[1]+'thumb'+parts[3];         }         return;     },     setImg = function (o,nextSide,allSides) {         var nextURL = getCleanImagesrc(decodeURIComponent(allSides[nextSide]));         o.set({             currentSide: nextSide,             imgsrc: nextURL         });         return nextURL;     },     setImgUrl = function (o, nextSide, nextURL) {         o.set({             currentSide: nextSide,             imgsrc: getCleanImagesrc(nextURL)         });     },     isInt = function (value) {         return !(value === undefined) &&  !isNaN(value) && parseInt(Number(value)) == value && !isNaN(parseInt(value, 10)) && value >= 0;     },     handleInput = function(msg_orig) {         var msg = (msg_orig),         args, cmds,  allSides=[],  nextSide, nextURL, flipimg, setimg, incrementimg, sameimages, setval;         flipimg = false;         setimg = false;         sameimages = false;         incrementimg = false;         nextURL='BLANK';         if (msg.type !== "api") {             return;         }         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();         }         args = msg.content         .replace(/<br\/>\n/g, ' ')         .replace(/(\{\{(.*?)\}\})/g," $2 ")         .split(/\s+--/);         var isthismethod= false;         switch(args.shift()) {             case '!change-token-img':                 isthismethod=true;                 while(args.length) {                     cmds=args.shift().match(/([^\s]+[|#]'[^']+'|[^\s]+[|#]"[^"]+"|[^\s]+)/g);                     switch(cmds.shift()) {                         case 'help':                             showHelp(msg.playerid);                             return;                         case 'set':                             if(cmds.length){                                 setimg = true;                                 setval =  cmds.shift();                                 if (! isInt(setval)) {                                     showError(msg.playerid,setval,'','ARG');                                     return;                                 }                             } else {                                 showHelp(msg.playerid);                                 return;                             }                             break;                         case 'flip':                             flipimg = true;                             break;                         case 'incr':                             incrementimg = true;                             break;                         case 'notsame':                             sameimages = false;                             break;                     }                 }         }         if (isthismethod == false) {             return;         }         if (setimg == false && flipimg == false && incrementimg == false ) {             showError(msg.playerid,'','','EMPTY');             return;         } else {             //loop through selected tokens             _.chain(msg.selected)             .uniq()             .map(function(o){                 return getObj('graphic',o._id);             })             .reject(_.isUndefined)             .each(function(o) {                 if (sameimages == false || allSides === undefined || allSides.length == 0  ) {                     allSides = o.get("sides").split("|");                 }                 if ( allSides.length > 1) {                     if (setimg == true) {                         nextSide = setval;                     } else {                         nextSide = o.get("currentSide") ;                         nextSide++;                         if (flipimg == true && nextSide > 1) {                             nextSide = 0;                         } else if (nextSide == allSides.length) {                             nextSide = 0;                         }                     }                     if (nextSide >= allSides.length) {                         showError(msg.playerid,allSides.length,o.get("name"),'SIDES');                         if (sameimages == true) {                             //quit since they are all the same                             return;                         }                     } else {                         let prev=JSON.parse(JSON.stringify(o));                         if (nextURL == 'BLANK' || sameimages == false) {                             nextURL = setImg(o,nextSide,allSides);                         } else {                             setImgUrl(o,nextSide,nextURL);                         }                         notifyObservers('tokenChange',o,prev);                     }                 } else {                     showError(msg.playerid,allSides.length,o.get("name"),'SIDES');                     if (sameimages == true) {                         //quit since they are all the same                         return;                     }                 }             });         }     },     observeTokenChange = function(handler){         if(handler && _.isFunction(handler)){             observers.tokenChange.push(handler);         }     },     notifyObservers = function(event,obj,prev){         _.each(observers[event],function(handler){             handler(obj,prev);         });     },     checkInstall = function() {         log('-=> ChangeTokenImg v'+version+' <=-  ['+(new Date(lastUpdate*1000))+']');     },     registerEventHandlers = function() {         on('chat:message', handleInput);     };     return {         CheckInstall: checkInstall,         RegisterEventHandlers: registerEventHandlers,         ObserveTokenChange: observeTokenChange     }; }()); on("ready",function(){     'use strict';     ChangeTokenImg.CheckInstall();     ChangeTokenImg.RegisterEventHandlers(); });
1509083159
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
What are the major differences between your version and the One-Click?
Judging by the answer I assume it is not possible using a macro? Would like to track time by using a token and macros.
1509107576
The Aaron
Pro
API Scripter
keithcurtis said: What are the major differences between your version and the One-Click? Hmm.. good question.. looks like nothing?&nbsp; Ah... I pushed up my changes to the repo:&nbsp; <a href="https://github.com/Roll20/roll20-api-scripts/commi" rel="nofollow">https://github.com/Roll20/roll20-api-scripts/commi</a>... I don't usually do that for other people's API scripts, but in this case it was causing crashes.
1509107622
The Aaron
Pro
API Scripter
Mattias H. said: Judging by the answer I assume it is not possible using a macro? Would like to track time by using a token and macros. Correct, the only way to automate it is via the API.
1509185160

Edited 1509186784
Nox
Translator
The Aaron said: Correct, the only way to automate it is via the API. Thanks a lot Aron!! As always you solve all my problems! Edit: Err... I got this, and the script doesn't&nbsp;flip the image :( what did I do wrong? i'm using also token mod and token number. TypeError: Cannot read property 'substring' of undefined TypeError: Cannot read property 'substring' of undefined at TrackedObj._validateAttrs (/home/node/d20-api-server/api.js:787:21) at TrackedObj.set (/home/node/d20-api-server/api.js:858:18) at setImg (apiscript.js:4716:11) at apiscript.js:4843:39 at Function._.each._.forEach (/home/node/d20-api-server/node_modules/underscore/underscore.js:153:9) at _.(anonymous function) [as each] (/home/node/d20-api-server/node_modules/underscore/underscore.js:1496:34) at handleInput (apiscript.js:4818:14) at eval (eval at (/home/node/d20-api-server/api.js:146:1), :65:16) at Object.publish (eval at (/home/node/d20-api-server/api.js:146:1), :70:8) at /home/node/d20-api-server/api.js:1510:12
1509190375

Edited 1509190401
The Aaron
Pro
API Scripter
Hmm... hard to say from that error message. If you want to PM me an invite, I’ll come look.&nbsp;
1509192716
The Aaron
Pro
API Scripter
Hmm... I'm going to guess that some of your Rollable Table Token images are not in a User Library, but are in the Marketplace. Try this version, it should tell you that's the case instead of crashing: // By:&nbsp; &nbsp; &nbsp; &nbsp;Christopher Buchholz //&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;with heavy copying from, I mean use of as a Pattern, TokenMod var ChangeTokenImg = ChangeTokenImg || (function() { &nbsp; &nbsp; 'use strict'; &nbsp; &nbsp; var version = '0.1.32', &nbsp; &nbsp; lastUpdate = 1509192678, &nbsp; &nbsp; observers = { &nbsp; &nbsp; &nbsp; &nbsp; tokenChange: [] &nbsp; &nbsp; }, &nbsp; &nbsp; showHelp = function(id) { &nbsp; &nbsp; &nbsp; &nbsp; var who=getObj('player',id).get('_displayname').split(' ')[0]; &nbsp; &nbsp; &nbsp; &nbsp; sendChat('', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '/w '+who+' &lt;div style="border: 1px solid black; background-color: white; padding: 3px 3px"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;div style="padding-bottom:5px"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;span style="font-size:130%;border-bottom:1px;font-weight:bold"&gt;ChangeTokenImg v'+version+ '&lt;/span&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;/div&gt;&lt;div style="padding-left:10px;padding-right:10px;padding-bottom:5px"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 'Changes the image for selected token IF the tokens are from a Rollable Table.' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;span style="color:#FF0000;"&gt;Currently works &lt;b&gt;ONLY&lt;/b&gt; if images are in your personal library!&lt;/span&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;/div&gt;&lt;div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;span style="border-bottom:1px;font-weight:bold"&gt;Usage:&lt;/span&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;/div&gt;&lt;div style="padding-left:10px;padding-right:10px;padding-bottom:5px"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 'select token(s) to change, then type ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;br/&gt;&lt;b&gt;!change-token-img&lt;/b&gt; ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;br/&gt;with one of the following options.'&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;/div&gt;&lt;div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;span style="border-bottom:1px;font-weight:bold"&gt;Type of change:&lt;/span&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;/div&gt;&lt;div style="padding-left:10px;padding-right:10px;padding-bottom:5px"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;b&gt;--flip&lt;/b&gt; Flips image between 0 and 1 ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;br/&gt;&lt;b&gt;--set&lt;/b&gt; Set the image index, must be followed by a space and a number: --set 3 sets the token to the 4th image in the rollable table. ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;br/&gt;&lt;b&gt;--incr&lt;/b&gt; Increments the token to the next image in the rollable table ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;/div&gt;&lt;div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;br/&gt;&lt;span style="border-bottom:1px;font-weight:bold"&gt;Modifiers:&lt;/span&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;/div&gt;&lt;div style="padding-left:10px;padding-right:10px;padding-bottom:5px"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 'These can be used with any of the above options:' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;br/&gt;&lt;b&gt;--notsame&lt;/b&gt; Asserts scripts should NOT assume all tokens have same rollable table of images. Default is ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 'script assumes all selected tokens use same images.' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;/div&gt;&lt;div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;br/&gt;&lt;span style="border-bottom:1px;font-weight:bold"&gt;Examples:&lt;/span&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;/div&gt;&lt;div style="padding-left:10px;padding-right:10px;padding-bottom:5px"&gt;' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;b&gt;!change-token-img --set 2 --notsame&lt;/b&gt; change all tokens to image in index 2 (3rd image) of rollable table. For each token, ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 'check the rollable table for images, do NOT assume all tokens are the same.' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;br/&gt;&lt;b&gt;!change-token-img --flip&lt;/b&gt; for all selected tokens, check their current image displayed. If it is the first image, flip ' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + 'token to the second image. If it is set to the second image, then flip token to the first image. All tokens have the same rollable table of images.' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;br/&gt;&lt;b&gt;!change-token-img --set 0&lt;/b&gt; Set all tokens to the first image, assume they are all the same.' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + '&lt;/div&gt;' &nbsp; &nbsp; &nbsp; &nbsp; ); &nbsp; &nbsp; }, &nbsp; &nbsp; showError = function(id,n,tname,errortype) { &nbsp; &nbsp; &nbsp; &nbsp; var who=(getObj('player',id)||{get:()=&gt;'API'}).get('_displayname'); &nbsp; &nbsp; &nbsp; &nbsp; var errorstr = 'ChangeTokenImg: '; &nbsp; &nbsp; &nbsp; &nbsp; if (errortype == 'SIDES') { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sidestr='s'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (n == 1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sidestr=''; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; errorstr = tname+' has only ' + n + ' side'+sidestr+'!'; &nbsp; &nbsp; &nbsp; &nbsp; } else if (errortype == 'EMPTY') { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; errorstr = 'You must pick --flip, --set or --incr'; &nbsp; &nbsp; &nbsp; &nbsp; } else if (errortype == 'ARG') { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; errorstr = n + ' is not a valid value for set parameter';&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; sendChat('', `/w "${who}" &lt;div&gt;${errorstr}&lt;/div&gt;`); &nbsp; &nbsp; },&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; getCleanImagesrc = function (imgsrc) { &nbsp; &nbsp; &nbsp; &nbsp; var parts = imgsrc.match(/(.*\/images\/.*)(thumb|max)(.*)$/); &nbsp; &nbsp; &nbsp; &nbsp; if(parts) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return parts[1]+'thumb'+parts[3]; &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,allSides[nextSide]); } &nbsp; &nbsp; &nbsp; &nbsp; return nextURL; &nbsp; &nbsp; }, &nbsp; &nbsp; setImgUrl = function (o, nextSide, nextURL) { &nbsp; &nbsp; &nbsp; &nbsp; var imgURL = getCleanImagesrc(nextURL); if(imgURL){ o.set({ currentSide: nextSide, imgsrc: imgURL }); } else { report(o,nextURL); } &nbsp; &nbsp; }, &nbsp; &nbsp; isInt = function (value) { &nbsp; &nbsp; &nbsp; &nbsp; return !(value === undefined) &&&nbsp; !isNaN(value) && parseInt(Number(value)) == value && !isNaN(parseInt(value, 10)) && value &gt;= 0; &nbsp; &nbsp; }, &nbsp; &nbsp; handleInput = function(msg_orig) { &nbsp; &nbsp; &nbsp; &nbsp; var msg = (msg_orig), &nbsp; &nbsp; &nbsp; &nbsp; args, cmds,&nbsp; allSides=[],&nbsp; nextSide, nextURL, flipimg, setimg, incrementimg, sameimages, setval; &nbsp; &nbsp; &nbsp; &nbsp; flipimg = false; &nbsp; &nbsp; &nbsp; &nbsp; setimg = false; &nbsp; &nbsp; &nbsp; &nbsp; sameimages = false; &nbsp; &nbsp; &nbsp; &nbsp; incrementimg = false; &nbsp; &nbsp; &nbsp; &nbsp; nextURL='BLANK'; &nbsp; &nbsp; &nbsp; &nbsp; if (msg.type !== "api") { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; if(_.has(msg,'inlinerolls')){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; msg.content = _.chain(msg.inlinerolls) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .reduce(function(m,v,k){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var ti=_.reduce(v.results.rolls,function(m2,v2){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(_.has(v2,'table')){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m2.push(_.reduce(v2.results,function(m3,v3){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m3.push(v3.tableItem.name); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return m3; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },[]).join(', ')); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return m2; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },[]).join(', '); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m['$[['+k+']]']= (ti.length && ti) || v.results.total || 0; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return m; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },{}) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .reduce(function(m,v,k){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return m.replace(k,v); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },msg.content) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .value(); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; args = msg.content &nbsp; &nbsp; &nbsp; &nbsp; .replace(/&lt;br\/&gt;\n/g, ' ') &nbsp; &nbsp; &nbsp; &nbsp; .replace(/(\{\{(.*?)\}\})/g," $2 ") &nbsp; &nbsp; &nbsp; &nbsp; .split(/\s+--/); &nbsp; &nbsp; &nbsp; &nbsp; var isthismethod= false; &nbsp; &nbsp; &nbsp; &nbsp; switch(args.shift()) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case '!change-token-img': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isthismethod=true; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while(args.length) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cmds=args.shift().match(/([^\s]+[|#]'[^']+'|[^\s]+[|#]"[^"]+"|[^\s]+)/g); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch(cmds.shift()) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'help': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showHelp(msg.playerid); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'set': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(cmds.length){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setimg = true; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setval =&nbsp; cmds.shift(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (! isInt(setval)) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showError(msg.playerid,setval,'','ARG'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &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; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showHelp(msg.playerid); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'flip': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; flipimg = true; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'incr': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; incrementimg = true; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 'notsame': &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sameimages = false; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; if (isthismethod == false) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; if (setimg == false && flipimg == false && incrementimg == false ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showError(msg.playerid,'','','EMPTY'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //loop through selected tokens &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _.chain(msg.selected) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .uniq() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map(function(o){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return getObj('graphic',o._id); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .reject(_.isUndefined) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .each(function(o) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (sameimages == false || allSides === undefined || allSides.length == 0&nbsp; ) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; allSides = o.get("sides").split("|"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ( allSides.length &gt; 1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (setimg == true) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nextSide = setval; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nextSide = o.get("currentSide") ; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nextSide++; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (flipimg == true && nextSide &gt; 1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nextSide = 0; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (nextSide == allSides.length) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nextSide = 0; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (nextSide &gt;= allSides.length) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showError(msg.playerid,allSides.length,o.get("name"),'SIDES'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (sameimages == true) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //quit since they are all the same &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &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; &nbsp; &nbsp; let prev=JSON.parse(JSON.stringify(o)); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (nextURL == 'BLANK' || sameimages == false) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nextURL = setImg(o,nextSide,allSides); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setImgUrl(o,nextSide,nextURL); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; notifyObservers('tokenChange',o,prev); &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; showError(msg.playerid,allSides.length,o.get("name"),'SIDES'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (sameimages == true) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //quit since they are all the same &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, &nbsp; &nbsp; observeTokenChange = function(handler){ &nbsp; &nbsp; &nbsp; &nbsp; if(handler && _.isFunction(handler)){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; observers.tokenChange.push(handler); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; }, &nbsp; &nbsp; notifyObservers = function(event,obj,prev){ &nbsp; &nbsp; &nbsp; &nbsp; _.each(observers[event],function(handler){ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handler(obj,prev); &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; }, &nbsp; &nbsp; checkInstall = function() { &nbsp; &nbsp; &nbsp; &nbsp; log('-=&gt; ChangeTokenImg v'+version+' &lt;=-&nbsp; ['+(new Date(lastUpdate*1000))+']'); &nbsp; &nbsp; }, &nbsp; &nbsp; registerEventHandlers = function() { &nbsp; &nbsp; &nbsp; &nbsp; on('chat:message', handleInput); &nbsp; &nbsp; }; &nbsp; &nbsp; return { &nbsp; &nbsp; &nbsp; &nbsp; CheckInstall: checkInstall, &nbsp; &nbsp; &nbsp; &nbsp; RegisterEventHandlers: registerEventHandlers, &nbsp; &nbsp; &nbsp; &nbsp; ObserveTokenChange: observeTokenChange &nbsp; &nbsp; }; }()); on("ready",function(){ &nbsp; &nbsp; 'use strict'; &nbsp; &nbsp; ChangeTokenImg.CheckInstall(); &nbsp; &nbsp; ChangeTokenImg.RegisterEventHandlers(); });
1509571144
The Aaron
Pro
API Scripter
Ah, tracked this issue down.&nbsp; I pushed a new version to the repo, but you can get it here:&nbsp; <a href="https://github.com/shdwjk/roll20-api-scripts/blob/" rel="nofollow">https://github.com/shdwjk/roll20-api-scripts/blob/</a>... The issue turned out to be that the images dragged in on the Rollable Table Token had the med.png version, which the script's older copy of GetCleanImagesrc was failing to properly filter.