This should get you the first part: class Util {
static Roll20Type(o) {
const validTypes = [
'ability', 'attribute', 'campaign', 'card', 'character', 'deck',
'graphic', 'hand', 'handout', 'jukeboxtrack', 'macro', 'message', 'page',
'path', 'player', 'rollabletable', 'tableitem', 'text', 'token'
];
if('function' === typeof o.get){
let t = o.get('type');
if(validTypes.includes(t)){
return t;
}
}
}
static Roll20MapObjectType(o) {
const validTypes = ['path','text','graphic'];
let t = Util.Roll20Type(o);
if(validTypes.includes(t)){
return t;
}
}
}
const findNearObjs = (location, predicate=()=>true, filterProps={}) => {
let x=0;
let y=0;
let pageid = Campaign().get('playerpageid');
let pred = predicate;
if(Util.Roll20MapObjectType(location)){
pred = (o,d)=>location.id !== o.id && predicate(o,d);
x = location.get('left');
y = location.get('top');
pageid= location.get('pageid');
} else {
x = location.x || x;
y = location.y || y;
pageid = location.pageid || pageid;
}
const distSq = (obj) => Math.pow((obj.get('left')-x),2)+Math.pow((obj.get('top')-y),2);
const compareDistSq = (a,b) => a.distSq-b.distSq;
return findObjs({ pageid, ...filterProps })
.map(o=>({distSq:distSq(o),object:o}))
.filter((o)=>pred(o.object,o.distSq))
.sort(compareDistSq);
};
const brightLightFilter = (o,distSq)=> (o.get('emits_bright_light') && Math.pow(o.get('bright_light_distance'),2)>distSq);
// for some token:
let candidates = findNearObjs(token,brightLightFilter,{type:'graphic'});