FYI, in case anyone is interested I modified Aaron's script to optionally create an actual rollable table object with the images as well (to make later minor editing like replacing one image easier). No options for weighting or showplayers (sets to 1 and false), because I basically never use weights for image tables and showplayers is just clicking a checkbox for what would be a minority of cases. Syntax: !make-rtt //only creates token !make-rtt --Table Name Can Include Spaces //creates token and rollable table Here's the macro I'm using: !make-rtt --?{Enter Table Name (or leave blank to just create the token)} The modified script: on('ready',()=>{
const s = {
err: "padding: 1px 1em; size:.8em; font-weight:bold; background: #cccccc; border:2px solid black; border-radius:1em; color: #990000;"
};
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 positionalSorter = (a,b) => {
let at = Math.round((a.get('top')+17)/35);
let bt = Math.round((b.get('top')+17)/35);
let al = Math.round((a.get('left')+17)/35);
let bl = Math.round((b.get('left')+17)/35);
let abt = at-bt;
let abl = al-bl;
return (0 === abt ? abl : abt);
};
const findTraits = (b) => (o) => {
let x = parseFloat(o.get('left'));
let y = parseFloat(o.get('top'));
let w = parseFloat(o.get('width'));
let h = parseFloat(o.get('height'));
b.minX = Math.min(b.minX,x-(w/2));
b.minY = Math.min(b.minY,y-(h/2));
b.maxX = Math.max(b.minX,x+(w/2));
b.maxY = Math.max(b.minY,y+(h/2));
b.layer = o.get('layer');
b.pageid = o.get('pageid');
return o;
};
on('chat:message',msg=>{
if('api'===msg.type && /^!make-rtt(\b\s|$)/i.test(msg.content) && playerIsGM(msg.playerid)){
let who = (getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname');
let traits = {
minX: Number.MAX_SAFE_INTEGER,
minY: Number.MAX_SAFE_INTEGER,
maxX: -Number.MAX_SAFE_INTEGER,
maxY: -Number.MAX_SAFE_INTEGER,
layer: 'objects',
pageid: ''
};
if(0===(msg.selected||[].length)){
sendChat('',`/w "${who}" <div style="${s.err}">Please selected some tokens.</div>`);
return;
}
let tableName;
let args = msg.content.split(/\s+--/);
if (args.length > 1) {
tableName = args[1].trim();
}
let images = (msg.selected || [])
.map(o=>getObj('graphic',o._id))
.filter(g=>undefined !== g)
.sort(positionalSorter)
.map(findTraits(traits))
.reduce((m,g)=>{
let i = getCleanImgsrc(g.get('imgsrc'));
if(i){
m.push(i);
} else {
g.set('status_dead',true);
}
return m;
},[]);
if(images.length){
let token = createObj('graphic',{
pageid: traits.pageid,
layer: traits.layer,
left: traits.minX||0,
top: traits.minY||0,
width: 70,
height: 70,
imgsrc: images[0],
sides: images.map(encodeURIComponent).join('|')
});
if(token){
toFront(token);
} else {
sendChat('',`/w "${who}" <div style="${s.err}">Failed to create token!</div>`);
}
if (tableName) {
let table = createObj('rollabletable',{
name: tableName,
showplayers: false
});
if (table) {
let tableID = table.get('_id');
images.forEach(img => {
let tableItem = createObj('tableitem',{
rollabletableid: tableID,
avatar: img,
name: '',
weight: 1
});
});
} else {
sendChat('',`/w "${who}" <div style="${s.err}">Failed to create rollable table!</div>`);
}
}
} else {
sendChat('',`/w "${who}" <div style="${s.err}">Only marketplace images found!</div>`);
}
}
});
});