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] !spin-token

1531453488

Edited 1531484253
MyRoll20Stuffs
API Scripter
I wanted to be able to have some animated fans or blade traps in a dungeon I was working on, so I took The Aaron's Bounce Token script and adapted it to spinning. Here i is in action: Here is the script. There plenty of variables you can adjust in the script to affect the speed / movement intervals. // By: Kastion (Adaptation of The Aaron, Arcane Scriptomancer's BounceToken Script) // Profile: <a href="https://app.roll20.net/users/3173313/kastion" rel="nofollow">https://app.roll20.net/users/3173313/kastion</a> var SpinTokens = SpinTokens || (function(){ 'use strict'; var version = '0.1.2', lastUpdate = 1523205020, schemaVersion = 0.1, stepRate = 25, defaultSecondsPerCycle = 1, millisecondsPerSecond = 1000, ch = function (c) { var entities = { '&lt;' : 'lt', '&gt;' : 'gt', "'" : '#39', '@' : '#64', '{' : '#123', '|' : '#124', '}' : '#125', '[' : '#91', ']' : '#93', '"' : 'quot', '-' : 'mdash', ' ' : 'nbsp' }; if(_.has(entities,c) ){ return ('&amp;'+entities[c]+';'); } return ''; }, showHelp = function() { sendChat('', '/w gm '+ '&lt;div style="border: 1px solid black; background-color: white; padding: 3px 3px;"&gt;'+ '&lt;div style="font-weight: bold; border-bottom: 1px solid black;font-size: 130%;"&gt;'+ 'SpinTokens v'+version+ '&lt;div style="clear: both"&gt;&lt;/div&gt;'+ '&lt;/div&gt;'+ '&lt;div style="padding-left:10px;margin-bottom:3px;"&gt;'+ '&lt;p&gt;Allows the GM to toggle spinning of selected tokens&lt;/p&gt;'+ '&lt;/div&gt;'+ '&lt;b&gt;Commands&lt;/b&gt;'+ '&lt;div style="padding-left:10px;"&gt;&lt;b&gt;&lt;span style="font-family: serif;"&gt;!spin-start '+ch('[')+'Seconds Per Cycle'+ch(']')+' '+ch('[')+'-- tokenID ...'+ch(']')+'&lt;/span&gt;&lt;/b&gt;'+ '&lt;div style="padding-left: 10px;padding-right:20px"&gt;'+ 'Starts a selected or specified tokens spinning, optionally with a speed.'+ '&lt;ul&gt;'+ '&lt;li style="border-top: 1px solid #ccc;border-bottom: 1px solid #ccc;"&gt;'+ '&lt;b&gt;&lt;span style="font-family: serif;"&gt;Seconds Per Cycle&lt;/span&gt;&lt;/b&gt; '+ch('-')+' Specifies the number of seconds for the token to make a full spin. &lt;b&gt;Default: '+defaultSecondsPerCycle +'&lt;/b&gt;&lt;/li&gt;'+ '&lt;/li&gt; '+ '&lt;/ul&gt;'+ '&lt;/div&gt;'+ '&lt;/div&gt;'+ '&lt;div style="padding-left:10px;"&gt;&lt;b&gt;&lt;span style="font-family: serif;"&gt;!spin-stop '+ch('[')+'-- tokenID ...'+ch(']')+'&lt;/span&gt;&lt;/b&gt;'+ '&lt;div style="padding-left: 10px;padding-right:20px"&gt;'+ 'Stops the selected or specified tokens from spinningb.'+ '&lt;/div&gt;'+ '&lt;/div&gt;'+ '&lt;/div&gt;' ); }, handleInput = function(msg) { if ( "api" !== msg.type || !playerIsGM(msg.playerid) ) { return; } let parts = msg.content.split(/\s+--\s+/); let args = parts[0].split(/\s+/); let ids = (parts[1]||'').split(/\s+/).filter((id)=&gt;id.length); switch(args[0]) { case '!spin-start': { if(!( msg.selected &amp;&amp; msg.selected.length &gt; 0 ) &amp;&amp; ids.length===0) { showHelp(); return; } let secondsPerCycle = Math.abs(args[1] || defaultSecondsPerCycle); ids=[...new Set([...(msg.selected||[]).map((s)=&gt;s._id), ...ids])]; ids.map((id)=&gt;getObj('graphic',id)) .filter((o)=&gt;undefined !== o) .forEach((o)=&gt;{ state.SpinTokens.spinners[o.id]={ id: o.id, rotation: o.get('rotation'), page: o.get('pageid'), rate: (secondsPerCycle*millisecondsPerSecond) }; }) ; } break; case '!spin-stop': { if(!( msg.selected &amp;&amp; msg.selected.length &gt; 0 ) &amp;&amp; ids.length===0) { showHelp(); return; } ids=[...new Set([...(msg.selected||[]).map((s)=&gt;s._id), ...ids])]; ids.map((id)=&gt;getObj('graphic',id)) .filter((o)=&gt;undefined !== o) .filter((o)=&gt;state.SpinTokens.spinners.hasOwnProperty(o.id)) .forEach((o)=&gt;{ o.set('rotation',state.SpinTokens.spinners[o.id].rotation); delete state.SpinTokens.spinners[o.id]; }) ; } break; } }, getActivePages = () =&gt; _.union([ Campaign().get('playerpageid')], _.values(Campaign().get('playerspecificpages')), _.chain(findObjs({ type: 'player', online: true })) .filter((p)=&gt;playerIsGM(p.id)) .map((p)=&gt;p.get('lastpage')) .value() ), animateSpin = function() { var pages = getActivePages(); _.chain(state.SpinTokens.spinners) .filter(function(o){ return _.contains(pages,o.page); }) .each(function(sdata){ var s = getObj('graphic',sdata.id); if(!s) { delete state.SpinTokens.spinners[sdaC1d]; } else { if (state.SpinTokens.spinners[sdata.id].rotation &gt;= 360) { state.SpinTokens.spinners[sdata.id].rotation = 0; s.set({ rotation: 0 }); } else { state.SpinTokens.spinners[sdata.id].rotation = state.SpinTokens.spinners[sdata.id].rotation + 10; s.set({ rotation: state.SpinTokens.spinners[sdata.id].rotation }); } } }); }, handleTokenDelete = function(obj) { var found = _.findWhere(state.SpinTokens.spinners, {id: obj.id}); if(found) { delete state.SpinTokens.spinners[obj.id]; } }, handleTokenChange = function(obj) { var found = _.findWhere(state.SpinTokens.spinners, {id: obj.id}); if(found) { state.SpinTokens.spinners[obj.id].rotation= obj.get('rotation'); } }, checkInstall = function() { log('-=&gt; SpinTokens v'+version+' &lt;=- ['+(new Date(lastUpdate*1000))+']'); if( ! _.has(state,'SpinTokens') || state.SpinTokens.version !== schemaVersion) { log(' &gt; Updating Schema to v'+schemaVersion+' &lt;'); state.SpinTokens = { version: schemaVersion, spinners: {} }; } setInterval(animateSpin,stepRate); }, registerEventHandlers = function() { on('chat:message', handleInput); on('destroy:graphic', handleTokenDelete); on('change:graphic', handleTokenChange); }; return { CheckInstall: checkInstall, RegisterEventHandlers: registerEventHandlers }; }()); on("ready",function(){ 'use strict'; SpinTokens.CheckInstall(); SpinTokens.RegisterEventHandlers(); });
1531458388
The Aaron
Pro
API Scripter
That’s funny because I created BounceTokens by modifying my SpinTokens script... <a href="https://github.com/Roll20/roll20-api-scripts/blob/master/SpinTokens/SpinTokens.js" rel="nofollow">https://github.com/Roll20/roll20-api-scripts/blob/master/SpinTokens/SpinTokens.js</a>
1531464172

