Here ya go. Toggle them to be changing with this command: !toggle-switching Then each selected token will start changing its side randomly. Tokens without multiple sides are ignored. If there are multiple sides, they will always pick a different side. Note, only sides that are a user library can be chosen, so marketplace images will need to be downloaded and re-uploaded to a user library. Each token will individually choose a random point to change between 10-15 seconds from when they are toggled on, and will choose a new point 10-15 seconds after each change. Script: on('ready',()=>{
const scriptName = 'RandomSideSwitch';
const version = '0.1.0';
const schemaVersion = 0.1;
const lastUpdate = 1643297414;
const CHANGE_MIN = 10;
const CHANGE_MAX = 15;
const checkInstall = () => {
log(`-=> ${scriptName} v${version} <=- [${lastUpdate}]`);
if (
!state.hasOwnProperty(scriptName) ||
state[scriptName].version !== schemaVersion
) {
log(` > Updating Schema to v${schemaVersion} <`);
switch (state[scriptName] && state[scriptName].version) {
case 0.1:
/* break; // intentional dropthrough */ /* falls through */
case "UpdateSchemaVersion":
state[scriptName].version = schemaVersion;
break;
default:
state[scriptName] = {
version: schemaVersion,
options: {},
tokenMap: {}
};
break;
}
}
};
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 setTokenSide = (token, side) => {
let sides = token.get('sides').split(/\|/).map(decodeURIComponent).map(getCleanImgsrc);
if('*'===side){
let cside = token.get('currentSide');
let keys = Object.keys(sides).filter(n=>cside != n);
if(keys.length){
side = keys[randomInteger(keys.length)-1];
} else {
side = cside;
}
} else {
side = Math.min(sides.length-1, Math.max(0, side));
}
if(sides[side]){
token.set({
currentSide: side,
imgsrc: sides[side]
});
} else {
log(`ERROR: "${token.get('name')}" (id: ${token.id}) does not have a user image at index ${side}!`);
}
};
const checkTokens = () => {
let now = Date.now();
Object.keys(state[scriptName].tokenMap).forEach(t=>{
if(state[scriptName].tokenMap[t].nextChange < now){
let token = getObj('graphic',t);
if(token){
setTokenSide(token,'*');
state[scriptName].tokenMap[t].nextChange = now + (CHANGE_MIN + randomInteger(CHANGE_MAX-CHANGE_MIN))*1000;
} else {
delete state[scriptName].tokenMap[t];
}
}
});
};
let interval = setInterval(checkTokens,1000);
on('chat:message',msg=>{
if('api'===msg.type && /^!toggle-switching(\b\s|$)/i.test(msg.content) && playerIsGM(msg.playerid)){
let who = (getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname');
let now = Date.now();
(msg.selected || [])
.map(o=>getObj('graphic',o._id))
.filter(g=>undefined !== g)
.forEach(token=>{
if(state[scriptName].tokenMap.hasOwnProperty(token.id)){
delete state[scriptName].tokenMap[token.id];
} else if(token.get('sides').length) {
state[scriptName].tokenMap[token.id] = {
nextChange: now + (CHANGE_MIN + randomInteger(CHANGE_MAX-CHANGE_MIN))*1000
};
}
})
;
}
});
checkInstall();
});