Astral Projection Creates a character called "Astral Presence" to represent things only a few players can see, shown as a pink circle of color with a name.&nbsp; Idea from this discussion:&nbsp;<a href="https://app.roll20.net/forum/post/6780930/player-specific-map-overlays" rel="nofollow">https://app.roll20.net/forum/post/6780930/player-specific-map-overlays</a> Commands: !ap -- create an Astral Presence spot for each selected token, named after it and sized appropriately.&nbsp; The token will have (Astral) appended to the name. You can also drag the character out to get a general purpose astral spot. To reveal all the Astral Presence spots to your players of choice, add them as controllers on the Astral Presence Character. Code: on('ready',function(){ const clearURL = '<a href="https://s3.amazonaws.com/files.d20.io/images/4277467/iQYjFOsYC5JsuOPUCI9RGA/thumb.png?1401938659" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/4277467/iQYjFOsYC5JsuOPUCI9RGA/thumb.png?1401938659</a>'; const auraColor = '#ff00ff'; let AstralCharacter; const assureCharacter = () =&gt; { AstralCharacter = findObjs({ type: 'character', name: 'Astral Presence' })[0]; if(!AstralCharacter){ AstralCharacter = createObj('character',{ name: 'Astral Presence' }); let p = findObjs({type:'page'})[0]; let t = createObj('graphic',{ imgsrc: clearURL, layer: 'objects', pageid: p.id, width: 70, height: 70, top: -1000, left: 0, name: `Astral Presence`, represents: AstralCharacter.id, aura1_color: auraColor, aura1_square: false, aura1_radius: 0.000001, showname: true, showplayers_name: false, showplayers_bar1: false, showplayers_bar2: false, showplayers_bar3: false, showplayers_aura1: false, showplayers_aura2: false, playersedit_name: true, playersedit_bar1: true, playersedit_bar2: true, playersedit_bar3: true, playersedit_aura1: true, playersedit_aura2: true }); setDefaultTokenForCharacter(AstralCharacter,t); setTimeout(()=&gt;t.remove(),100); } }; assureCharacter(); const doAstralPresence = (token) =&gt; { let baseObj = { imgsrc: clearURL, layer: token.get('layer'), pageid: token.get('pageid'), name: `${token.get('name')} (Astral)`, aura1_color: auraColor, aura1_square: false, aura1_radius: 0.000001, represents: AstralCharacter.id, width: token.get('width'), height: token.get('height'), top: token.get('top'), left: token.get('left'), showname: true, showplayers_name: false, showplayers_bar1: false, showplayers_bar2: false, showplayers_bar3: false, showplayers_aura1: false, showplayers_aura2: false, playersedit_name: true, playersedit_bar1: true, playersedit_bar2: true, playersedit_bar3: true, playersedit_aura1: true, playersedit_aura2: true }; let ap = createObj('graphic',baseObj); setTimeout(()=&gt;toFront(ap),0); }; on('chat:message',function(msg){ var cmd,ids; if('api' !== msg.type || !playerIsGM(msg.playerid) ){ return; } ids = msg.content.split(/\s+/); cmd = ids.shift(); ids = _.union(ids, ((msg.selected &amp;&amp; _.pluck(msg.selected,'_id')) || []) ); switch(cmd){ case '!ap': _.chain(ids) .uniq() .map( (id) =&gt; getObj('graphic',id) ) .reject(_.isUndefined) .each( doAstralPresence ); break; } }); }); Support my work on If you use my scripts, want to contribute, and have the spare bucks to do so , go right ahead. However, please don't feel like you must contribute just to use them! I'd much rather have happy Roll20 users armed with my scripts than people not using them out of some sense of shame. Use them and be happy, completely guilt-free! Disclaimer: This Patreon campaign is not affiliated with Roll20; as such, contributions are voluntary and Roll20 cannot provide support or refunds for contributions.