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 .
×

Ping Function Stops Working During Sessions

Separating this discussion from the disable ping thread . Short description: During sessions, the ability to create a visible ping stops working.  A refresh will enable the user to ping once before it again becomes invisible.  It is difficult to determine if the ping is no longer working or if it is now transparent. The players' assigned color does not change. The occurrence is seemingly random, sometimes happening as soon as you sign in but more often it happens during the session.  Players will be pinging spots on the VTT and the next ping does not show.   I have reported this with visual demonstrations and console logs several times, but the help desk has never been able to reproduce it. I mainly use Firefox, but my players have experienced it on Chrome, Edge, and Brave as well.   If anyone has ideas on what to try to either fix the issue or trace down the cause, I am willing to try and document any findings.
Oginme  said: Jarren  said: Oginme, are you using Keith's PingBuddy script or the Teleport script, or any other script that changes players' user color?  I do use the teleport mod.  It is not linked to teleporting tokens though.  I have had games where I sign in with my players, someone will ping on the map and their ping will no longer be visible even when they change their ping color (which has never been discovered as 'transparent').  After one person loses the visual ping, everyone else will lose it as soon as they attempt to ping.. First one shows, second one is transparent. There have been a couple of cases where no one was able to ping right from the start. I have not seen the teleport script change a player's ping color, but I will keep an eye out for it. The Teleport script changes the player color briefly (so quickly that it's not noticeable) when the token is teleported so that a visible ping isn't shown to all players.         teleportPing = function(obj,pad){             let player, oldcolor;             // figure out if there is a player attached             if(Teleport.configparams.HIDEPING){                 player = findTokenPlayer(obj,pad);                 if(!player){                     player=DEFAULTPLAYER;                 }                 oldcolor = player.get("color");                 player.set("color","transparent");                 setTimeout(function(){                     sendPing(pad.get("left"), pad.get("top"), pad.get("_pageid"), player.id, true, player.id);                     setTimeout(function(){                         player.set("color",oldcolor);                     },1000);                 },10);             }         }, I wouldn't be surprised if other scripts also do the same thing.  Two that come to mind are The Aaron's Observer script and the PlayerStart scriptlet  that KeithCurtis wrote, but at a quick glance those two don't adjust the player's color when they update vision. 
Interesting.  I will disable the teleport for one of the campaigns where I see this happening and report back if it continues or not.   I wonder what the purpose of temporarily setting the color to transparent would be.  I can take a idle game and see what happens if I change the ping color to something other than transparent.  It has honestly been decades since I did any real programming. I've dabbled a bit with making alterations to some of the scripts, but haven't had the time, energy, or inclination to make a complete dive into the scripts. Thanks!
1777520437
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
In the case of Ping Buddy, one of the functions is a Party token. As you move the party token around the map, the player view is continually pulled to the new location. You can turn off the behavior, but the reason it toggles is so that the animation is not continually disrupting the experience.
Oginme said: Interesting.  I will disable the teleport for one of the campaigns where I see this happening and report back if it continues or not.   I wonder what the purpose of temporarily setting the color to transparent would be.  I can take a idle game and see what happens if I change the ping color to something other than transparent.  It has honestly been decades since I did any real programming. I've dabbled a bit with making alterations to some of the scripts, but haven't had the time, energy, or inclination to make a complete dive into the scripts. It's set to transparent simply so there isn't a visible ping for other players to see when the player's view is moved.  If you want to set it to a different color, it's on the line that I bolded above in the teleportPing function:                  player.set("color","transparent"); Change that to any hex value, such as:                 player.set("color","#FFFFFF"); However, the teleport script also has a config menu where you can disable the change to transparent. The full config menu: !teleport --config or directly toggle the HidePing off/on: !teleport --hideping
Thanks Jarren!   I will give disabling the ping and then changing the color in separate games to see what happens. Running eight games a week, I expect that I will run into some of the fringe issues with Jumpgate more frequently than others.  This will also give me a chance to test the different configurations in different games to narrow down which works best. OG
Yeah my regular game is on hiatus currently so I’m definitely not going to find bugs as often. :) And just fyi I was responding to the bug report I submitted yesterday, and also playing around with the Teleport script (I haven’t used it for a while) and noticed that the settings were all correct to change to transparent but I was still seeing the player color ping, which is not what I remember happening before. When I turned off the HidePing my test account wasn’t being pinged at all. I didn’t have a lot of time to deep dive and switch to the Experimental server or anything though.
1777562947
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
Jarren said: And just fyi I was responding to the bug report I submitted yesterday, and also playing around with the Teleport script (I haven’t used it for a while) and noticed that the settings were all correct to change to transparent but I was still seeing the player color ping, which is not what I remember happening before. When I turned off the HidePing my test account wasn’t being pinged at all. I didn’t have a lot of time to deep dive and switch to the Experimental server or anything though. I'm seeing this behavior with Ping Buddy as well. The transparency swap used to work, but something seems to have changed between when I published it and now.
keithcurtis said: I'm seeing this behavior with Ping Buddy as well. The transparency swap used to work, but something seems to have changed between when I published it and now. My first thought is to play with the setTimeout function, and to add some logging between steps to get an idea of what is happening. I added a quick sendChat step to Teleport after adjusting the color to transparent, and it was showing that the player object color had been changed, but visually I was still seeing the ping color.
keithcurtis said: Jarren said: And just fyi I was responding to the bug report I submitted yesterday, and also playing around with the Teleport script (I haven’t used it for a while) and noticed that the settings were all correct to change to transparent but I was still seeing the player color ping, which is not what I remember happening before. When I turned off the HidePing my test account wasn’t being pinged at all. I didn’t have a lot of time to deep dive and switch to the Experimental server or anything though. I'm seeing this behavior with Ping Buddy as well. The transparency swap used to work, but something seems to have changed between when I published it and now. Looking back through my help center requests, I first reported the issue with the transparent ping issue back in November, 2025. It has been documented and reported three times, but each time they were not able to reproduce the issue. It has only occurred in Jumpgate and was not happening at all in the legacy VTT. All except one of my games is now using Jumpgate, so this is not necessarily a fair comparison. I also wonder if this might be connected to the right click button ceasing to work or if it is a separate issue.  I have treated it as a different problem since the cessation of ping visibility occurs more often while the loss of right click functionality is more sporadic (but more intrusive).  Set up my Friday campaigns to have one with a visible ping and the other to hide ping.  Will do the same with my Saturday campaigns and see what happens.
Just an FYI that I heard back from Roll20 Support that they have reproduced the issue with transparent pings as I described. Hopefully that means they'll be able to put in a broader fix that will resolve your issue as well! 
Jarren said: Just an FYI that I heard back from Roll20 Support that they have reproduced the issue with transparent pings as I described. Hopefully that means they'll be able to put in a broader fix that will resolve your issue as well!  That is, I hope, good news.  I had it happen from the beginning in my Monday campaign.  My assigned color entering the game was transparent and I changed it, but all the pings (mine and others) still could not be seen.  I had turned the option to ping the teleported token off. It did appear again in my Tuesday campaign where I had altered the teleport ping to be bright yellow.  There was no use of teleport but the visible pings stopped working after nearly two hours. Wednesday's campaign had other issues which I spent time trying to document and no uses of the teleport mod was used.  The pings stopped being visible, but since everyone needed to refresh the VTT several times, it was inconsistent for everyone. I have taken the games and reversed the teleport effect (off vs colored announcement ping) to see what happens next week.
What scripts do you have loaded in the game? Have you tried disabling Teleport and seeing if it still happens? 
Update:  I have disabled Teleport in several games and still see the same issue of pings stopping to work. It seemed to work for a couple of sessions, until it didn't.  Pings still changed to transparent. Strangely in a different game where the teleport script was present but was not being used (no teleports were created or active. I noted last night that when the ping stopped working, my assigned color became transparent. It was previously bright green. I switched it back and the pings were still not visible. Not everyone in the game lost their visual ping at the same time, it happened to one of the players before my pings failed to show.   In my other games, I had changed the teleport settings to hide the ping and turned off the autoping.  Neither prevented the pings from becoming transparent.  I edited the teleport mod in notepad and changed the ping to red (#FF0000), and reinstalled it as a custom script, but still encountered the transparent pings. Not sure if this is definitive in ruling out the teleport mod as the source or part of the issue. Still working on collecting more data to report to the help center.
1779201131
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
Can you screen shot your list of active installed mods? It might give a clue.
keithcurtis said: Can you screen shot your list of active installed mods? It might give a clue. I am reasonably consistent in my mods.  I have three screen shots attached.  ToTD is a 5e 2014 campaign running in the default sandbox.  TLM is a 5e 2024 campaign which runs in the experimental sandbox. HoD is a mixed 2024/2014 campaign which runs in the experimental sandbox.  All are currently running in Jumpgate. 
ToTD
TLM
HoD
1779207888