Edited 1531464330
vÍnce
Pro
Sheet Author
Everything old is new again. ;-P
The Aaron said: That’s funny because I created BounceTokens by modifying my SpinTokens script... <a href="https://github.com/Roll20/roll20-api-scripts/blob/master/SpinTokens/SpinTokens.js" rel="nofollow">https://github.com/Roll20/roll20-api-scripts/blob/master/SpinTokens/SpinTokens.js</a> Oh wow I had no idea this even existed! All that's left to do is for someone to find my script on the forums and modify it to bounce tokens haha.
WOW I am an amature at scrips I don't know how to read it or even apply to my own game I am asking because with this you could make fire flicker. I know you probably are busy but if you ever get time please explain this to me. Looks SO Cool. this is future of table gaming. Its what a real table cant do and I want to learn.
Steven C. said: WOW I am an amature at scrips I don't know how to read it or even apply to my own game I am asking because with this you could make fire flicker. I know you probably are busy but if you ever get time please explain this to me. Looks SO Cool. this is future of table gaming. Its what a real table cant do and I want to learn. Best way I've found to do make realistic / cool looking fire is to use PageFX located here And then create a Custom FX in game called Campfire. Here is mine: { "angle": 0, "angleRandom": 180, "duration": -1, "emissionRate": 1000, "endColour": [191, 94, 26, 1], "endColourRandom": [30, 20, 0, 0.25], "gravity": {"x":0.01, "y":0.01}, "lifeSpan": 50, "lifeSpanRandom": 15, "maxParticles": 100, "size": 2, "sizeRandom": 5, "speed": 0.3, "speedRandom": 0.8, "startColour": [220, 143, 35, 1], "startColourRandom": [32, 0, 0, 0.25] } Here is an example the creator of PageFX made: I suggest you read up on the wiki and at least try to get an understanding on how to add and use API scripts in your game. Also if you're interested in animating stuff in your game here is a list of ways I used a script I made (!delay) to simulate animations in various different ways.