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

Need some help on simple stopwatch script

1563473308
SᵃᵛᵃǤᵉ
Sheet Author
API Scripter
Trying to create a timer that sends a message to chat. Compiler says its good but it's not working. 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 && ti) || v.results .total || 0; return m; }, {}) .reduce(function(m, v, k) { return m.replace(k, v); }, msg.content) .value(); } else { return msg.content; } } on("chat:message", function(msg) { if (msg.type === "api" && /^!attr/.test(msg.content)) { let cmd = processInlinerolls(msg).split(/\s+/); var who = getObj('player', msg.playerid).get('_displayname') .split(' ')[0]; var seconds = (Number(cmd[1])) || 0; var minutes = (Number(cmd[2])) || 0; var hours = (Number(cmd[3])) || 0; var time = hours * 3600 + minutes * 60 + seconds; setTimeout(function() { sendChat(msg.who, "Time's Up!!"); }, time); } });
1563488699
The Aaron
Roll20 Production Team
API Scripter
That looks like it should work.  I cleaned it up a little with some modern practices. You're passing it an elapsed time, not a clock face time, right? !attr 0 0 10 In about 10 seconds, send the message. I say "about" because setTimeout() only guarantees it will be at least that long until it activates.  The error won't be too obvious on a single timer event, but if you wanted to do something "ever N seconds", using setTimeout() would eventually lead to a serious drift in measured vs actual time. Code: on('ready',()=>{ const processInlinerolls = (msg) => { if(_.has(msg,'inlinerolls')){ return _.chain(msg.inlinerolls) .reduce(function(m,v,k){ let 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 && ti) || v.results.total || 0; return m; },{}) .reduce(function(m,v,k){ return m.replace(k,v); },msg.content) .value(); } else { return msg.content; } }; on("chat:message", function(msg) { if (msg.type === "api" && /^!attr/.test(msg.content)) { let cmd = processInlinerolls(msg).split(/\s+/); let who = (getObj('player', msg.playerid)||{get:()=>'API'}).get('_displayname'); let seconds = (parseInt(cmd[1])) || 0; let minutes = (parseInt(cmd[2])) || 0; let hours = (parseInt(cmd[3])) || 0; let time = hours * 3600 + minutes * 60 + seconds; setTimeout(()=>{ sendChat(msg.who, "Time's Up!!"); }, time); } }); });
1563489076
SᵃᵛᵃǤᵉ
Sheet Author
API Scripter
Yeah I dont want it ti be tied to a token. All I need is to tell me time is expired.
1563490070
The Aaron
Roll20 Production Team
API Scripter
eh?  It's not tied to a token?
1563490101
The Aaron
Roll20 Production Team
API Scripter
You mean the !attr command?  I just left it what you had it as.
1563490734
SᵃᵛᵃǤᵉ
Sheet Author
API Scripter
I see, I must've typoed that...the command should have been !sw for stopwatch also saw where I left the numbers in milliseconds, so I made that edit just now. now testing
1563490826
SᵃᵛᵃǤᵉ
Sheet Author
API Scripter
SO here is the working code. I plan to add an option for a custom message I hope. on('ready',()=>{ const processInlinerolls = (msg) => { if(_.has(msg,'inlinerolls')){ return _.chain(msg.inlinerolls) .reduce(function(m,v,k){ let 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 && ti) || v.results.total || 0; return m; },{}) .reduce(function(m,v,k){ return m.replace(k,v); },msg.content) .value(); } else { return msg.content; } }; on("chat:message", function(msg) { if (msg.type === "api" && /^!sw/.test(msg.content)) { let cmd = processInlinerolls(msg).split(/\s+/); let who = (getObj('player', msg.playerid)||{get:()=>'API'}).get('_displayname'); let seconds = (parseInt(cmd[1])) || 0; let minutes = (parseInt(cmd[2])) || 0; let hours = (parseInt(cmd[3])) || 0; let time = (hours * 3600 + minutes * 60 + seconds) * 1000; setTimeout(()=>{ sendChat(msg.who, "Time's Up!!"); }, time); } }); });
Here's a TurnClock script (kinda old now) that I like to use. If you start it with a selected token, it'll add the clock status marker and tick off the last 10 seconds. It's designed to add sound effects, but I've disabled them.  on("ready", function() { "use strict"; on("chat:message", function (msg) { var args; if (msg.type === "api"){ args = msg.content.split(/\s+/); if (args[0].match(/^!Clock/i)){ let time = parseInt(args[1],10)||0; if(time){ let due = _.now()+time*1000, tokens = _.chain(msg.selected) .map((o)=>getObj('graphic',o._id)) .reject(_.isUndefined) .value(), names = _.map(tokens,(t)=>t.get('name')), numCheck, updateClock = ()=>{ let num=Math.ceil((due-_.now())/1000); if(num>0){ _.map(tokens,(t)=>t.set('status_stopwatch',num)); if (numCheck !== num){ numCheck = num; } _.delay(updateClock,200); } else { _.map(tokens,(t)=>t.set('status_stopwatch',false)); sendChat("", "Turn Over!"); } }; sendChat("TurnClock", "!Sound: Ticking Clock"); sendChat("", "TurnClock Started on: " + names.join(', ')); updateClock(); } } } }); on("chat:message", function (msg) { if (msg.type === "api" && msg.content === "!Sound: Ticking Clock") { PlaySound('Sound: Ticking Clock', 6000); }; if (msg.type === "api" && msg.content === "!Sound: Buzzer") { PlaySound('Sound: Buzzer', 1000); }; }); }); function PlaySound(trackname, time) { var track = findObjs({type: 'jukeboxtrack', title: trackname})[0]; if(track){ if (track.get('playing') === false){ track.set('playing',false); track.set('softstop',false); //track.set('volume', 100); log(track); if(track) { track.set('playing',true); log('playing'); setTimeout(function() {track.set('playing',false);log('stopping sound');}, time); log(track); } else { log("No track found"); } } else {track.set('playing', false); }} }
1563547275

Edited 1563547419
SᵃᵛᵃǤᵉ
Sheet Author
API Scripter
Thanks, I'll take a look at it. But what I was going for is a stopwatch/timer that can be set to different times and will display a customized message.  
1563549514

Edited 1563555184
Sure. When you fire the script, it opens a dialogue box to ask how many seconds you want to count. Enter the value (e.g. 30 seconds, or 200 seconds, etc.) and start the clock, and it outputs to chat that the clock has started. Then it goes silent until there are 10 seconds remaining on the timer. To fire the script: !Clock ?{How much time?} If you selected a token when firing the script, the script outputs a second-by-second countdown on the token once the timer has ticked down to 10 seconds: When the time is up, an alert is delivered to chat (Turn Over!).  The idea for my application was to use the timer to create urgency for the players during their turns, so that's why script outputs a second-by-second countdown on the token starting at 10 seconds. I did not want the script spamming the chat, so it's configured to apply the count to the Token.
1563553617
SᵃᵛᵃǤᵉ
Sheet Author
API Scripter
I see, that's pretty cool. I'll have to make a note for players on how many seconds in certain intervals, for a particular GURPS game mechanic.