Edited 1779238186
Here's a script that will watch for a player's color to be changed to/from transparent. It will watch for any API commands and report if any commands happened within the past 5 seconds, which could help determine if that is causing the player's color is changing. Edit: I updated the script to 1.1 with a little more robust error checking and a nicer interface. var PlayerColorWatcher = PlayerColorWatcher || (function () { 'use strict'; var version = '1.1', schemaVersion = 1; var defaults = { intervalSeconds: 1, whisperTarget: 'gm', chatMode: 'all', maxRecentCommands: 20 }; var css = { window: 'background:#d9ecff;border:2px solid #000;border-radius:6px;padding:6px;line-height:1.35;text-align:left;', title: 'font-weight:bold;text-align:center;margin:0 0 0 0;', button: 'display:inline-block;margin:-2px 0;padding:0px 4px;border:1px solid #000;border-radius:5px;background:#fff;color:#003366;font-weight:bold;text-decoration:none;', buttons: 'white-space:normal;text-align:left;', code: 'font-family:monospace;background:#fff;border:1px solid #999;border-radius:3px;padding:0 3px;' }; var recentCommands = [], timer = null; var normalizeIntervalSeconds = function (value) { value = parseFloat(value); if (isNaN(value)) value = defaults.intervalSeconds; return Math.max(1, Math.min(10, Math.round(value))); }; var normalizeChatMode = function (value) { value = String(value || '').toLowerCase(); if (value === 'all' || value === 'trackall' || value === 'everything') return 'all'; if (value === 'transparent' || value === 'tofromtransparent' || value === 'transparentonly') return 'transparent'; if (value === 'logonly' || value === 'none' || value === 'off') return 'logonly'; return defaults.chatMode; }; var checkInstall = function () { state.PlayerColorWatcher = state.PlayerColorWatcher || {}; state.PlayerColorWatcher.version = schemaVersion; state.PlayerColorWatcher.config = state.PlayerColorWatcher.config || {}; state.PlayerColorWatcher.players = state.PlayerColorWatcher.players || {}; Object.keys(defaults).forEach(function (key) { if (typeof state.PlayerColorWatcher.config[key] === 'undefined') state.PlayerColorWatcher.config[key] = defaults[key]; }); if (typeof state.PlayerColorWatcher.config.intervalMs !== 'undefined') { state.PlayerColorWatcher.config.intervalSeconds = Math.round(state.PlayerColorWatcher.config.intervalMs / 1000); delete state.PlayerColorWatcher.config.intervalMs; } if (typeof state.PlayerColorWatcher.config.chatMode === 'undefined') { state.PlayerColorWatcher.config.chatMode = state.PlayerColorWatcher.config.logOnlyTransparentChanges ? 'transparent' : state.PlayerColorWatcher.config.logAllChanges === false ? 'logonly' : 'all'; } delete state.PlayerColorWatcher.config.logAllChanges; delete state.PlayerColorWatcher.config.logOnlyTransparentChanges; delete state.PlayerColorWatcher.config.includeRecentCommands; state.PlayerColorWatcher.config.intervalSeconds = normalizeIntervalSeconds(state.PlayerColorWatcher.config.intervalSeconds); state.PlayerColorWatcher.config.chatMode = normalizeChatMode(state.PlayerColorWatcher.config.chatMode); }; var getConfig = function () { return state.PlayerColorWatcher.config; }; var getRecentCommandSeconds = function () { return getConfig().intervalSeconds * 6; }; var chatName = function () { return 'Player Color Watcher v' + version; }; var htmlEscape = function (str) { return String(str || '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>') .replace(/"/g, '"').replace(/'/g, '''); }; var logEscape = function (str) { return String(str || '').replace(/\s+/g, ' ').trim(); }; var makeButton = function (label, command) { return '<a style="' + css.button + '" href="' + htmlEscape(command) + '">' + label + '</a>'; }; var makeWindow = function (body) { return '<br><div style="' + css.window + '">' + body + '</div>'; }; var whisper = function (body) { sendChat(chatName(), '/w ' + getConfig().whisperTarget + ' ' + makeWindow(body)); }; var makeTitle = function (title) { return '<div style="' + css.title + '">' + htmlEscape(title) + '</div>'; }; var makeTitleWithButton = function (title, button) { return '<div style="text-align:center;font-weight:bold;margin:0 0 2px 0;">' + '<span style="float:right;font-weight:normal;">' + button + '</span>' + '<span>' + htmlEscape(title) + '</span></div><div style="clear:both;"></div>'; }; var getPlayerName = function (player) { return player.get('_displayname') || player.get('displayname') || player.id; }; var colorIsTransparent = function (color) { return String(color || '').toLowerCase() === 'transparent'; }; var shouldSendChatForChange = function (oldColor, newColor) { var mode = getConfig().chatMode; if (mode === 'all') return true; if (mode === 'transparent') return colorIsTransparent(oldColor) || colorIsTransparent(newColor); return false; }; var getChatModeLabel = function () { var mode = getConfig().chatMode; if (mode === 'all') return 'All'; if (mode === 'transparent') return 'Transparent'; if (mode === 'logonly') return 'Log Only'; return mode; }; var addRecentCommand = function (msg) { var cfg = getConfig(); recentCommands.push({ time: Date.now(), who: msg.who || 'Unknown', playerid: msg.playerid || '', content: msg.content || '' }); while (recentCommands.length > cfg.maxRecentCommands) recentCommands.shift(); }; var getRecentNonWatcherCommands = function () { var now = Date.now(), recentCommandSeconds = getRecentCommandSeconds(); return recentCommands.filter(function (cmd) { return now - cmd.time <= recentCommandSeconds * 1000 && !String(cmd.content || '').match(/^!pcw\b/); }); }; var getApiLogNote = function () { var matches = getRecentNonWatcherCommands(), cmd; if (!matches.length) return 'no api used'; cmd = matches[matches.length - 1]; return 'api: ' + logEscape(cmd.who) + ': ' + logEscape(cmd.content); }; var getRecentCommandSummary = function () { var matches = getRecentNonWatcherCommands(), recentCommandSeconds = getRecentCommandSeconds(); if (!matches.length) return '<br><b>Recent API commands:</b> none in the last ' + recentCommandSeconds + ' sec'; return '<br><b>Recent API commands:</b><br>' + matches.map(function (cmd) { return '• ' + htmlEscape(cmd.who) + ': <span style="' + css.code + '">' + htmlEscape(cmd.content) + '</span>'; }).join('<br>'); }; var initializePlayers = function () { var stored = state.PlayerColorWatcher.players; findObjs({ _type: 'player' }).forEach(function (player) { stored[player.id] = { name: getPlayerName(player), color: player.get('color') }; }); }; var checkPlayers = function () { var stored = state.PlayerColorWatcher.players; findObjs({ _type: 'player' }).forEach(function (player) { var id = player.id, name = getPlayerName(player), currentColor = player.get('color'), previousColor; if (!stored[id]) { stored[id] = { name: name, color: currentColor }; return; } previousColor = stored[id].color; if (previousColor !== currentColor) { stored[id] = { name: name, color: currentColor }; log('Player Color Watcher: ' + name + ' color changed from ' + previousColor + ' to ' + currentColor + ' | chat mode: ' + getChatModeLabel() + ' | ' + getApiLogNote()); if (shouldSendChatForChange(previousColor, currentColor)) { whisper( makeTitleWithButton('Color Changed', makeButton('⚙️', '!pcw')) + '<b>' + htmlEscape(name) + '</b> color: ' + '<b>' + htmlEscape(previousColor) + '</b> to ' + '<b>' + htmlEscape(currentColor) + '</b>' + getRecentCommandSummary() ); } } }); }; var showSettings = function () { var cfg = getConfig(); whisper( makeTitle('Settings') + '<b>Chat Mode:</b> ' + makeButton(getChatModeLabel(), '!pcw --mode|?{Chat output mode|All,all|Transparent,transparent|Log Only,logonly}') + '<br><b>Interval:</b> ' + makeButton('every ' + cfg.intervalSeconds + ' sec', '!pcw --interval|?{Polling interval in seconds, 1-10|' + cfg.intervalSeconds + '}') + '<br><b>Recent API Commands:</b> last ' + getRecentCommandSeconds() + ' sec' ); }; var setIntervalSeconds = function (value) { getConfig().intervalSeconds = normalizeIntervalSeconds(value); startTimer(); showSettings(); }; var setChatMode = function (value) { getConfig().chatMode = normalizeChatMode(value); showSettings(); }; var getPipedArgs = function (content) { var args = {}; (content.match(/--[^|]+(?:\|[^\s]+)?/g) || []).forEach(function (part) { var pieces = part.replace(/^--/, '').split('|'); args[String(pieces[0] || '').toLowerCase()] = pieces.slice(1).join('|'); }); return args; }; var handleInput = function (msg) { var args; if (msg.type === 'api') addRecentCommand(msg); if (msg.type !== 'api' || !msg.content.match(/^!pcw\b/)) return; if (!playerIsGM(msg.playerid)) { sendChat(chatName(), '/w "' + msg.who + '" ' + makeWindow(makeTitle('Permission Denied') + 'Only the GM can use this command.')); return; } args = getPipedArgs(msg.content); if (Object.keys(args).length === 0) { showSettings(); return; } if (typeof args.mode !== 'undefined' || typeof args.chatmode !== 'undefined') { setChatMode(typeof args.mode !== 'undefined' ? args.mode : args.chatmode); return; } if (typeof args.interval !== 'undefined') { setIntervalSeconds(args.interval); return; } showSettings(); }; var startTimer = function () { var cfg = getConfig(); if (timer) clearInterval(timer); timer = setInterval(checkPlayers, cfg.intervalSeconds * 1000); }; var registerEventHandlers = function () { on('chat:message', handleInput); }; on('ready', function () { checkInstall(); initializePlayers(); registerEventHandlers(); startTimer(); log('Player Color Watcher v' + version + ' ready.'); }); return {}; }());
1779212135
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
I don't see anything in the script lists that would auto-change color beyond what has been discussed already in this thread. Jarren's script looks like the best investigative bet.
keithcurtis said: I don't see anything in the script lists that would auto-change color beyond what has been discussed already in this thread. Jarren's script looks like the best investigative bet. I didn't think so either.  I have Jarren's script added to tonight's game.  I spent a few hours today on it, setting up maps and encounters and had no issue, but it usually does not occur until there are players in the game.  I have been urging my players to collect the console logs and report it to the help center, but figure few actually follow through on it.
So last night's game fell victim to the general outage.  Everything was going OK until the outage started affecting the functions: could not use the token bubble to adjust hp, damage buttons stopped working (2024 character sheet) for certain players, then the sandbox crashed.  Pings stopped working shortly after that, but with the sandbox down, the script did not fire. Next opportunity on Friday!