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

[Help] Torch script causing high CPU usage in Chrome with !flicker-on

I really like The-Aaron's Torch script....just discovered that it had added functionality regarding flickering light sources without me knowing about it. So, I've been playing with it, and it seems that these flickering light sources are CPU-intensive in Chrome, but not in Firefox.  I've tried disabling all Chrome extensions and resetting all settings and flags back to default, but this didn't change anything. This is about a dozen light sources on a 50 x 60 map. I really like that this script allows me to separate a token's vision from a token's light source, and I'm hoping I don't have to give that up now that I've got this new-found functionality. I'm wondering if anyone has any work-arounds to make this work in Chrome (my players use Chrome).  Barring that, I'm wondering if I can use the source code and make a custom script where it's easy to just comment out the section that actually makes the lights flicker and move, while still keeping the rest of the functionality....working under the assumption that it is the flickering that is causing the CPU usage issues. If my assumption is correct regarding the CPU usage, it would be nice as a script enhancement to actually disable the flickering, while still allowing the separate light sources on the dynamic lighting layer. [The Aaron]. Thanks.
1535913876
The Aaron
Pro
API Scripter
You absolutely can.&nbsp; Here, I made this version for you that does exactly that.&nbsp; Flicker functions are still there, but now they only create and maintain the light source as a secondary light on the token.&nbsp; This is actually something I've had as an idea to work on for a while, but time is fleeting... =D Code: // By: The Aaron, Arcane Scriptomancer // Contact: <a href="https://app.roll20.net/users/104025/the-aaron" rel="nofollow">https://app.roll20.net/users/104025/the-aaron</a> var Torch = Torch || (function() { 'use strict'; var version = '0.8.11', lastUpdate = 1535913288, schemaVersion = 0.1, flickerURL = '<a href="https://s3.amazonaws.com/files.d20.io/images/4277467/iQYjFOsYC5JsuOPUCI9RGA/thumb.png?1401938659" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/4277467/iQYjFOsYC5JsuOPUCI9RGA/thumb.png?1401938659</a>', 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(who) { sendChat('', '/w "'+who+'" '+ '&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;'+ 'Torch v'+version+ '&lt;/div&gt;'+ '&lt;div style="padding-left:10px;margin-bottom:3px;"&gt;'+ '&lt;p&gt;Torch provides commands for managing dynamic lighting. Supplying a first argument of &lt;b&gt;help&lt;/b&gt; to any of the commands displays this help message, as will calling !torch or !snuff with nothing supplied or selected.&lt;/p&gt;'+ '&lt;p&gt;Torch now supports &lt;b&gt;&lt;i&gt;Jack Taylor&lt;/i&gt;&lt;/b&gt; inspired flickering lights. Flicker lights are only active on pages where a player is (GMs, drag yourself to other pages if you don'+ch("'")+'t want to move the party.) and are persisted in the state. Flicker lights can be used in addition to regular lights as they are implemented on a separate invisible token that follows the nomal token.&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;!torch '+ch('[')+ch('&lt;')+'Radius'+ch('&gt;')+' '+ch('[')+ch('&lt;')+'Dim Start'+ch('&gt;')+' '+ch('[')+ch('&lt;')+'All Players'+ch('&gt;')+' '+ch('[')+ch('&lt;')+'Token ID'+ch('&gt;')+ch('|')+ch('&lt;')+'--Angle'+ch('&gt;')+' ... '+ch(']')+ch(']')+ch(']')+ch(']')+'&lt;/span&gt;&lt;/b&gt;'+ '&lt;div style="padding-left: 10px;padding-right:20px"&gt;'+ '&lt;p&gt;Sets the light for the selected/supplied tokens. Only GMs can supply token ids to adjust.&lt;/p&gt;'+ '&lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; If you are using multiple '+ch('@')+ch('{')+'target'+ch('|')+'token_id'+ch('}')+' calls in a macro, and need to adjust light on fewer than the supplied number of arguments, simply select the same token several times. The duplicates will be removed.&lt;/p&gt;'+ '&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;'+ch('&lt;')+'Radius'+ch('&gt;')+'&lt;/span&gt;&lt;/b&gt; '+ch('-')+' The radius that the light extends to. (Default: 40)'+ '&lt;/li&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;'+ch('&lt;')+'Dim Start'+ch('&gt;')+'&lt;/span&gt;&lt;/b&gt; '+ch('-')+' The radius at which the light begins to dim. (Default: Half of Radius )'+ '&lt;/li&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;'+ch('&lt;')+'All Players'+ch('&gt;')+'&lt;/span&gt;&lt;/b&gt; '+ch('-')+' Should all players see the light, or only the controlling players (Darkvision, etc). Specify one of &lt;i&gt;1, on, yes, true, sure, yup, or -&lt;/i&gt; for yes, anything else for no. (Default: yes)'+ '&lt;/li&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;'+ch('&lt;')+'Token ID'+ch('&gt;')+'&lt;/span&gt;&lt;/b&gt; '+ch('-')+' A Token ID, usually supplied with something like '+ch('@')+ch('{')+'target'+ch('|')+'Target 1'+ch('|')+'token_id'+ch('}')+'.'+ '&lt;/li&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;'+ch('&lt;')+'--Angle'+ch('&gt;')+'&lt;/span&gt;&lt;/b&gt; '+ch('-')+' The angle of the light arc of the light. (Default: 360)'+ '&lt;/li&gt; '+ '&lt;/ul&gt;'+ '&lt;/div&gt;'+ '&lt;b&gt;&lt;span style="font-family: serif;"&gt;!snuff '+ch('[')+ch('&lt;')+'Token ID'+ch('&gt;')+' ... '+ch(']')+'&lt;/span&gt;&lt;/b&gt;'+ '&lt;div style="padding-left: 10px;padding-right:20px"&gt;'+ '&lt;p&gt;Turns off light for the selected/supplied tokens. Only GMs can supply token ids to adjust.&lt;/p&gt;'+ '&lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; If you are using multiple '+ch('@')+ch('{')+'target'+ch('|')+'token_id'+ch('}')+' calls in a macro, and need to adjust light on fewer than the supplied number of arguments, simply select the same token several times. The duplicates will be removed.&lt;/p&gt;'+ '&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;'+ch('&lt;')+'Token ID'+ch('&gt;')+'&lt;/span&gt;&lt;/b&gt; '+ch('-')+' A Token ID, usually supplied with something like '+ch('@')+ch('{')+'target'+ch('|')+'Target 1'+ch('|')+'token_id'+ch('}')+'.'+ '&lt;/li&gt; '+ '&lt;/ul&gt;'+ '&lt;/div&gt;'+ '&lt;b&gt;&lt;span style="font-family: serif;"&gt;!flicker-on '+ch('[')+ch('&lt;')+'Radius'+ch('&gt;')+' '+ch('[')+ch('&lt;')+'Dim Start'+ch('&gt;')+' '+ch('[')+ch('&lt;')+'All Players'+ch('&gt;')+' '+ch('[')+ch('&lt;')+'Token ID'+ch('&gt;')+ch('|')+ch('&lt;')+'--Angle'+ch('&gt;')+' ... '+ch(']')+ch(']')+ch(']')+ch(']')+'&lt;/span&gt;&lt;/b&gt;'+ '&lt;div style="padding-left: 10px;padding-right:20px"&gt;'+ '&lt;p&gt;Behaves identically to !torch, save that it creates a flickering light.&lt;/p&gt;'+ '&lt;/div&gt;'+ '&lt;b&gt;&lt;span style="font-family: serif;"&gt;!flicker-off '+ch('[')+ch('&lt;')+'Token ID'+ch('&gt;')+' ... '+ch(']')+'&lt;/span&gt;&lt;/b&gt;'+ '&lt;div style="padding-left: 10px;padding-right:20px"&gt;'+ '&lt;p&gt;Behaves identically to !snuff, save that it affects the flickering light.&lt;/p&gt;'+ '&lt;/div&gt;'+ '&lt;b&gt;&lt;span style="font-family: serif;"&gt;!daytime '+ch('[')+ch('&lt;')+'Token ID'+ch('&gt;')+ch(']')+'&lt;/span&gt;&lt;/b&gt;'+ '&lt;div style="padding-left: 10px;padding-right:20px"&gt;'+ '&lt;p&gt;Turns off dynamic lighting for the current player page, or the page of the selected/supplied token.&lt;/p&gt;'+ '&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;'+ch('&lt;')+'Token ID'+ch('&gt;')+'&lt;/span&gt;&lt;/b&gt; '+ch('-')+' A Token ID, usually supplied with something like '+ch('@')+ch('{')+'target'+ch('|')+'Target 1'+ch('|')+'token_id'+ch('}')+'.'+ '&lt;/li&gt; '+ '&lt;/ul&gt;'+ '&lt;/div&gt;'+ '&lt;b&gt;&lt;span style="font-family: serif;"&gt;!nighttime '+ch('[')+ch('&lt;')+'Token ID'+ch('&gt;')+ch(']')+'&lt;/span&gt;&lt;/b&gt;'+ '&lt;div style="padding-left: 10px;padding-right:20px"&gt;'+ '&lt;p&gt;Turns on dynamic lighting for the current player page, or the page of the selected/supplied token.&lt;/p&gt;'+ '&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;'+ch('&lt;')+'Token ID'+ch('&gt;')+'&lt;/span&gt;&lt;/b&gt; '+ch('-')+' A Token ID, usually supplied with something like '+ch('@')+ch('{')+'target'+ch('|')+'Target 1'+ch('|')+'token_id'+ch('}')+'.'+ '&lt;/li&gt; '+ '&lt;/ul&gt;'+ '&lt;/div&gt;'+ '&lt;b&gt;&lt;span style="font-family: serif;"&gt;!global-light '+ch('[')+ch('&lt;')+'Token ID'+ch('&gt;')+ch(']')+'&lt;/span&gt;&lt;/b&gt;'+ '&lt;div style="padding-left: 10px;padding-right:20px"&gt;'+ '&lt;p&gt;Toggles Global Illumination for the current player page, or the page of the selected/supplied token.&lt;/p&gt;'+ '&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;'+ch('&lt;')+'Token ID'+ch('&gt;')+'&lt;/span&gt;&lt;/b&gt; '+ch('-')+' A Token ID, usually supplied with something like '+ch('@')+ch('{')+'target'+ch('|')+'Target 1'+ch('|')+'token_id'+ch('}')+'.'+ '&lt;/li&gt; '+ '&lt;/ul&gt;'+ '&lt;/div&gt;'+ '&lt;/div&gt;'+ '&lt;/div&gt;' ); }, setFlicker = function(o,r,d,p,a) { var found = _.findWhere(state.Torch.flickers, {parent: o.id}), fobj; if( found ) { fobj = getObj('graphic',found.id); if(fobj) { fobj.set({ layer: 'walls', showname: false, aura1_radius: '', showplayers_aura1: false, light_radius: r, light_dimradius: d, light_otherplayers: p, light_angle: a }); } else { delete state.Torch.flickers[found.id]; } } if(!fobj) { // new flicker fobj =createObj('graphic',{ imgsrc: flickerURL, subtype: 'token', name: 'Flicker', pageid: o.get('pageid'), width: 70, height: 70, top: o.get('top'), left: o.get('left'), layer: 'walls', light_radius: r, light_dimradius: d, light_otherplayers: p, light_angle: a }); } toBack(fobj); state.Torch.flickers[fobj.id]={ id: fobj.id, parent: o.id, active: true, page: o.get('pageid'), light_radius: r, light_dimradius: d, light_angle: a }; }, clearFlicker = function(fid) { var f = getObj('graphic',fid); if(f) { f.remove(); } delete state.Torch.flickers[fid]; }, handleInput = function(msg) { var args, radius, dim_radius, arc_angle=360, other_players, page, objs=[],who,whoChar; if (msg.type !== "api") { return; } whoChar = (getObj('player',msg.playerid)||{get:()=&gt;'API'}); who=whoChar.get('_displayname'); args = msg.content.split(" "); switch(args[0]) { case '!torch': if((args[1]||'').match(/^(--)?help$/) || ( !_.has(msg,'selected') &amp;&amp; args.length &lt; 5)) { showHelp(who); return; } radius = parseInt(args[1],10) || 40; dim_radius = parseInt(args[2],10) || (radius/2); other_players = _.contains([1,'1','on','yes','true','sure','yup','-'], args[3] || 1 ); objs = _.chain(args) .rest(4) .uniq() .filter(function(a){ var angle=a.match(/^--(\d+)$/); if(angle){ arc_angle=(Math.min(360,Math.max(0,angle[1]))); return false; } return true; }) .map(function(t){ return getObj('graphic',t); }) .filter(()=&gt;playerIsGM(msg.playerid)) .reject(_.isUndefined) .value(); _.each(_.union(objs,_.map(msg.selected,function (o) { return getObj(o._type,o._id); })), function(o){ o.set({ light_radius: radius, light_dimradius: dim_radius, light_otherplayers: other_players, light_angle: arc_angle }); }); break; case '!snuff': if((args[1]||'').match(/^(--)?help$/) || ( !_.has(msg,'selected') &amp;&amp; args.length &lt; 2)) { showHelp(who); return; } if(playerIsGM(msg.playerid)) { _.chain(args) .rest(1) .uniq() .map(function(t){ return getObj('graphic',t); }) .reject(_.isUndefined) .each(function(t) { t.set({ light_radius: '', light_dimradius: '', light_otherplayers: false, light_angle: 360 }); }); } _.each(msg.selected,function (o) { getObj(o._type,o._id).set({ light_radius: '', light_dimradius: '', light_otherplayers: false, light_angle: 360 }); }); break; case '!daytime': if((args[1]||'').match(/^(--)?help$/) ) { showHelp(who); return; } if(playerIsGM(msg.playerid)) { page = getObj('page', whoChar.get('lastpage')); if(page) { page.set({ showlighting: false }); sendChat('','/w gm It is now &lt;b&gt;Daytime&lt;/b&gt; on '+page.get('name')+'!'); } } break; case '!nighttime': if((args[1]||'').match(/^(--)?help$/) ) { showHelp(who); return; } if(playerIsGM(msg.playerid)) { page = getObj('page', whoChar.get('lastpage')); if(page) { page.set({ showlighting: true }); sendChat('','/w gm It is now &lt;b&gt;Nighttime&lt;/b&gt; on '+page.get('name')+'!'); } } break; case '!global-light': if((args[1]||'').match(/^(--)?help$/) ) { showHelp(who); return; } if(playerIsGM(msg.playerid)) { page = getObj('page', whoChar.get('lastpage')); if(page) { page.set({ lightglobalillum: !(page.get('lightglobalillum')) }); sendChat('','/w gm Global Illumination is now '+(page.get('lightglobalillum')?'&lt;span style="font-weight:bold;color:#090;"&gt;ON&lt;/span&gt;':'&lt;span style="font-weight:bold;color:#900;"&gt;OFF&lt;/span&gt;' )+' on page &lt;b&gt;'+page.get('name')+'&lt;/b&gt;!'); } } break; case '!flicker-on': if((args[1]||'').match(/^(--)?help$/) || ( !_.has(msg,'selected') &amp;&amp; args.length &lt; 5)) { showHelp(who); return; } radius = parseInt(args[1],10) || 40; dim_radius = parseInt(args[2],10) || (radius/2); other_players = _.contains([1,'1','on','yes','true','sure','yup','-'], args[3] || 1 ); objs=_.chain(args) .rest(4) .uniq() .filter(function(a){ var angle=a.match(/^--(\d+)$/); if(angle){ arc_angle=(Math.min(360,Math.max(0,angle[1]))); return false; } return true; }) .filter(()=&gt;playerIsGM(msg.playerid)) .map(function(t){ return getObj('graphic',t); }) .reject(_.isUndefined) .value(); _.each(_.union(objs,_.map(msg.selected,function (o) { return getObj(o._type,o._id); })), function(o){ setFlicker(o, radius, dim_radius, other_players,arc_angle); }); break; case '!flicker-off': if((args[1]||'').match(/^(--)?help$/) || ( !_.has(msg,'selected') &amp;&amp; args.length &lt; 2)) { showHelp(who); return; } if(playerIsGM(msg.playerid)) { objs=_.chain(args) .rest(1) .uniq() .value(); } objs=_.union(objs,_.pluck(msg.selected,'_id')); _.each(state.Torch.flickers, function(f) { if( _.contains(objs, f.parent)) { clearFlicker(f.id); } }); break; } }, handleTokenMove = function(obj,prev) { if( obj.get('left') !== prev.left || obj.get('top') !== prev.top || obj.get('width') !== prev.width || obj.get('height') !== prev.height || obj.get('rotation') !== prev.rotation ) { let found = _.findWhere(state.Torch.flickers, {parent: obj.id}); if(found) { let flicker = getObj('graphic',found.id); if(flicker) { flicker.set({ left: obj.get('left'), top: obj.get('top'), width: obj.get('width'), height: obj.get('height'), rotation: obj.get('rotation') }); } } } }, handleTokenDelete = function(obj) { var found = _.findWhere(state.Torch.flickers, {parent: obj.id}); if(found) { clearFlicker(found.id); } else { found = _.findWhere(state.Torch.flickers, {id: obj.id}); if(found) { delete state.Torch.flickers[obj.id]; } } }, checkInstall = function() { log('-=&gt; Torch v'+version+' &lt;=- ['+(new Date(lastUpdate*1000))+']'); if( ! _.has(state,'Torch') || state.Torch.version !== schemaVersion) { log(' &gt; Updating Schema to v'+schemaVersion+' &lt;'); /* Default Settings stored in the state. */ state.Torch = { version: schemaVersion, flickers: {} }; } }, registerEventHandlers = function() { on('chat:message', handleInput); on('destroy:graphic', handleTokenDelete); on('change:graphic', handleTokenMove); }; return { CheckInstall: checkInstall, RegisterEventHandlers: registerEventHandlers }; }()); on("ready",function(){ 'use strict'; Torch.CheckInstall(); Torch.RegisterEventHandlers(); });
1535914184
The Aaron
Pro
API Scripter
The left Arcane Scriptomancer has a 20/10 "Darkvision", and a 60/30, 60º non-flickering flicker, this is what he sees: The right Arcane Scriptomancer just has sight.&nbsp; Here's what he can see: I've always thought that a Keyhole light pattern would make more sense, so you could do that with this script.&nbsp; Here the left Arcane Scriptomancer now has a 7.5/2.5 visible light and the same bullseye as above.&nbsp; This is the right Arcane Scriptomancer view.
Thanks.&nbsp; That helps a lot with Chrome.
1535918592
The Aaron
Pro
API Scripter
No worries. =D