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] !delay

1530245785

Edited 1531078367
MyRoll20Stuffs
API Scripter
Edited July 3rd 2018 !delay version 0.8.3 New Syntax : !delay [seconds]|[loops (optional)] \\[speaker (optional)] --[command] It works with the following chat commands: /desc /em /me /w /roll /gmroll normal chat support inline roll support Here are some examples: /desc !delay 5 --/desc Bob waves hello. Bob waves hello. Chat !delay 5 \\Joe --Hello Joe: Hello /em !delay 5 \\Fred --/em smiles at you. Fred smiles at you. !delay 5 \\Bob --/me does a backflip. Bob does a backflip. /w !delay 5 \\Kastion --/w gm Hello GM! (From Kastion): Hello GM! /roll !delay 5 \\Norm --/roll 1d20 Norm: rolling 1d20 (9) = 9 /gmroll !delay 5 \\Kastion --/gmroll 1d20 Kastion: (To GM) rolling 1d20 (4) = 4 Inline Roll Support !delay 5 \\Kastion --/em swings his sword at Joe [[1d20]] and does [[1d8]] damage! Kastion swings his sword at Joe rolling 17 for his attack roll and does 8 damage! API COMMANDS: You can call other API commands and delay them there is a catch however. If the API command in question uses msg.playerid in it do the following to make it compatible with !delay Search for the following in the function that handles chat:message: if (msg.type !== "api") { &nbsp;&nbsp;&nbsp; return; } And Directly Below it add the following: if (!state. commandname _pid) &nbsp;&nbsp;&nbsp; state. commandname _pid = "API"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (msg.playerid !== "API") &nbsp;&nbsp;&nbsp; state. commandname _pid = msg.playerid; else &nbsp;&nbsp;&nbsp; msg.playerid = state. commandname _pid;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Replace " commandname " with the command name in question or the script name. Here is the updated version of the script that now supports looping and speaking as. /* Delay Function / Command by Kastion the Scriptomancer Profile: <a href="https://app.roll20.net/users/3173313/kastion" rel="nofollow">https://app.roll20.net/users/3173313/kastion</a> Syntax: !delay [seconds] \\ [speaker] -- [command] */ function processInlinerolls(msg) { if(_.has(msg,'inlinerolls')){ return _.chain(msg.inlinerolls) .reduce(function(m,v,k){ var ti=_.reduce(v.results.rolls,function(m2,v2){ if(_.has(v2,'table')){ m2.push(_.reduce(v2.results,function(m3,v3){ m3.push(v3.tableItem.name); return m3; },[]).join(', ')); } return m2; },[]).join(', '); m['$[['+k+']]']= (ti.length &amp;&amp; ti) || v.results.total || 0; return m; },{}) .reduce(function(m,v,k){ return m.replace(k,v); },msg.content) .value(); } else { return msg.content; } } function delayFunction(speaker, output, pid) { return function() { if (speaker.length &gt; 0) { var token = findObjs({ _pageid: Campaign().get("playerpageid"), _type: "graphic", _name: speaker.trim()}); var char = ""; } else var token = ""; if (token.length) { _.each(token, function(obj) { var char = getObj("character", obj.get("represents")); if (char) sendChat("character|" + char.id, output.trim()); else sendChat(speaker, output.trim()); }); } else sendChat(speaker, output.trim()); } } on("chat:message", function(msg) { if('api' !== msg.type ) { return; } var cmdName = "!delay"; var msgTxt = msg.content; if(msg.type == "api" &amp;&amp; msgTxt.indexOf(cmdName) !== -1 &amp;&amp; playerIsGM(msg.playerid)) { var inline_rolls = processInlinerolls(msg); var seconds = msg.content.split(' ')[1]; var speaking = msg.content.split('\\\\')[1]; var command = inline_rolls.substring(inline_rolls.indexOf('--')+2); var pid = msg.playerid; if (speaking) speaking = speaking.split('--')[0]; else speaking = ""; if (!isNaN(seconds) &amp;&amp; command) var delay_length = seconds * 1000; else return; setTimeout(delayFunction(speaking, command, pid), delay_length); }; }); on('ready',function(){ log("-=&gt; Delay command loaded (!delay) &lt;=-"); }); Here is a video showing how powerful !delay can be if used with a number of different API commands. The video uses the following commands: &nbsp;&nbsp;&nbsp; !tl &nbsp;&nbsp;&nbsp; !token-mod &nbsp;&nbsp;&nbsp; !cfx &nbsp;&nbsp;&nbsp; !sfx &nbsp;&nbsp;&nbsp; !kaboom &nbsp;&nbsp;&nbsp; !screenshake &nbsp;&nbsp;&nbsp; !ping (New function I wrote) &nbsp;&nbsp;&nbsp; !fade (New function I wrote) This is the list of commands executed in the above video. !tl lock !fade out BRNA !sfx song:Ambush2 action:loop unique:true volume:100 !sfx song:Bones1 action:play unique:true volume:100 !ping -LAHF5tOCLTscmYyPkEX !delay 1 --!token-mod --flip showplayers_bar3 showplayers_name --set currentside|+1 --ids -LAHF5tOCLTscmYyPkEX !delay 1 --!cfx bomb-death -LAHTP5U47IaVZdebP4m -LAHF5tOCLTscmYyPkEX !delay 1 --!sfx song:Vanish action:play unique:true volume:100 !delay 4 --!token-mod --flip showplayers_bar3 showplayers_name --set currentside|+1 --ids -LAHFPyR5lMGsj1q6aGW !delay 4 --!cfx bomb-death -LAHSx-pBVRZKudBuf2V -LAHFPyR5lMGsj1q6aGW !delay 4 --!sfx song:Vanish1 action:play unique:true volume:100 !delay 4 --!sfx song:Zombie1 action:play unique:true volume:100 !delay 7 --!token-mod --flip showplayers_bar3 showplayers_name --set currentside|+1 --ids -LAHFKhaAZKcpNW9Nw9e !delay 7 --!cfx bomb-death -LAHRkQglUu1JD9kNdRG -LAHFKhaAZKcpNW9Nw9e !delay 7 --!sfx song:Vanish2 action:play unique:true volume:100 !delay 7 --!sfx song:Zombie2 action:play unique:true volume:100 !delay 10 --!token-mod --flip showplayers_bar3 showplayers_name --set currentside|+1 --ids -LAHFG1-GkNjk1eFGi_0 !delay 10 --!cfx bomb-death -LAHSVmIwKMEibXooDvN -LAHFG1-GkNjk1eFGi_0 !delay 10 --!sfx song:Vanish3 action:play unique:true volume:100 !delay 10 --!sfx song:Zombie3 action:play unique:true volume:100 !delay 13 --!ping -LAH7fK7jLnwsObDJ8nU !delay 15 --!sfx song:Bones1 action:play unique:true volume:100 !delay 15 --!token-mod --flip showplayers_bar3 showplayers_name --set currentside|+1 --ids -LAH7fK7jLnwsObDJ8nU !delay 15 --!cfx bomb-death -LAHV3MLf9NdxllNQApk -LAH7fK7jLnwsObDJ8nU !delay 15 --!sfx song:Vanish action:play unique:true volume:100 !delay 18 --!token-mod --flip showplayers_bar3 showplayers_name --set currentside|+1 --ids -LAH7z0KO7TSATVX4yLr !delay 18 --!cfx bomb-death -LAHV3YTBg-W4pX3n3MS -LAH7z0KO7TSATVX4yLr !delay 18 --!sfx song:Vanish1 action:play unique:true volume:100 !delay 18 --!sfx song:Zombie1 action:play unique:true volume:100 !delay 21 --!token-mod --flip showplayers_bar3 showplayers_name --set currentside|+1 --ids -LAH7myPOl_0xVcmp6hc !delay 21 --!cfx bomb-death -LAHU-34OSIywtnxQdY4 -LAH7myPOl_0xVcmp6hc !delay 21 --!sfx song:Vanish2 action:play unique:true volume:100 !delay 21 --!sfx song:Zombie2 action:play unique:true volume:100 !delay 24 --!token-mod --flip showplayers_bar3 showplayers_name --set currentside|+1 --ids -LAH7wlmchqgXQqd2FXD !delay 24 --!cfx bomb-death -LAHV32TtE1ECrAJuUQp -LAH7wlmchqgXQqd2FXD !delay 24 --!sfx song:Vanish3 action:play unique:true volume:100 !delay 24 --!sfx song:Zombie3 action:play unique:true volume:100 !delay 24 --!sfx song:Mephit1 action:play unique:true volume:100 !delay 27 --!ping -LAHZyCjzLsE1-hs4mqz !delay 32 --!ping -LAHXttRTQHOMFAD_9ic !delay 32 --!sfx song:Bones2 action:play unique:true volume:100 !delay 36 --!cfx nova-death -LAHWGF4voPddycMLbje -LAHXttRTQHOMFAD_9ic !delay 36 --!sfx song:Ogre1 action:play unique:true volume:100 !delay 36 --!token-mod --flip showplayers_bar3 showplayers_name --set currentside|+1 --ids -LAHXttRTQHOMFAD_9ic -LAH7tRDx4vG3rCcWi1X -LAH7IoNq4T19BxG1pIp -LAH7ASZLpua7udsz2UQ -LAH71GtfZ8ukdXc6Kc5 -LAH76mYFjH6vsCkN2_H -LAH7E4rnJAJ4KEo8li8 -LAH7IoNq4T19BxG1pIp !delay 38 --!kaboom 20 50 scatter --death --ids -LAHXttRTQHOMFAD_9ic !delay 38 --!ScreenShake 6 !delay 42 --!ping -LB9djHBooIt4U1BCLm0 !delay 42 --!tl unlock If you have any issues with the script or any feature suggestions please don't hesitate to reply to this thread.
1530269928

