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


Hello, Is it a normal behaviour that token markers don't copy from tokens on different maps ? The hp copy, but if I set a token marker to a Token, it doesn't update the tokens on the other maps... Is it normal ? Is it doable ??
Depends on whether you are dragging a new token to a page or you are copying. HP is a property of the character that the token picks up if it is linked to the character. Every token brought into a page is a new token, but if a character has a default token, all the properties of that default token are brought in, including any link to a character sheet previously established and any token markers assigned to that token when it was assigned as a default . If you want to assign a token marker and have it carry over to another map when you drag a token onto a page, you have to make that token the default for that character. You can copy a token and paste it to a new page and that carries over token markers. With API, you might be able to have auto updating across pages, but I don't know of any that do this.
Yeah, my idea was to have a listener for the token graphic changes to be able to auto update the token markers from one map to another. I already have a script for following the exhaustion so I wonder if something like that is scriptly doable through a kind of snippet...? thanks for your answer
It's definitely doable. I just don't know of any script that does it!

Edited 1683479705
Forum Champion
Token Markers do not automatically populate to other tokens, only the token bars(bubbles) do. This is because they are changing the character sheet/attributes and then that gets applied to the tokens. However, if you update the default token with the token marker on the token then you can hit Apply Default Tokens while editing the character and it will update the token to all the tokens in the game.  Of course, there may be an Mod, as you were discussing above. 
The Aaron
Forum Champion
API Scripter
If you set them with TokenMod using the Character ID, it will set it on all tokens that represent that character.  !token-mod --set statusmarkers|+blue --ids @{selected|character_id} A script could be written that synchronizes the statusmarkers for tokens across pages, probably you'll only want to do it for tokens controlled by players, otherwise all your goblins might get the same mark. 
Hey The Aaron,  Yes you're right, that's exactly what i was looking for. I know about the token-mod with character id trick, but i have so many sources that could apply a condition that i cannot only rely on TM for that.  If a script can be written to listen to any "controlledby" token across all pages that'd be wonderful.  Thanks. 
The Aaron
Forum Champion
API Scripter
Ok. See how this works for you.  It will update player controlled tokens if you manually change them, or use TokenMod.  Additionally, you can call a command to force a sync of all player controlled tokens, with the caveat that it simply finds the one with the most statuses, and syncs them all to that.  Here's that command: !sync-all-token-status And here's the code: /* global TokenMod */ on('ready',()=>{ const isPlayerCharacter = (character) => { let players = character.get('controlledby') .split(/,/) .filter(s=>s.length); return players.includes('all') || undefined !== players.find((p)=>!playerIsGM(p)); }; const isPlayerToken = (token) => { let players = token.get('controlledby') .split(/,/) .filter(s=>s.length); if( players.includes('all') || undefined !== players.find((p)=>!playerIsGM(p))) { return true; } return isPlayerCharacter(getObj('character',token.get('represents')) || {get: function(){return '';} } ); }; const syncAllDuplicates = (obj) => { findObjs({ type: 'graphic', represents: obj.get('represents') }).forEach(o=>o.set('statusmarkers',obj.get('statusmarkers'))); }; const handleChangeGraphic = (obj,prev) => { if(isPlayerToken(obj) && obj.get('statusmarkers') !== prev.statusmarkers){ syncAllDuplicates(obj); } }; const syncAllCharacterTokens = (cid) => { let tokens = findObjs({type:'graphic', represents: cid}); let s = tokens.reduce((m,t)=> m.split(/,/).length>t.get('statusmarkers').split(/,/).length ? m : t.get('statusmarkers') ,''); if(s.length){ tokens.forEach(t=>t.set('statusmarkers',s)); } }; const syncAllStatusMarkers = (who) => { let graphics = findObjs({type: 'graphic'}); let characters = []; const processCharacters = () => { let cid = characters.shift(); if(cid){ syncAllCharacterTokens(cid); setTimeout(processCharacters,0); } else { sendChat('',`/w "${who}" <div>Synchronized all character tokens.</div>`); } }; const buildCharacterList = () => { let t = graphics.shift(); if(t){ let cid = t.get('represents'); if(cid){ characters.push(cid); } setTimeout(buildCharacterList,0); } else { characters = [ Set(characters)]; setTimeout(processCharacters,0); } }; buildCharacterList(); }; on('chat:message',msg=>{ if('api'===msg.type && /^!sync-all-token-status(\b\s|$)/i.test(msg.content) && playerIsGM(msg.playerid)){ let who = (getObj('player',msg.playerid)||{get:()=>'API'}).get('_displayname'); syncAllStatusMarkers(who); } }); on('change:graphic',handleChangeGraphic); if('undefined' !== typeof TokenMod && TokenMod.ObserveTokenChange){ TokenMod.ObserveTokenChange(handleChangeGraphic); } });