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

[Script Modification Request] Flight - ability to set Status Marker with no number

1615239409

Edited 1615398810
Currently the Flight script will add a number of markers that are labeled in order for whatever height you want to display, and I've got that working well.  But I would like the ability to add a single blank marker of that type if no number is provided, and I'm hoping the script would be relatively easy to modify. There's also no way to add a single marker labeled with a '0' (for instance if a character has a temporary Flying speed from the 'Fly' spell being cast on them, but they are not currently in the air). Thanks for any help you're able to provide! I wasn't able to find an obvious, easy modification, so I'll have to rely on anyone who has more scripting skills than myself! :)
1615399432
I just realized that I didn't include a working link to the script, so I edited it above.  Here's a link to Flight version 3.5 that I'm looking at specifically. I'm pretty sure the portion that needs to be modified is here:     function markStatus(marker, num, selected) {         var markerStr = '',             token, markers;         if (!selected) return;         selected = _.reject(selected, (o) => o._type !== 'graphic');         if (!selected.length) return;         if(num) {             markerStr = _.chain(num.toString().split(''))                 .map((d) => `${marker}@${d}`)                 .value()                 .join(',');         }         _.each(selected, (obj) => {             token = getObj('graphic', obj._id);             if (token && token.get('subtype') === 'token') {                 token.set(`status_${marker}`, false);                 markers = token.get('statusmarkers');                 markers = markers ? markers.trim() : '';                 markers += (markers.length ? ',' : '') + markerStr;                 token.set('statusmarkers', markers);             }         });     } I'm still trying to figure out why using  !fly 0  doesn't result in a single marker being added to the token with a '0' on it; instead it removes all markers.
1615404872
The Aaron
Forum Champion
API Scripter
I've got my eye on this, I'm hoping to write that for you this evening.  I actually have a rewrite of the flight script called FlyMore, that I think is a bit better (it also handles depth, for example).  I'll probably give you a custom version of that, if that's ok.
1615408073
David M.
Pro
API Scripter
Ok, thank goodness, Aaron. I was literally about to post a very kludge-y non-javascripty hack job bastardization of the script that technically does what Jarren asked but would be very embarrassing. It felt like I was putting a face tattoo on the Mona Lisa.
1615408741
The Aaron
Forum Champion
API Scripter
Lol. =D FlyMore will also support relative changes, like flying up 20ft or down 20ft.
1615413502
The Aaron said: I've got my eye on this, I'm hoping to write that for you this evening.  I actually have a rewrite of the flight script called FlyMore, that I think is a bit better (it also handles depth, for example).  I'll probably give you a custom version of that, if that's ok. Oh that would be amazing!  My players will likely have a combat during our game this weekend where flying height is going to be important, and I've been trying to figure out the easiest way to keep track of it without doing it manually. :)
1615438622
The Aaron
Forum Champion
API Scripter
OK, here's my FlyMore script. Edit the statuses at the top to whatever you like.  Note: you can have the groundStatus and upStatus set to the same thing with no problems. Call it with !fly: !fly 25 !fly [NUMBER]  with tokens selected.  NUMBER  can be prefaced with an operation from among:  + ,  - ,  * ,  / , or  = . Prefacing with an operation will make a relative change, for example,  !fly -20  will reduce the selected token elevation by 20. Note: to explicitly set a negative  elevation, preface with  = , for example,  !fly =-20  will set the elevation to -20 no matter where it is currently. Code: on('ready', () => { const upStatus = 'green'; const groundStatus = 'blue'; 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(entry.mark.length) { memo[entry.mark] = ( memo[entry.mark] && memo[entry.mark].push(entry) && memo[entry.mark]) || [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 = (op) => { let applyOp = (e) => { let n = Math.round(op(e)); if(0 !== n) { return { [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 })) }; } return {[groundStatus]:[{mark:groundStatus,num:'',idx:10000}]}; }; const clean = (sm) => { delete sm[downStatus]; delete sm[groundStatus]; delete sm[upStatus]; return sm; }; const getElevation = (sm) => { let accum=0; let marks = [upStatus,downStatus,groundStatus]; let mark = marks.find(s=>sm.hasOwnProperty(s)); let dir = (mark === downStatus) ? -1 : 1; if(mark){ sm[mark].find(e=>{ if(Number.isInteger(e.num)){ accum*=10; accum+=e.num; return false; } return true; }); } return dir*accum; }; const set = (sm,e) => ({...sm,...applyOp(e)}); return (t) => { let sm = decomposeStatuses(t.get('statusmarkers')); let e = getElevation(sm); t.set({ statusmarkers: composeStatuses(set(clean(sm),e)) }); }; }; 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; } }; const getChangeOp = (change) => { const ops = { '+': (a,b)=>a+b, '-': (a,b)=>a-b, '/': (a,b)=>a/(b||1), '*': (a,b)=>a*b, '!': (a,b)=>(a?0:b), '=': (a,b)=>b }; let txt = `${change}`; let op = (ops.hasOwnProperty(txt[0]) ? txt[0] : "="); let num = parseInt(txt.slice((txt[0]===op) ? 1 : 0)); return (n)=>ops[op](n,num); }; 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. <code>NUMBER</code> can be prefaced with an operation from among: <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>, or <code>=</code>. Prefacing with an operation will make a relative change, for example, <code>!fly -20</code> will reduce the selected token elevation by 20. Note: to explicitly set a negative elevation, preface with <code>=</code>, for example, <code>!fly =-20</code> will set the elevation to -20 no matter where it is currently.</div>`); return; } let op = getChangeOp(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(op); tokens.map(ss); } }); });