I had a go at mocking this up, and while the mulit-sided token will work, I found it to have a bit too much "flicker" as it changed sides, so I mocked up a separate implementation where I used TokenMod + Metascripts to assign the image source of the token. First, the multi-sided token option: The command line in the GIF (shown in the roll template) left a little off. Here is the full command line I used: !{{(^) {&select KokoroFade, +layer in [objects,gmlayer]} !token-mod --set currentside|1 !token-mod --set layer|objects {^&delay .25} !token-mod --set currentside|2 {^&delay .25} !token-mod --set currentside|3 {^&delay .25} !token-mod --set currentside|4 {^&delay .25} !token-mod --set currentside|5 {^&delay .25} !token-mod --set currentside|6 {^&delay .25} !token-mod --set currentside|7 {^&delay .25} !token-mod --set currentside|8 {^&delay .25} !token-mod --set currentside|9 {^&delay .25} !token-mod --set currentside|10 {^&delay .25} !multiTokenFx burst death {^&delay .25} }} Note that for this one I planned on having the token (named KokoroFade) set to a transparent face to begin with, and positioned on the GM layer, so the first thing the command does is set the token to be the first face (10% opacity), and then it gets moved to the objects layer. After that, we cycle through sides that show images which are 10% increases in opacity, before finally erupting in an FX burst. Scripts Required: MetascriptToolbox TokenMod multiTokenFx (see code & note at the bottom) Better Solution by Setting imgsrc of Token Here's the other (and better, IMO) solution I found, built around using TokenMod to change the imgsrc property of the token. To make this work, I still used the same rollable table of images (10 images, each in 10% opacity increments up to 100%). I created a token from this rollable table, named it "KokoroFadeSource," and placed it on the GMLayer. Then I placed a normal token (not mutli-sided) for the character I wanted to have fade in, and also on the GMLayer. This one I named "KokoroFade". The logic to this goes: ... set the token's imgsrc property to be a transparent png (using a hard-coded URL from my library for a fully transparent png) ... retrieve the sides list from the source token ... use a Plugger replace() function to replace the pipe-separators with new line characters and TokenMod verbiage to set up individual commands that will change the imgsrc of the main token, including individual {&delay values} to give the effect time to manifest Note: I preexamined my images to see that they had 2 particular cache values on the end, which I also included in the find/replace so that I could strip the values off. In the end, the command line is slimmer and more token-agnostic, and the effect is smoother. Here is the command: !{{(^) {&select KokoroFade, +layer in [gmlayer,objects]} !token-mod --set imgsrc|<a href="https://s3.amazonaws.com/files.d20.io/images/396805006/y_oYWA8ZypRaDvyLVsFuAQ/original.png" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/396805006/y_oYWA8ZypRaDvyLVsFuAQ/original.png</a> !token-mod --set layer|objects {^&delay .1} !token-mod --set imgsrc|{&eval}replace(--source|"@(KokoroFadeSource.sides)" --find#"https%3A"#"https:" --find|%3F1718223729|' ' --find|%3F1718223730|' ' --find#"|"#"{&^delay .25}{&cr}!token-mod --set imgsrc|"){&/eval}{&^delay .25} !multiTokenFx burst death {^&delay .25} }} And here is the effect in action: A Note About multiTokenFx I'm using a script I nabbed from Nick O in this video , but which I have modified to work with metascripts. The version I'm using is below: /* */ on('ready', () => { on("chat:message", msg => { if (msg.type !== "api") { return; } let args = msg.content.split(/\s+/); if (args[0] == "!multiTokenFx") { if (!msg.selected) { sendChat("MultiFX", "/w gm please select some tokens"); return; } let fxType = args[1].toLowerCase(); let fxColor = args[2].toLowerCase(); let fxTypes = ['beam', 'bomb', 'breath', 'bubbling', 'burn', 'burst', 'explode', 'glow', 'missile', 'nova', 'splatter']; let fxColors = ['acid', 'blood', 'charm', 'death', 'fire', 'frost', 'holy', 'magic', 'slime', 'smoke', 'water']; if (fxTypes.includes(fxType) && fxColors.includes(fxColor)) { let fullFx = fxType + "-" + fxColor; msg.selected.forEach(selectedItem => { if (selectedItem._type == "graphic") { let token = getObj("graphic", selectedItem._id); spawnFx(token.get("left"), token.get("top"), fullFx, token.get("pageid")); } }); } else { if(!fxTypes.includes(fxType)){ sendChat("MultiFX", `/w gm Acceptable fxTypes include: ${fxTypes.join(', ')}`); } if (!fxColors.includes(fxColor)) { sendChat("MultiFX", `/w gm Acceptable fxColors include: ${fxColors.join(', ')}`); } } } }); }); /* */