Depending on how you are setting things up, using TokenMod to set the name with an appended elevation can be pretty useful: !token-mod --set name|"@{selected|character_name} [?{Elevation}m]" ... So I was going to hack the existing fly script to add positive and negative values, but that was obnoxious for a few reasons, so I just rewrote it. Works just like the old one but supports positive and negative numbers. (Positive are on green, negative are on red) Edit the upStatus and downStatus with the tag names of other statuses if you want something different (look at the help for TokenMod for the tag names of the format: marker::1234 ) The code: on('ready', () => {
const upStatus = 'green';
const downStatus = 'red';
const decomposeStatuses = (statuses) =>
statuses.split(/,/).reduce((memo,st,idx) => {
let parts=st.split(/@/);
let entry = {
mark: parts[0],
num: parseInt(parts[1],10),
idx: idx
};
if(isNaN(entry.num)){
entry.num='';
}
if(parts[0].length) {
memo[parts[0]] = ( memo[parts[0]] && memo[parts[0]].push(entry) && memo[parts[0]]) || [entry] ;
}
return memo;
},{});
const composeStatuses = (statuses) =>
Object.keys(statuses).reduce((m,k) => {
statuses[k].forEach((sd)=>m.push(sd));
return m;
},[])
.sort((a,b)=>a.idx-b.idx)
.map( (s) => ('dead'===s.mark ? 'dead' : ( s.mark+(s.num!=='' ? '@'+s.num : ''))) )
.join(',');
const statusSetter = (n) => {
let s = {
[n>0?upStatus:downStatus]:
n.toString()
.split('')
.filter(c=>/\d/.test(c))
.map((c,i) => ({
mark: (n>0 ? upStatus : downStatus),
num: c,
idx: 10000+i
}))
};
const clean = (sm) => {
delete sm[ (n>0 ? downStatus : upStatus) ];
return sm;
};
const set = (sm) => ({...sm,...s});
return (t) => t.set({
statusmarkers: composeStatuses(set(clean(decomposeStatuses(t.get('statusmarkers')))))
});
};
const processInlinerolls = (msg) => {
if(msg.hasOwnProperty('inlinerolls')){
return msg.inlinerolls
.reduce((m,v,k) => {
let ti=v.results.rolls.reduce((m2,v2) => {
if(v2.hasOwnProperty('table')){
m2.push(v2.results.reduce((m3,v3) => [...m3,v3.tableItem.name],[]).join(", "));
}
return m2;
},[]).join(', ');
return [...m,{k:`$[[${k}]]`, v:(ti.length && ti) || v.results.total || 0}];
},[])
.reduce((m,o) => m.replace(o.k,o.v), msg.content);
} else {
return msg.content;
}
};
on('chat:message',msg=>{
if('api'===msg.type && /^!fly(\b\s|$)/i.test(msg.content) ){
let who = (getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname');
let args = processInlinerolls(msg).split(/\s+/);
if(args.length < 2) {
sendChat('fly', `/w "${who}" <div><b>Usage:</b> <code>!fly [NUMBER]</code> with tokens selected.</div>`);
return;
}
let num = parseInt(args[1]);
let tokens = (msg.selected || [])
.map(o => getObj('graphic',o._id))
.filter(t => undefined !== t)
.filter(t => t.get('subtype') === 'token')
;
let ss = statusSetter(num);
tokens.map(ss);
}
});
});