Edited 1530270165
MyRoll20Stuffs
API Scripter
I just wanted to add that the following commands will not work with !delay /fx /ooc or /o /talktomyself /emas The following script / command (CFX) can be used in place of /fx to delay FX. /emas can be emulated by specifying a speaker and using /em Example: !delay 5 \\Bob --/em waves. (Also it should be noted that if no speaker (\\) is specified with /em it won't show any player's name in the chat and if using the above example you will get "Bob waves." but if you do the following: !delay 5 --/em waves. It will just output " waves." So a speaker is necessary when delaying /em Also one last thing of note, Markdown works in the output as normal: Please post any issues you have or suggestions / feature requests in this thread.
I've been doing a lot of neat things with this !delay script. One thing I did recently was use !token-mod to modify sizes of objects to simulate growing/shrinking animations. Check out this video to see what I'm talking about and look at the below code block to see how it is done. !delay 1 \\Lethrandralil --I will not forget this embarrassment. !delay 4 \\Lethrandralil --/em utters an arcane incantation. !delay 8 \\Lethrandralil --I will be coming for you. I will melt the flesh from your bones. !delay 12 \\Lethrandralil --/em finishes his spell and is covered in a globe of darkness. !delay 12 --!cfx nova-death -LDvIpkUGUBt-HgQI12t -LDvUbwtJkIlsW6taVW9 !delay 12 --!sfx song:Rumble action:play unique:true volume:75 !delay 12 --!token-mod --set layer|objects --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 12 --!token-mod --set layer|gmlayer --ignore-selected --ids -LDvUbwtJkIlsW6taVW9 !delay 12 \\Lethrandralil --Come forth my minions. !delay 15 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 15.1 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 15.2 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 15.3 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 15.4 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 15.5 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 15.6 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 15.7 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 15.8 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 15.9 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 16 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 16.1 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 16.2 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 16.3 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 16.4 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 16.5 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 16.6 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 16.7 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 16.8 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 16.9 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 17 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 17.1 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 17.2 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 17.3 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 17.4 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 17.5 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 17.6 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 17.7 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 17.8 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 17.9 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 18 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 18.1 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 18.2 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 18.3 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 18.4 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 18.5 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 18.6 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 18.7 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 18.8 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 18.9 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 19 --!token-mod --set width|-10 height|-10 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 19.5 --!token-mod --set layer|gmlayer --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 20 --!token-mod --set width|420 height|420 --ignore-selected --ids -LGKGVmT3ZPXKDZ7DtEg !delay 21 --!cfx bomb-death -LDtD3mLkoM-_G0yS05j -LDtDVeZVFeT8j54Zcpc !delay 21 --!sfx song:Nature action:play unique:true volume:100 !delay 21 --!token-mod --set layer|objects --ignore-selected --ids -LDtDVeZVFeT8j54Zcpc !delay 23 --!cfx bomb-death -LDtD5zBPJLp34u6CEFc -LDtDdf5CU7nIBXNKpIv !delay 23 --!sfx song:Nature action:play unique:true volume:100 !delay 23 --!token-mod --set layer|objects --ignore-selected --ids -LDtDdf5CU7nIBXNKpIv !delay 25 --!cfx bomb-death -LDtD8i0Sfdtr6qbQs6I -LDtDntWJxiOkTarEX4a !delay 25 --!sfx song:Nature action:play unique:true volume:100 !delay 25 --!token-mod --set layer|objects --ignore-selected --ids -LDtDntWJxiOkTarEX4a Have any cool ideas for using !delay? Any suggestions would be great! I'm already having a blast with what I've been able to script using the !delay command.
1530461981
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
I like the growth/shrinking effect! Great idea.
keithcurtis said: I like the growth/shrinking effect! Great idea. Thanks keithcurtis! Here is another example of it in use.
1530464799
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
One use I spoke of in another thread was to use it to do lightning effects. Create an invisible token on a page with Dynamic Lighting, and give it light of a huge radius that everyone can see. Use the delay command with token mod to flash the light on and off at (seemingly) random intervals. Question: Can !delay leapfrog other API commands? If issue a delayed command with a delay of 100 seconds, but manually issue another command at the 50 second mark, will both of them occur, or will one interfere with the action of the other?
keithcurtis said: One use I spoke of in another thread was to use it to do lightning effects. Create an invisible token on a page with Dynamic Lighting, and give it light of a huge radius that everyone can see. Use the delay command with token mod to flash the light on and off at (seemingly) random intervals. Question: Can !delay leapfrog other API commands? If issue a delayed command with a delay of 100 seconds, but manually issue another command at the 50 second mark, will both of them occur, or will one interfere with the action of the other? Both of them will occur. An example I ran this: !delay 10 --!sfx song:Fire action:play unique:true volume:75 Then at about 3 seconds in ran this: !sfx song:Fire action:play unique:true volume:75 And both commands will fire. The first, at the 10 second mark, and the second right after hitting enter. Also the order of the commands mean nothing to delay - I just order them in time for readability. Example if you run a macro that outputs this: !delay 4 --/desc 4 seconds in. !delay 1 --/desc 1 second in. /desc No delay. This is the result:
1530470392
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
That's really handy. Looks like it's great for handling animations.
keithcurtis said: That's really handy. Looks like it's great for handling animations. I tried out your lightning idea and it turned out like this. Needs a bit of polishing but does the trick. Here's the !delay macro used for it: !delay 1 --!sfx song:RainAmb action:play unique:true volume:100 !delay 11 --!token-mod --set layer|objects --ignore-selected --ids -LGMHmUFq00MEvPxC4Z0 !delay 11 --!token-mod --on light_otherplayers --ids -LGMHmUFq00MEvPxC4Z0 !delay 11 --!token-mod --set light_radius|300 light_dimradius|300 --ignore-selected --ids -LGMHmUFq00MEvPxC4Z0 !delay 11.2 --!sfx song:Thunder1 action:play unique:true volume:100 !delay 11.2 --!token-mod --set layer|gmlayer --ignore-selected --ids -LGMHmUFq00MEvPxC4Z0 !delay 11.2 --!token-mod --set light_radius|0 light_dimradius|0 --ignore-selected --ids -LGMHmUFq00MEvPxC4Z0 !delay 15 --!token-mod --set layer|objects --ignore-selected --ids -LGMKzYqe0edmID-F4bt !delay 15 --!token-mod --on light_otherplayers --ids -LGMKzYqe0edmID-F4bt !delay 15 --!token-mod --set light_radius|300 light_dimradius|300 --ignore-selected --ids -LGMKzYqe0edmID-F4bt !delay 15.2 --!sfx song:Thunder1 action:stop !delay 15.2 --!sfx song:Thunder2 action:play unique:true volume:100 !delay 15.2 --!token-mod --set layer|gmlayer --ignore-selected --ids -LGMKzYqe0edmID-F4bt !delay 15.2 --!token-mod --set light_radius|0 light_dimradius|0 --ignore-selected --ids -LGMKzYqe0edmID-F4bt !delay 22 --!token-mod --set layer|objects --ignore-selected --ids -LGMLM39S28pdED5ZMI7 !delay 22 --!token-mod --on light_otherplayers --ids -LGMLM39S28pdED5ZMI7 !delay 22 --!token-mod --set light_radius|300 light_dimradius|300 --ignore-selected --ids -LGMLM39S28pdED5ZMI7 !delay 22.2 --!sfx song:Thunder2 action:stop !delay 22.2 --!sfx song:Thunder3 action:play unique:true volume:100 !delay 22.2 --!token-mod --set layer|gmlayer --ignore-selected --ids -LGMLM39S28pdED5ZMI7 !delay 22.2 --!token-mod --set light_radius|0 light_dimradius|0 --ignore-selected --ids -LGMLM39S28pdED5ZMI7 !delay 26 --!sfx song:Thunder3 action:stop !delay 30 --!token-mod --set layer|objects --ignore-selected --ids -LGMNU7x9P8xj-QhsOOu !delay 30 --!token-mod --on light_otherplayers --ids -LGMNU7x9P8xj-QhsOOu !delay 30 --!token-mod --set light_radius|300 light_dimradius|300 --ignore-selected --ids -LGMNU7x9P8xj-QhsOOu !delay 30.2 --!sfx song:Thunder5 action:play unique:true volume:100 !delay 30.2 --!token-mod --set layer|gmlayer --ignore-selected --ids -LGMNU7x9P8xj-QhsOOu !delay 30.2 --!token-mod --set light_radius|0 light_dimradius|0 --ignore-selected --ids -LGMNU7x9P8xj-QhsOOu !delay 35 --!sfx song:Thunder3 action:stop
Can you add this to the one-click repo?&nbsp; This is awesome!
1530519142
Ziechael
Forum Champion
Sheet Author
API Scripter
That lightning effect is fantastic, great video to demonstrate it too! I've loosely been following this thread trying to think of a way to use it to best effect in my game and this may well be it! Is there a way to loop a delayed command? Thinking of programmed tannoy messages and the like that would repeat every now and again without having to hardcode it... although I suppose a limit on the amount of looping would be needed to prevent the dreaded infinite loop of doom!!
Ziechael said: That lightning effect is fantastic, great video to demonstrate it too! I've loosely been following this thread trying to think of a way to use it to best effect in my game and this may well be it! Is there a way to loop a delayed command? Thinking of programmed tannoy messages and the like that would repeat every now and again without having to hardcode it... although I suppose a limit on the amount of looping would be needed to prevent the dreaded infinite loop of doom!! I'll see about setting a loop option and a second value to set how long to loop it. I've been thinking of making a !loop command for the last few days but if I can just build that functionality into !delay all the better.
1530542044
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
That would be an excellent addition.
1530631589

Edited 1531078397
MyRoll20Stuffs
API Scripter
I've added in support for looping and for speaking "as a character" and showing the token's avatar in chat. Here is the new syntax for the command: Syntax: !delay [seconds]|[loops (optional)] \\[speaker (optional)] --[command] Support for looping is still a work in progress as I've come across some issues with it. Expect an update soon. Example: T The above will repeat the command 3 times once every 3 seconds. You can see I set the speaker to "Adelaide" and it used that character's avatar. Unfortunately after talking to The Aaron about it there is no workaround for delaying a command unless support is added to the specific script. For example, to work with !token-mod I had to add the following: In the "handleInput" function right after if (msg.type !== "api") { return; } Added: if (!state.tokenmod_pid) state.tokenmod_pid = "API"; if (msg.playerid !== "API") state.tokenmod_pid = msg.playerid; else msg.playerid = state.tokenmod_pid; The Aaron is going to add in support for !delay in the core !token-mod script so it will not require editing and I'm going to ask authors of some of the most commonly used scripts if they would be able to add support as well. Here is the updated script - I will edit the original post as well with the details: /* Delay Function / Command by Kastion the Scriptomancer Profile: <a href="https://app.roll20.net/users/3173313/kastion" rel="nofollow">https://app.roll20.net/users/3173313/kastion</a> Syntax: !delay [seconds] \\ [speaker] -- [command] */ function processInlinerolls(msg) { if(_.has(msg,'inlinerolls')){ return _.chain(msg.inlinerolls) .reduce(function(m,v,k){ var ti=_.reduce(v.results.rolls,function(m2,v2){ if(_.has(v2,'table')){ m2.push(_.reduce(v2.results,function(m3,v3){ m3.push(v3.tableItem.name); return m3; },[]).join(', ')); } return m2; },[]).join(', '); m['$[['+k+']]']= (ti.length &amp;&amp; ti) || v.results.total || 0; return m; },{}) .reduce(function(m,v,k){ return m.replace(k,v); },msg.content) .value(); } else { return msg.content; } } function delayFunction(speaker, output, pid) { return function() { if (speaker.length &gt; 0) { var token = findObjs({ _pageid: Campaign().get("playerpageid"), _type: "graphic", _name: speaker.trim()}); var char = ""; } else var token = ""; if (token.length) { _.each(token, function(obj) { var char = getObj("character", obj.get("represents")); if (char) sendChat("character|" + char.id, output.trim()); else sendChat(speaker, output.trim()); }); } else sendChat(speaker, output.trim()); } } on("chat:message", function(msg) { if('api' !== msg.type ) { return; } var cmdName = "!delay"; var msgTxt = msg.content; if(msg.type == "api" &amp;&amp; msgTxt.indexOf(cmdName) !== -1 &amp;&amp; playerIsGM(msg.playerid)) { var inline_rolls = processInlinerolls(msg); var seconds = msg.content.split(' ')[1]; var speaking = msg.content.split('\\\\')[1]; var command = inline_rolls.substring(inline_rolls.indexOf('--')+2); var pid = msg.playerid; if (speaking) speaking = speaking.split('--')[0]; else speaking = ""; if (!isNaN(seconds) &amp;&amp; command) var delay_length = seconds * 1000; else return; setTimeout(delayFunction(speaking, command, pid), delay_length); }; }); on('ready',function(){ log("-=&gt; Delay command loaded (!delay) &lt;=-"); });
I'm running into some issues with the looping now that I've had more time to use it. Do not use the script until I update it here as soon as possible.
1531076282

Edited 1531076302
MyRoll20Stuffs
API Scripter
I updated the posts that had the most recent code in them with looping functionality but as you can see in the post above this one I was having issues getting it set up bug free. I was in the process of moving at the end of last month / start of this month so I haven't been able to work on the script. (Went some time with no internet access as well since the move) I should have an updated version of the script with looping support in the next 2-3 days hopefully. The next time I post to this thread will be with looping functionality working. Also the script I changed to in the above posts contains the functionality for showing the Avatar of the "speaker" in chat so that is still working.
I'm still working on getting looping bug free. In the mean time, here's another application I found for the !delay command. I have an airship battle at one point on my campaign and I made extensive use of delaying !token-mod to make it appear as though the enemy ship was approaching and matching speed to board the player's ship. There are also some cannons I set up with FX as well. You're seeing what the GM would see so you'll see a few "invisible" tokens with auras that only the GM can see. Anyways here it is: <a href="https://www.youtube.com/watch?v=FKUJhGoFqD4" rel="nofollow">https://www.youtube.com/watch?v=FKUJhGoFqD4</a>
1531178062
vÍnce
Pro
Sheet Author
;-) Nice job.
Here's another application of the !delay script. I made a water trap that fills the room with water. There are 4 pipes, a chest in a cage, and 5 levers in the room. 4/5 of the levers turn the puddle next t pipe into pools. Puling the other lever unlocks the cage the chest is in but also starts filling the room completely with water. There is a magic item in the chest but more importantly inside it is another lever. Pulling it opens a drain in the middle of the room and all the water drains out. Here is a video of my attempt at this. It's still a work in-progress. I think to make it look more natural / fluid I need to enlarge the pools until they reach the center of the room then start enlarging the water token in the middle of the room while shrinking the smaller pools. Anyways check the video out. I'll post another once I work out all the fine details of this trap.
1531516950

