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

LightningFX script

1597157714

Edited 1598118587
David M.
Pro
API Scripter
This has probably been done before, but here's a fun little script to add lightning effects to a map. We don't use sound in our games, so no soundFX in the current script, but maybe later. EDIT -  Note: currently only supports Legacy Dynamic Lighting Click for animated gif of our hero about to realize he's in a dire situation (11s loop) Same FX settings with DL layer trees (7s loop). Setup: 1) Place a handful of tokens across the map with the following settings:         name : "Lightning"         All Players See Light : checked         image: transparent png         Aura1: 0ft (so the GM can see the square of the source) 2) Call !lightning on (+optional params?) to start the light show 3) Call !Lightning off to stop. Only lightning tokens on the player page are affected Optional parameters in bold below: !lightning <on/off> <minInterval> <maxInterval> <maxDuration>      minInterval = minimum time between flashes (in milliseconds) -- DEFAULT = 200      minInterval = maximum time between flashes (in milliseconds) -- DEFAULT = 10000      maxDuration = maximum duration of each flash (in milliseconds) -- DEFAULT = 400 Examples of valid calls: !lightning on    //uses default values !lightning off    //turns off FX (there may be one more cycle that has to finish after command is given) !lightning on 400    //overrides the minInterval, rest are default values !lightning on 400 8000    //overrides the min & max Intervals, with default value used for maxDuration !lightning on 400 8000 200    //overrides all timer values For the animated gif example above, I used 5 lightning tokens (red highlight) and drew tree trunks in the DL layer. I thought it created a pretty spooky effect. Here's the script! const LightningFX = (() => { const scriptName = "LightningFX"; const version = '0.1'; var globalKill = true; const LIGHT_NAME = 'Lightning'; const checkInstall = function() { log(scriptName + ' v' + version + ' initialized.'); }; const flashOff = function(src) { src.set('light_radius', 0); } const flashOn = function(src, dim, timeout) { let rand = Math.random() * timeout; if (dim) { src.set('light_dimradius', -15); src.set('light_radius', 200); } else { src.set('light_radius', 200); } setTimeout(flashOff, rand, src); } const handleFX = function(sources, minInterval, maxInterval, maxDuration, active) { let dim = false; if (active) { let rand = Math.floor(Math.random() * (maxInterval - minInterval + 1) + minInterval); if ( randomInteger(2) === 2 ) { dim = true; } else { dim = false; } setTimeout(function() { sources.forEach((src) => { flashOn(src, dim, maxDuration); }); if (!globalKill) { handleFX(sources, minInterval, maxInterval, maxDuration, true); } }, rand); } else { sources.forEach((src) => { flashOff(src); }); } } const handleInput = function(msg) { //set defaults let minInterval = 200; let maxInterval = 10000; let maxDuration = 400; try { if(msg.type=="api" && msg.content.indexOf("!lightning") === 0 && playerIsGM(msg.playerid)) { who = getObj('player',msg.playerid).get('_displayname'); let cmd = msg.content.split((/\s+/)); cmd.shift(); switch (cmd.length) { case 0: //no commands, do nothing sendChat('Lightning',`/w "${who}" `+ 'No commands given to !Lightning script'); break; case 1: //on or off break; case 2: //minInterval minInterval = parseInt(cmd[1]) break; case 3: //minInterval maxInterval minInterval = parseInt(cmd[1]) maxInterval = parseInt(cmd[2]) break; case 4: default: //minInterval maxInterval maxDuration minInterval = parseInt(cmd[1]) maxInterval = parseInt(cmd[2]) maxDuration = parseInt(cmd[3]) break; } if ( isNaN(minInterval) || isNaN(maxInterval) || isNaN(maxDuration) ) { sendChat('Lightning',`/w "${who}" `+ 'Error. Non-Numeric timer settings detected'); return; } var sources = findObjs({ _pageid: Campaign().get("playerpageid"), _type: "graphic", name: LIGHT_NAME }); if (!sources) { sendChat('Lightning',`/w "${who}" `+ 'No Lightning Sources on Player Page!'); globalKill = true; return; } switch (cmd[0].toLowerCase()) { case "on": //TURN ON FX globalKill = false; handleFX(sources, minInterval, maxInterval, maxDuration, true); break; case "off": //TURN OFF FX globalKill = true; handleFX(sources, minInterval, maxInterval, maxDuration, false); break; default: sendChat('Lightning',`/w "${who}" `+ 'Unrecognized command. Expected Lighting \"on\" or \"off\"'); return; } } } catch(err) { sendChat('Lightning',`/w "${who}" `+ 'Unhandled exception: ' + err.message); } }; const registerEventHandlers = function() { on('chat:message', handleInput); }; on("ready",() => { checkInstall(); registerEventHandlers(); }); })();
Nice script I used it in my past session and with the thunder crash sound track it worked out nice, too bad when I use a weather overlay from the marketplace the sound gets all screwy. Your script worked like a charm though thanks !!
1597781751
David M.
Pro
API Scripter
Great, thanks for the feedback!