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] RangeAuras - Set a token's auras based on range categories defined in an attribute

1485282284

Edited 1485339002
Elena S.
Sheet Author
YAY, it's all sorted out! The Following Reply from Scriptomancer "The Aaron" has the script! The concept here is to take the range information from a weapon on a character sheet typically input as "<short>/<medium>/<long>" and parse it into an array. The script then applies the designated array index numbers to the aura1_radius and aura2_radius properties of the selected token. The aura colors for different ranges used by the script are also stored in an array, so that when the auras are set they will be automatically given a pre-defined color based on what range the aura is being displayed for. e.g. Short range would always display as Green, Medium as Orange, and Long as Red. Supports up to 7 uniquely colored range categories! If for some reason you have more than that the auras will default to the highest index from the array which stores the aura colors. It also plays well with repeating fieldsets!
1485288199

Edited 1485290723
The Aaron
Pro
API Scripter
Try this, it should cover everything on the To do list: on('ready',function(){     "use strict";     var auraColors = [         '#FF0000', /* Red */         '#FF7F00', /* Orange */         '#FFFF00', /* Yellow */         '#00FF00', /* Green */         '#0000FF', /* Blue */         '#4B0082', /* Indigo */         '#9400D3'  /* Violet */     ],          getRanges = function(desc){       return _.chain((desc||'').match(/(\d+[\s\/\d]*)/g))         .reduce((m,s)=> {             let t=s.split(/\s*\/\s*/);             return (t.length > m.length ? t : m);         },[])         .map((n)=>parseInt(n,10))         .value();     },     bound = (v,l,h) => Math.min(h,Math.max(l,v)),     attrLookup = function(character,name){         let match=name.match(/^(repeating_.*)_\$(\d+)_.*$/);         if(match){             let index=match[2],                 attrMatcher=new RegExp(`^${name.replace(/_\$\d+_/,'_([-\\da-zA-Z]+)_')}$`),                 createOrderKeys=[],                 attrs=_.chain(findObjs({type:'attribute', characterid:character.id}))                     .map((a)=>{                         return {attr:a,match:a.get('name').match(attrMatcher)};                     })                     .filter((o)=>o.match)                     .each((o)=>createOrderKeys.push(o.match[1]))                     .reduce((m,o)=>{ m[o.match[1]]=o.attr; return m;},{})                     .value(),                 sortOrderKeys = _.chain( ((findObjs({                         type:'attribute',                         characterid:character.id,                         name: `_reporder_${match[1]}`                     })[0]||{get:_.noop}).get('current') || '' ).split(/\s*,\s*/))                     .intersection(createOrderKeys)                     .union(createOrderKeys)                     .value();             if(index<sortOrderKeys.length && _.has(attrs,sortOrderKeys[index])){                 return attrs[sortOrderKeys[index]];             }             return;         }          return findObjs({ type:'attribute', characterid:character.id, name: name})[0];     };     on('chat:message',function(msg){         if('api' === msg.type && msg.content.match(/^!aura-range\b/) ){             let args=_.rest(msg.content.split(/\s+/)),                 attrName=(args.shift()||''),                 aura1Index = args.shift()||0,                 aura2Index = args.shift()||1;                              _.chain(msg.selected)                 .pluck('_id')                 .map( (id) => getObj('graphic',id) )                 .reject(_.isUndefined)                 .map( (t) => {return {token:t, character:getObj('character',t.get('represents'))};} )                 .reject( (o)=>_.isUndefined(o.character))                 .map( (o) => { o.attribute = attrLookup(o.character, attrName); return o;} )                 .reject( (o)=>_.isUndefined(o.attribute))                 .map( (o) => { o.ranges = getRanges(o.attribute.get('current')); return o; })                 .each( (o) => {                     o.token.set({                         aura1_color: auraColors[bound(aura1Index,0,auraColors.length-1)],                         aura1_radius: o.ranges[bound(aura1Index,0,o.ranges.length-1)]||0,                         aura2_color: auraColors[bound(aura2Index,0,auraColors.length-1)],                         aura2_radius: o.ranges[bound(aura2Index,0,o.ranges.length-1)]||0                     });                 });         }     }); });
1485288225
The Aaron
Pro
API Scripter
(Big thanks to Jakob for spelling out the steps to handling repeating attributes!)
I know that this can't be solved with auras, but I'd actually love to have the range(s) indicated by circle lines (or even just dotted line circles) instead of filled circle areas. I personally hate these filled aura circles, because they cover too much of the background (especially if you have several tokens and several auras [aurae?] overlapping). I thought about solving this with the AoE script, but that isn't accurate enough... or I'm just too clumsy when drawing the line. So my thought was: Before you are all investing way too much time into this - wouldn't the other approach with circle lines be a bit more "appealing"? Or is it just my personal preference?
1485290188