Edited 1531519753
MyRoll20Stuffs
API Scripter
Here's another usage I have found for the !delay command. It's a bit rough around the edges and needs more work but you'll get the basic idea behind it. I use !delay combined with !token-mod to make a ghost flicker in and out of view basically jumping back and forth between planes or something similar. Here is a quick video showing what I mean. I need to work on it I'll edit this post with a cleaner version. EDIT: Here's a lightly better ghost vanishing effect but still could use more work.
1531526794

Edited 1531526843
MyRoll20Stuffs
API Scripter
Here is another use I found for !delay and !token-mod. Anyone remember in Final Fantasy 3 (FF6 JP) in the Narshe Mines there is a cavern room where a mote of light follows a specific pattern through the room to the end and if you walk out of place you trigger the trap. Once the characters enter the room the door seals and they are locked in. In my version a WIll'o'Wisp leads a trail leaving a path of light behind it. If the player doesn't follow the path of light from the Will'o'Wisp they trigger an arrow trap and take 1d6 damage then are teleported to the start of the room. Reaching the end of the path successfully allows you to pull a switch which 1) Unlocks and opens the barred door and 2) Opens a sealed chest right next to the lever and get a few low-level wondrous items. You can attack the Will'o'Wisp but if you do you're screwed on trying to follow the path and have to trial and error until they finally get it, which will not be easy. This is how the trap turned out using !delay and !token-mod
1534102537

