Greetings! Hope everyone had a great winter holiday and a safe and happy new year! This morning we pushed code with a lot of exciting changes! The Token Marker Update with Custom Token Marker Sets This morning we released an exciting,&nbsp; long-and-much-requested , new feature: Custom Token Markers! Token Markers are the little icons that are available in the radial menu when you select a token.&nbsp; They're a set of icons that Roll20 provides to help you track things on your token. As of today, your token markers are no longer bound by the default set provided! You may previously have known them as Status Indicators, Status Icons, or Status Indicator Overlays. We realized, however, that you can use them for so much more than statuses, so now they're just called&nbsp; Token Markers , and the wiki has been updated to reflect that.&nbsp; Please note :&nbsp; We are maintaining the "statusmarkers" programming object &nbsp;within the API to maintain your custom scripts. How to Use Them Creating Token Marker Sets To use your own token markers, you'll first want to get a set of markers that works for you. There are several icon packs in the Marketplace right now that creators have made that are downloadable as status icon sets. For these screen shots, I used a set from Czepeku called&nbsp; 80 Status Effect Icons . Stay tuned, though! In a couple of weeks, marketplace creators will be able to create and submit their own token marker sets for sale. The ideal size for a token marker is 512 x 512, and marketplace creators making their own sets should use these dimensions. When they get applied to your token, they'll be resized to 48 x 48 or smaller, depending on the token size and scaling of the markers, but the larger size future-proofs your tokens for a future feature. Token markers can be .gif, .png, or .jpeg/.jpg formats. Animated token markers are not supported at this time; if you upload an animated gif, only one frame will be uploaded and displayed. Note: &nbsp;Token markers do count towards the storage quota, based on the 512 x 512 image size. Creating token marker sets is available without limitation to all users. Purchased marketplace token marker sets, when available, will not count towards your storage quota. After you have some images you want to use, upload your token marker set to your library. Go to Tools &gt; Token Marker Library. You'll see the Token Set Library: The first time you visit, you'll only see the default token marker set. However, if you click the Create Set button, you'll be prompted to name your new set of token markers: Name your new marker set and click Create Set. The new empty set will be available in the library, and you will automatically be taken to its page to upload your markers: Click the Add Images button or link to upload images to your token set: Drag and drop your files onto the box and click Upload when you're ready. You'll need to wait a minute while the files upload. Once they finish, you'll be prompted to view the markers and rename them if you like: Note that when naming your token markers, you can only use letters, numbers and the "-" character. Spaces will be converted to underscore characters. Click Save. The markers will be added to the token marker set in your library. Adding a Token Marker Set to a Game Now that you have your custom token marker set uploaded, you should add it to a game! Open the game details page for the campaign you want to add your markers. I picked my Curse of Strahd game: In the right-hand column, you'll see "Token Marker Sets." That shows which sets are in the current game. Click the + icon to add a set to the game: Select the set or sets you want to add, and click Update. If you click Create New Set here, you'll be taken to the Token Marker Library. After you click Update, the token markers will be available in game. Note: &nbsp;Players currently in the game will need to reload the VTT in order to see the new token markers. You can reorder the sets that are in the game! Hover over the set to get the arrows and then click and drag it up or down: Removing Token Marker Sets from a Game Click the three dot menu to remove the token marker set from the game, or to view it in the library. It is possible to remove the default token marker set entirely from the game. Note: &nbsp;You cannot remove the color dots or the red "X" overlay from the token markers. If you remove a token marker set from a game, and you had tokens that were using those markers, the markers will no longer be visible on the token. However, when you add the token marker set back to the game, the markers on those tokens will reappear. Removing and Renaming Token Markers To remove a token marker from a set or rename it, open the set from your Token Marker Library and click the token marker to select it: You can click the Rename or Delete links to edit the markers. Note that when naming your token markers, you can only use letters, numbers and the "-" character. Spaces will be converted to underscore characters. Renaming and Deleting Token Marker Sets To remove a token marker from a set or rename it, open the set from your Token Marker Library and click the token marker to select it: You can rename the set and click Rename Set, or click Delete Set to remove it entirely. Selecting the New Token Marker To select your new token marker, click the radial menu and open the token marker menu as normal. Your custom markers will be available in the menu. If you had put the custom token marker set above the default set in the campaign details page, they will appear above the default set in this menu. How Does It Work with the API? One of the big challenges we had with this update was the API. There are several scripts that use the token markers, and we didn't want to break that functionality. If you're an API author and you want to know how to access the token marker IDs in your scripts, here's how! Please note :&nbsp; We are maintaining the "statusmarkers"&nbsp; programming object &nbsp;within the API to maintain your custom scripts. A new function has been added to the Roll20 API to support custom Token Markers. This information is stored under the campaign node as ‘token_markers’. it can be accessed from the api via Campaign().get( "token_markers" ); This information is read-only. The return value will a stringified JSON array containing an object for each token marker currently in the game. { &nbsp;&nbsp;&nbsp;&nbsp; "id" : 59 ,&nbsp; // the database id for the &nbsp;&nbsp;&nbsp;&nbsp; "name" : "Bane" ,&nbsp; // the name (non-unique) of the marker &nbsp;&nbsp;&nbsp;&nbsp; "tag" : "Bane::59" ,&nbsp; // how the token is actually referenced &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // this will include the id for custom markers, but not &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // for default markers. &nbsp;&nbsp;&nbsp;&nbsp; "url" : " <a href="https://s3.amazonaws.com/files.d20.io/images/59/yFnKXmhLTtbMtaq-Did1Yg/icon.png?1575153187" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/59/yFnKXmhLTtbMtaq-Did1Yg/icon.png?1575153187</a>" &nbsp;&nbsp;&nbsp;&nbsp; // ^the url for the token marker's image } We’ve written an example script to show how you can use this to find Token Markers available in your Campaign. Add this Script to your game and these commands will be available: !markernames &nbsp;will output all markers to the chat with the image, name and id !markerids &lt;name&gt; &nbsp;will output any/all markers to the chat that match the provided name !settokenmarker &lt;string&gt; &nbsp;will add the provided string to the currently selected token’s marker list. Note that this doesn’t do any validation to make sure the Token Marker exists, it simply adds the provided value to the token markers. !gettokenmarkers &nbsp;outputs the currently selected token’s statusmarker attribute to the chat. on( "ready" , () =&gt; { &nbsp;&nbsp;&nbsp;&nbsp; const &nbsp; tokenMarkers = JSON.parse(Campaign().get( "token_markers" )); &nbsp;&nbsp;&nbsp;&nbsp; const &nbsp; getChatMessageFromTokenMarkers = markers =&gt; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; let chatMessage =&nbsp; '' ; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _.each(markers, marker =&gt; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chatMessage += `&lt;p&gt;&lt;img src= '${marker.url}' &gt; ${marker.id}: ${marker.name}&lt;/p&gt;`; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &nbsp; chatMessage; &nbsp;&nbsp;&nbsp;&nbsp; }; &nbsp; on( "chat:message" , msg =&gt; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (msg.content.split( " " )[ 0 ].toLowerCase() ===&nbsp; '!markernames' ) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; let chatMessage = getChatMessageFromTokenMarkers(tokenMarkers); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sendChat( "Token Markers" , chatMessage); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; else &nbsp; if (msg.content.split( " " )[ 0 ].toLowerCase() ===&nbsp; '!markerids' ) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const &nbsp; markerName = msg.content.split( " " )[ 1 ].toLowerCase(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; let results = []; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _.each(tokenMarkers, marker =&gt; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (marker.name.toLowerCase() === markerName) results.push(marker); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; log(results); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; let chatMessage = getChatMessageFromTokenMarkers(results); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; chatMessage = chatMessage ||&nbsp; 'Unable to find any matching token markers' &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sendChat( "Token Markers" , chatMessage); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; else &nbsp; if (msg.content.split( " " )[ 0 ].toLowerCase() ===&nbsp; '!settokenmarker' ) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const &nbsp; markerName = msg.content.split( " " )[ 1 ].toLowerCase(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if &nbsp; (!msg.selected &amp;&amp; msg.selected[ 0 ]._type ==&nbsp; "graphic" )&nbsp; return ; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj = getObj(msg.selected[ 0 ]._type, msg.selected[ 0 ]._id); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentMarkers = obj.get( "statusmarkers" ).split( ',' ); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentMarkers.push(markerName); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.set( "statusmarkers" , currentMarkers.join( ',' )); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; else &nbsp; if (msg.content.split( " " )[ 0 ].toLowerCase() ===&nbsp; '!gettokenmarkers' ) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if &nbsp; (!msg.selected)&nbsp; return ; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if &nbsp; (msg.selected[ 0 ]._type !==&nbsp; "graphic" )&nbsp; return ; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj = getObj(msg.selected[ 0 ]._type, msg.selected[ 0 ]._id); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentMarkers = obj.get( "statusmarkers" ); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sendChat( "Token Markers" , currentMarkers); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp;&nbsp; }); }); What's Next? This is a major update and has spent several weeks in testing on the Development server. We're looking forward to supporting token marker sets on the marketplace, plus a few quality of life improvements that are already underway, like copying token markers from one set to another-- that feature is hitting the Dev server this week, so if you're a Pro user, be sure to check it out! As always, please feel free to report any bugs or feedback in the dedicated feedback thread for this new feature! Other Changes Handouts no longer save "Loading..." when you edit them while the handout or game is still loading, resulting in data loss. Now, if the handout is still loading, any changes you make will not be saved. Marketplace items with an apostrophe in them no longer fail during purchase. A minor typo was fixed in the large map warning message. Character Sheets D&amp;D 5e by Roll20 NPC traits and reactions now work like PC traits Added roll buttons in the global modifier fields. Spell slots code was updated and refactored Pathfinder 2 by Roll20 Apply Settings now applies critical roll options Fate by Roll20 A toggle option between Fate Core and Fate Accelerated Quality of Life improvements, such as moving Aspects up and making stress tracks a repeating section. Licensed Product Patch Notes D&amp;D 5e: SRD:&nbsp; Giant boar hit point dice updated. Monster Manual:&nbsp; Giant boar hit point dice updated. Reckless trait added to white abishai. Descent into Avernus Patch 1.5:&nbsp; added the Reckless trait to the white abishai character sheet. Check This Out The next community roundtable is this Thursday, January 9!&nbsp; Read the details here &nbsp;and mark your calendar to join in the chat if you have questions to ask! Roll20 staff had a roundtable on December 13. Catch the video&nbsp; here ! Looking for previous release notes? Read the&nbsp; full list on the helpdesk , or check out the&nbsp; most recent note &nbsp;here.