Edited 1485290454
Elena S.
Sheet Author
Okay, now it works fine when being handed an attribute from a repeating fieldset, but doesn't work when handed a regular attrName.... Totally confused! Not a huge problem, I can just have my players set all of their ranged weapons in the repeating portion of the weapons chart, and put their primary melee weapon in the first fixed weapon slot. But that would be a big problem for character sheets where all of the weapon slots are fixed on the sheet rather than part of a repeating fieldset. Otherwise it's working perfectly as I had hoped! Here's the error code when the script is passed an attribute name which is not part of a repeating fieldset: ReferenceError: attrName is not defined ReferenceError: attrName is not defined at _.chain.map.filter (apiscript.js:4659:77) at apiscript.js:4675:46 at Function._.map._.collect (/home/node/d20-api-server/node_modules/underscore/underscore.js:172:24) at _.(anonymous function) [as map] (/home/node/d20-api-server/node_modules/underscore/underscore.js:1496:34) at apiscript.js:4675:18 at eval (eval at (/home/node/d20-api-server/api.js:146:34), :65:16) at Object.publish (eval at (/home/node/d20-api-server/api.js:146:34), :70:8) at /home/node/d20-api-server/api.js:1489:12 at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:560 at hc (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:39:147)
1485290795
The Aaron
Pro
API Scripter
Copy paste error, I corrected the code above. Arthur, that would definitely be possible.  The major benefit of using an Aura is that you don't have to manage moving objects around.  The benefit of a path would certainly be having more than 2 of them.
Awesome, sweet, spectacular, A-Freaking-Mazing!!!!! All bow to the great Scriptomancer "The Aaron"! @Arthur B The whole multiple overlapping auras issue is part of why I wanted to have a script to turn auras on and off quickly, and why I installed TokenMod initially. TokenMod works great for most of the Aura management with a few simple macros, but I wanted be able to automate pulling the ranges from the character sheet so players won't have to type them in manually (and possibly fudge things). As I'd said in the TokenMod thread, before we spun this little project off to its own thread, I have a branch set of macros for: turning on different range auras fixed spell/ability auras making auras visible and turning them back off The branch macro set also automatically sets aura colors similarly to how the script does so that me and all of my players can tell what a given aura is for just by it's color. I'm hoping that it will all streamline dealing with ranged attacks considerably, while avoiding the visual clutter of overlapping auras. Half of the PC's currently in my campaign use ranged weapons almost exclusively, so I really wanted to have a good solution for setting up and clearing auras quickly. This script automating the range aura branches will definitely simplify things immensely!
1485293509
The Aaron
Pro
API Scripter
By the way, not sure if you noticed, but it will now allow an arbitrary number of ranges (with up to 7 colors, anything higher will just be purple).  for "strange attack 10/20/30/40/50/60/70/80/90/100", you could specify: !aura-range attribute 4,9 to get auras of 50 and 100.
1485296628

Edited 1485296694
Elena S.
Sheet Author
Cool, good to know! I did notice that the range array was no longer bound to a maximum index of 2
1485303605
vÍnce
Pro
Sheet Author
I want to see some images... ;-)
1485304302
The Aaron
Pro
API Scripter
Vince said: I want to see some images... ;-)
1485304729
Stephen S.
Pro
Marketplace Creator
Sheet Author
API Scripter
Those for Vince? Please let them be vorpal kittens.
1485304963
vÍnce
Pro
Sheet Author
It had to be cats...
1485306414
The Aaron
Pro
API Scripter
It's just auras, so the pictures wouldn't look that impressive. =D
1485307022
vÍnce
Pro
Sheet Author
1485308496

Edited 1485308668
Elena S.
Sheet Author
I'll post a link to our game's twitch feed after the next session when you should be able to see the script at work... =) Though as The Aaron said, it won't exactly be flashy
If anyone is interested I can also post copies of the Branch-set macros I have set up for my players to manage their auras. Then you could tweak them to fit the attributes that your character sheet stores the relevant information in. Llet me know.