Edited 1534102565
vÍnce
Pro
Sheet Author
Is it possible to pass a roll template through delay?&nbsp; I tried something like !delay 0 --&amp;{template:default}{{name=Test roll}}{{roll=[[ 1d20 ]]}} which resulted in : &nbsp;{{name=Test roll}}{{roll=13}} Allowing roll template macros would be nice.&nbsp;
1534108302
Michael I.
Pro
Sheet Author
Also any chance we can get a function to delay a Macro call. !delay 5 #macro this could open up all sorts of possibility with nested macros.
1536873117
Mik Holmes
Pro
Marketplace Creator
Hey, I'm not great with scripting - when you say above that you need to add something to another script to get it to work with delay, is this what you mean? In TokenMod (latest version from git, named in Roll20 as "TokenMod") if (msg.type !== "api") { return; } //ADDED STUFF FOR !DELAY &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (!state.TokenMod_pid) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state.TokenMod_pid = "API"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (msg.playerid !== "API") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; state.TokenMod_pid = msg.playerid; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg.playerid = state.TokenMod_pid; //END ADDED STUFF Trying it replacing commandname with token-mod gives&nbsp;ReferenceError: Invalid left-hand side in assignment
I can't get this to work with the TokenMod script. I've tried adding the additional lines but it still won't run any TokenMod commands with a delay. Can anyone help me out?
I can't seem to get it to work with TokenMod either. I have added the following code to the tokenmod script and get the message TypeError: Cannot read property 'get' of undefined : when it tries to run the !delay 5 --!token-mod --off showplayers_aura1 --set aura1_radius| if (!state.tokenmod_pid) state.tokenmod_pid = "API"; if (msg.playerid !== "API") state.tokenmod_pid = msg.playerid; else msg.playerid = state.tokenmod_pid; Below is part of a macro I am running to turn on a 30ft radius that all the players can see (this works fine) and after a delay of 5 seconds turn it off and set the radius to 'null' (which crashes the API), it works fine if entered in the chat. !token-mod --on showplayers_aura1 --set aura1_radius|30 aura1_color|#ff0000 !delay 5 --!token-mod --off showplayers_aura1 --set aura1_radius Can you post a copy of your TokenMod script that you are using for this?
This looks great. &nbsp; I'm a little concerned that you are bypassing access control on the modified scripts. &nbsp;If I understand correctly what you did there, the modified scripts that you indirectly call (like tokenmod) will run their commands as whoever last used that command. &nbsp; So you could end up running commands that you would not have been allowed to use directly?