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

Three dimensional tracking script?

I'm setting up a Spelljammer campaign and need a way to track elevation of the ship tokens.  I know there is a flight script (if anyone has the link), but I also want to track pitch and yaw of the various tokens without having to go to the notes of each.  I'm using the tracker bars for AC, HP, and maneuverability.  Though the last one could be changed, now that I think about it.  Is there an easy script or command to show a value on the token? Help is much appreciated. 
1471238924

Edited 1471240578
Lithl
Pro
Sheet Author
API Scripter
Flight script It wouldn't be too difficult to duplicate the !fly command for other relevant bits of information, although I don't know how using multiple statusmarkers like that would interact. Also, as demonstrated by the screenshot in the README, a large number of digits can make the statusmarkers flow out to the left of the token very quickly, so I don't know if that solution is necessarily viable for you. Edit: here's a new version that would be easier to extend var bshields = bshields || {}; bshields.flight = (function() { &nbsp; &nbsp; 'use strict'; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; var version = 3.4, &nbsp; &nbsp; &nbsp; &nbsp; commands = { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fly: function(args, msg) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var height = parseInt(args[0]) || 0; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; markStatus('fluffy-wing', height, msg.selected); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /** &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* To add new command, use this template: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; commandname: function(args, msg) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var num = parseInt(args[0]) || 0; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; markStatus('statusmarker-name', num, msg.selected); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* Statusmarker names are listed at <a href="https://wiki.roll20.net/API:Objects#Graphic_.28Token.2FMap.2FCard.2FEtc..29" rel="nofollow">https://wiki.roll20.net/API:Objects#Graphic_.28Token.2FMap.2FCard.2FEtc..29</a> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* commandname should be ALL LOWER-CASE and CANNOT contain spaces. If commandname includes anything other than a-z0-9_ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* or if it begins with a number, it must be enclosed in quotes, eg: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'command-name': function... &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; help: function(command, args, msg) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (_.isFunction(commands[`help_${command}`])) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; commands[`help_${command}`](args, msg); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; help_fly: function(args, msg) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat(`Flight v${version}`, 'Specify !fly &'+'lt;number&'+'gt; to add that number as wings on the selected token.'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; function markStatus(marker, num, selected) { &nbsp; &nbsp; &nbsp; &nbsp; var markerStr = '', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; token, markers; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!selected) return; &nbsp; &nbsp; &nbsp; &nbsp; selected = _.reject(selected, (o) =&gt; o._type !== 'graphic'); &nbsp; &nbsp; &nbsp; &nbsp; if (!selected.length) return; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(num) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; markerStr = _.chain(num.toString().split('')) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map((d) =&gt; `${marker}@${d}`) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .value() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .reverse() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .join(','); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _.each(selected, (obj) =&gt; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; token = getObj('graphic', obj._id); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (token && token.get('subtype') === 'token') { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; token.set(`status_${marker}`, false); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; markers = token.get('statusmarkers'); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; markers = markers ? markers.trim() : ''; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; markers += (markers.length ? ',' : '') + markerStr; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; token.set('statusmarkers', markers); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; } &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; function handleInput(msg) { &nbsp; &nbsp; &nbsp; &nbsp; var isApi = msg.type === 'api', &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; args = msg.content.trim().splitArgs(), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; command, arg0, isHelp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (isApi) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; command = args.shift().substring(1).toLowerCase(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; arg0 = args.shift() || ''; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; isHelp = arg0.toLowerCase() === 'help' || arg0.toLowerCase() === 'h' || command === 'help'; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!isHelp) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (arg0 && arg0.length &gt; 0) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; args.unshift(arg0); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (_.isFunction(commands[command])) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; commands[command](args, msg); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (_.isFunction(commands.help)) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; commands.help(command === 'help' ? arg0 : command, args, msg); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; } else if (_.isFunction(commands['msg_' + msg.type])) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; commands['msg_' + msg.type](args, msg); &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; } &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; function registerEventHandlers() { &nbsp; &nbsp; &nbsp; &nbsp; on('chat:message', handleInput); &nbsp; &nbsp; } &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; return { &nbsp; &nbsp; &nbsp; &nbsp; registerEventHandlers: registerEventHandlers &nbsp; &nbsp; }; }()); on('ready', function() { &nbsp; &nbsp; 'use strict'; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; bshields.flight.registerEventHandlers(); }); As you can see here, adding a new command with functionality just like !fly is basically a matter of copying lines 7-10, changing "fly" to what you want the new command to be, and changing "fluffy-wing" to what you want the new statusmarker to be.
The only issue I see with the Fly api is that negative numbers aren't possible. &nbsp;Easy fix is to simply make 10 the base plane and use 1-9 as negative and go 11-19 as positives. Thanks for the suggestion, I'll try it out.
1471286551
The Aaron
Pro
API Scripter
Could modify it to use green dots for positive and red dots for negative.
1471286649
The Aaron
Pro
API Scripter
Changing line 9 to this should do it...: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; markStatus( (height&gt;0?'green':'red') , height, msg.selected);
1471286795

Edited 1471286865
The Aaron
Pro
API Scripter
Also, regarding the large digits status markers thing, you can play with the&nbsp; Grid Scale to make the markers appear smaller, giving you more digits. &nbsp;Also, placing them at the bottom of a token is sometimes much nicer (see My&nbsp; Settings-Status Marker Position ).
That's a good alternative too. &nbsp;For Spelljammer the typical hex size is 150 feet. &nbsp;If I limit sight range to 10 hexes, I don't need more than 2 digits. &nbsp;On the other hand color markers would allow for larger encounter ranges. &nbsp;I'll try both and see what works. &nbsp;The pitch and yaw markers don't need to go beyond 9 (using 10's of degrees), but need to show up/down or left/right. &nbsp;Probably a combination of the two methods will work. I'll try it out and post some screenshots of what works in case someone else wants to use it.
1471291623
The Aaron
Pro
API Scripter
Sounds complicated! (read AWESOME!). &nbsp;If I were starting from scratch on something like this, I think I'd approach it more like my Facing script and add follower graphics with the added details, toggling them with API commands. &nbsp;Done correctly, that could basically give you a base with all the data, similar to what you might have with heroclix or the like.
Ok, I set this up and added a couple of commands but I get this error: TypeError: msg.content.trim(...).splitArgs is not a function TypeError: msg.content.trim(...).splitArgs is not a function at handleInput (apiscript.js:60:39) at eval (eval at (/home/node/d20-api-server/api.js:105:34), :65:16) at Object.publish (eval at (/home/node/d20-api-server/api.js:105:34), :70:8) at /home/node/d20-api-server/api.js:1200: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) at Kd (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:546) at Id.Mb (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:489) at Ld.Mb (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:94:425) at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:111:400 The lines I added look like this: pitch: function(args, msg) { var height = parseInt(args[0]) || 0; markStatus('green', height, msg.selected); }, rotate: function(args, msg) { var height = parseInt(args[0]) || 0; markStatus('red', height, msg.selected); }, Basically, I plan to use the !fly command to set height, the !pitch command to set angle of elevation (on a clockwise basis) and the !rotate command to show roll (also clockwise). &nbsp; But I'm not enough of a coder to tell what is wrong with the script and if it's something I did or a typo in the original (which I copy/pasted).
1471636038
The Aaron
Pro
API Scripter
Split Args is another script in the repo that is required for the fly script. &nbsp;You can install it from the Script Library.
Gotcha, thanks. And fixed. &nbsp;Works great. &nbsp;Thanks all for the help and the great scripts.
1471651760
The Aaron
Pro
API Scripter
No worries! &nbsp;Happy Rolling!