{"name":"Vortex","type":"script","author":"BEL3Iav6K058rvXZ","img":"modules/JB2A_DnD5e/Library/Generic/Template/Circle/Vortex_01_Regular_Blue_Thumb.webp","scope":"global","command":"/*\n####################################################\n   This macro needs the Sequencer module to work.\n   Also, you need to select at least one token\n####################################################\n*/\n// You can find its documentation on Github : https://github.com/fantasycalendar/FoundryVTT-Sequencer/wiki\n\nlet effectScale = 1.5;\nconst vortexEffects = Sequencer.EffectManager.getEffects({ object: token, name: \"Vortex\" }); \n\n// If an effect exist, let's dismiss it. Otherwise, let's create one.\nif(vortexEffects.length){\n    await Sequencer.EffectManager.endEffects({ object: token, name: \"Vortex\" })\n}\nelse{\n\nnew Sequence()\n//Will play the intro sequence of a blue vortex animation.\n    .effect()\n        .file(\"jb2a.template_circle.vortex.intro.blue\") //Edit this line to customize the intro animation as follow : jb2a.template_circle.vortexvortex.intro.color\n        .scaleToObject(effectScale)\n        .attachTo(token)\n        .belowTokens() \n        .waitUntilFinished(-1000)\n//Then it will transition to the loop sequence of a blue vortex animation.\n    .effect()\n        .file(\"jb2a.template_circle.vortex.loop.blue\") //Edit this line to customize the loop animation as follow : jb2a.template_circle.vortexvortex.loop.color\n        .scaleToObject(effectScale)\n        .attachTo(token)\n        .belowTokens()\n        .persist()\n        .name(\"Vortex\")\n        .fadeIn(500)\n        .fadeOut(500)\n        .waitUntilFinished(-1000)\n//Finally it will play the outro sequence of a blue vortex animation as follow : jb2a.template_circle.vortexvortex.outro.color\n    .effect()\n        .file(\"jb2a.template_circle.vortex.outro.blue\") //Edit this line to customize the outro animation.\n        .scaleToObject(effectScale)\n        .attachTo(token)\n        .belowTokens() \n    .play()\n}","folder":null,"sort":0,"flags":{"advanced-macros":{"runAsGM":false,"runForSpecificUser":""},"core":{"sourceId":"Macro.e3oACqy4EALxW2N9"}},"_id":"0A7GsVcYO7oJ5s22","ownership":{"BEL3Iav6K058rvXZ":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.2.1","coreVersion":"10.291","createdTime":null,"modifiedTime":1717070409976,"lastModifiedBy":"n1PqRj2wSLmNmxBt"}}
{"name":"Icosahedron","type":"script","author":"BEL3Iav6K058rvXZ","img":"modules/JB2A_DnD5e/Library/Generic/Energy/IcosahedronStarAbove_01_Regular_BlueYellow_Thumb.webp","scope":"global","command":"/*\n####################################################\n   This macro needs the Sequencer module to work.\n   Also, you need to select a token\n####################################################\n*/\n\nconst effectScale = 1.6; // The scale will be depending on the token size already. this serves as a multiplier if you want all of them smaller or larger.\nconst effectFade = 500; // How long do you wish the fade in and fade out to be (in milliseconds)?\n\n//In this loop, we'll apply the effect on the selected token, unless an effect with the same name already exists, in which case, we'll dismiss it.\nconst isoEffects = Sequencer.EffectManager.getEffects({  name: `${token.name}-Isocahedron_${token.id}` }); \nif(isoEffects.length){\n    await Sequencer.EffectManager.endEffects({  name: `${token.name}-Isocahedron_${token.id}` })\n}\nelse{\n    new Sequence() \n        .effect()\n            .attachTo(token)        \n            .file(`jb2a.icosahedron.star.below.blueyellow`)\n            .belowTokens()//by default, the effect would be played above the tokens, we want this one to be played underneath so we can place the overlay above it\n            .scaleToObject(effectScale)\n            .fadeIn(effectFade, {ease: \"easeOutCubic\"})\n            .fadeOut(effectFade, {ease: \"easeOutCubic\"})\n            .persist()\n            .name(`${token.name}-Isocahedron_${token.id}`)\n        .effect()\n            .attachTo(token)\n            .file(`jb2a.icosahedron.star.above.blueyellow`)\n            .scaleToObject(effectScale)\n            .fadeIn(effectFade, {ease: \"easeOutCubic\"})\n            .fadeOut(effectFade, {ease: \"easeOutCubic\"})\n            .persist()\n            .name(`${token.name}-Isocahedron_${token.id}`)\n            .play();\n}","folder":null,"sort":0,"flags":{"advanced-macros":{"runAsGM":false,"runForSpecificUser":""},"core":{"sourceId":"Macro.td0FSeUvPTLRf3aP"}},"_id":"4PTLjC4A3S3UlwY2","ownership":{"BEL3Iav6K058rvXZ":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.2.1","coreVersion":"10.291","createdTime":null,"modifiedTime":1717070326107,"lastModifiedBy":"n1PqRj2wSLmNmxBt"}}
{"name":"Magic Circle","type":"script","author":"BEL3Iav6K058rvXZ","img":"modules/JB2A_DnD5e/Library/Generic/Magic_Signs/EvocationCircleIntro_02_Regular_Red_Thumb.webp","scope":"global","command":"/*\n####################################################\n   This macro needs the Sequencer module to work.\n   Also, you need to select a token\n####################################################\n*/\n//You can find its documentation here on Github : https://github.com/fantasycalendar/FoundryVTT-Sequencer/wiki\n\nlet effectScale = 2;\nconst magicCircleEffects = Sequencer.EffectManager.getEffects({ name: `${token.name}_Magic-Circle_${token.id}` }); \n\n// If an effect exist, let's dismiss it. Otherwise, let's create one.\nif(magicCircleEffects.length){\n    await Sequencer.EffectManager.endEffects({ name: `${token.name}_Magic-Circle_${token.id}` })\n}\nelse{\nnew Sequence()\n//Will play the intro and stay on the looped part because of the persist and once dismissed, will transition to the ending sequence!\n    .effect()\n        .file(\"jb2a.magic_signs.circle.02.evocation.complete.red\") \n        .scaleToObject(effectScale)\n        .atLocation(token)\n        .belowTokens()\n        .persist()\n        .name(`${token.name}_Magic-Circle_${token.id}`)\n    .play()\n}","folder":null,"sort":0,"flags":{"advanced-macros":{"runAsGM":false,"runForSpecificUser":""},"core":{"sourceId":"Macro.e3oACqy4EALxW2N9"}},"_id":"59QD8R6jX5whsSEg","ownership":{"BEL3Iav6K058rvXZ":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.2.1","coreVersion":"10.291","createdTime":null,"modifiedTime":1717070348948,"lastModifiedBy":"n1PqRj2wSLmNmxBt"}}
{"name":"Flask Throw","type":"script","author":"57wlqmR4nbpd6oQC","img":"modules/JB2A_DnD5e/Library/Generic/Weapon_Attacks/Ranged/ThrowFlask01_01_Regular_Orange_Thumb.webp","scope":"global","command":"/*\n####################################################\n   This macro needs the Sequencer module to work.\n   Also, you need to target at least one token and select the token who will be throwing the flask\n####################################################\n*/\n\n// Let's create a function with arguments. That means that we can call this function later and define each argument (here they're called dbThrow, dbFracture and dbExplosion);\n// If you look at the end of the macro, we're using each arg to call a specific Database path. (i.e: await grenade('dbPath01', 'dbPath02', 'dbPath03'))\nasync function grenade(dbThrow, dbFracture, dbElemental, dbElemental2, dbSideExplosion, dbExplosion ){\n    let source = token; // this is the first selected token\n    let targets = Array.from(game.user.targets); // This is an array that will contain all targeted tokens (we need at least one to know where to throw the potion or grenade)\n        for(let target of targets){ // The for loop will iterate for each target, if more than one token is targeted. Otherwise it will run it only once\n        new Sequence()\n        .effect() \n            .file(dbThrow)\n            .atLocation(source)\n            .stretchTo(target)\n            .waitUntilFinished(-150)\n        .effect()\n            .file(dbFracture)\n            .atLocation(target)\n            .scale(0.5)\n            .rotateTowards(source) // we rotate it so it points back towards the token throwing the potion and add a 180 degrees rotation to it\n            .rotate(180)\n        .effect()\n            .file(dbElemental)\n            .atLocation(target)\n            .scale(0.5)\n            .rotateTowards(source)\n            .rotate(180)\n        .effect()\n            .file(dbElemental)\n            .atLocation(target)\n            .scale(0.35)\n            .mirrorY()\n            .rotateTowards(source)\n            .rotate(180)\n        .effect()\n            .file(dbElemental2)\n            .atLocation(target)\n            .scale(0.35)\n            .mirrorY()\n            .rotateTowards(source)\n            .rotate(180)    \n        .effect()\n            .file(dbSideExplosion)\n            .atLocation(target)\n            .scale(0.65)\n            .mirrorY()\n            .rotateTowards(source)\n            .rotate(180)\n            .tint(\"#92CBFF\")                    \n        .effect()\n            .file(dbExplosion)\n            .atLocation(target)\n            .scale(0.35)\n            .tint(\"#92CBFF\") //Tints the assets with a blue colour\n            .randomRotation()   \n        .play();\n        \n        let delay = Sequencer.Helpers.random_int_between(600, 1000) // neat little helper from Sequencer giving us a whole number between two values\n        await Sequencer.Helpers.wait(delay) // another helper that allows us to delay the time between each loop (when we have more than one target)\n        \n        }\n    }\nawait grenade('jb2a.throwable.throw.flask.01.orange','jb2a.explosion.side_fracture.flask.01','jb2a.side_impact.part.fast.ice_shard.blue', 'jb2a.side_impact.part.slow.snowflake.blue','jb2a.smoke.puff.side.02.white.1','jb2a.smoke.puff.ring.01.white.2');","folder":null,"sort":0,"flags":{"core":{"sourceId":"Macro.W2QYYoDR3ulKzbkt"},"advanced-macros":{"runForSpecificUser":""}},"_id":"8wJXfuRBWsvtabMM","ownership":{"default":0,"57wlqmR4nbpd6oQC":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.2.1","coreVersion":"10.291","createdTime":null,"modifiedTime":1717070238680,"lastModifiedBy":"n1PqRj2wSLmNmxBt"}}
{"name":"Whirl","type":"script","author":"BEL3Iav6K058rvXZ","img":"modules/JB2A_DnD5e/Library/Generic/Template/Circle/Whirl_01_Regular_Blue_Thumb.webp","scope":"global","command":"/*\n####################################################\n   This macro needs the Sequencer module to work.\n   Also, you need to select at least one token\n####################################################\n*/\n// You can find its documentation on Github : https://github.com/fantasycalendar/FoundryVTT-Sequencer/wiki\n\nconst effectScale = 1.5;\n// First, check if an effect with the name \"Whirl\" exists on the selected token.\nconst whirlEffects = Sequencer.EffectManager.getEffects({ object: token, name: \"Whirl\" });\n\n// If an effect exist, let's dismiss it. Otherwise, let's create one.\nif(whirlEffects.length){\n    await Sequencer.EffectManager.endEffects({ object: token, name: \"Whirl\" })\n}\nelse{\n    new Sequence()\n//Will play the intro sequence of a blue whirl animation.\n    .effect()\n        .file(\"jb2a.template_circle.whirl.intro.blue\") //Edit this line to customize the intro animation as follow : jb2a.template_circle.whirl.intro.color\n        .attachTo(token)\n        .scaleToObject(effectScale)\n        .belowTokens() \n        .waitUntilFinished(-1000)\n//Then it will transition to the loop sequence of a blue whirl animation.\n    .effect()\n        .file(\"jb2a.template_circle.whirl.loop.blue\") //Edit this line to customize the loop animation as follow : jb2a.template_circle.whirl.loop.color\n        .attachTo(token)\n        .scaleToObject(effectScale)\n        .belowTokens()\n        .persist()\n        .name(\"Whirl\")\n        .fadeIn(500)\n        .fadeOut(500)\n        .waitUntilFinished(-1000)\n//Finally it will play the outro sequence of a blue whirl animation as follow : jb2a.template_circle.whirl.outro.color\n    .effect()\n        .file(\"jb2a.template_circle.whirl.outro.blue\") //Edit this line to customize the outro animation.\n        .attachTo(token)\n        .scaleToObject(effectScale)\n        .belowTokens() \n    .play()\n}","folder":null,"sort":0,"flags":{"advanced-macros":{"runAsGM":false,"runForSpecificUser":""},"core":{"sourceId":"Macro.e3oACqy4EALxW2N9"}},"_id":"8wTsHszafgDbzIK8","ownership":{"BEL3Iav6K058rvXZ":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.2.1","coreVersion":"10.291","createdTime":null,"modifiedTime":1717070461660,"lastModifiedBy":"n1PqRj2wSLmNmxBt"}}
{"name":"Arrows - Bolts","type":"script","author":"BEL3Iav6K058rvXZ","img":"modules/JB2A_DnD5e/Library/Generic/Weapon_Attacks/Ranged/Arrow01_01_Regular_White_Thumb.webp","scope":"global","command":"/*\n####################################################\n   This macro needs the Sequencer module to work.\n   Also, you need to target at least one token and select the one who will shoot the arrow.\n####################################################\n*/\n//You can find the Sequencer module documentation here on Github : https://github.com/fantasycalendar/FoundryVTT-Sequencer/wiki\n\n//You can use the \"Show Sequencer Database\" Tool in the left-hand side toolbar to preview all our available animations.\n//Thanks to the module Sequencer, you'll also be able to copy the path of the asset you want in a single click and replace it here to customize the macro.\n//Since we're working in macros, we'll prefer using the database path, especially for ranged attacks like this one.\n\n// For ranged attacks, we usually create a few different sizes so that Sequencer can choose the most appropriate one, depending on the distance between the source token and each target.\n\nlet selectedToken = canvas.tokens.controlled[0]; // First selected token\nlet targets = Array.from(game.user.targets); // Array of targeted tokens\n\nfor(let target of targets){\nnew Sequence()\n    .effect()\n        .file(\"jb2a.arrow.physical.white.01\") //Replace the text between quotation marks.\n        .atLocation(selectedToken)\n        .stretchTo(target)       \n    .play();\n}","folder":null,"sort":0,"flags":{"core":{"sourceId":"Macro.SCLqktdZTaBKsVFY"},"advanced-macros":{"runAsGM":false,"runForSpecificUser":""}},"_id":"9Uqq27aB4pwygo9H","ownership":{"BEL3Iav6K058rvXZ":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.2.1","coreVersion":"10.291","createdTime":null,"modifiedTime":1717069734681,"lastModifiedBy":"n1PqRj2wSLmNmxBt"}}
{"name":"Spike-Trap 10x05ft","type":"script","author":"u7AwIDe7bKx1FJ7L","img":"modules/JB2A_DnD5e/Library/Generic/Traps/Spike_Trap/Stills/SpikeTrapTopHolesDeployed01_Regular_Grey_05x05ft_400x400_StillFrame.webp","scope":"global","command":"/*##################################################################\n          INSTRUCTIONS\nThis macro requires these modules : \n- Sequencer\n- Tagger\n\nPlace down a Tile with only the holes using the following filepath : \n\"modules/JB2A_DnD5e/Library/Generic/Traps/Spike_Trap/Stills/SpikeTrapTopHolesHidden01_Dark_Black_10x05ft_600x400_StillFrame.webp\"\nThe full size of the trap is 600x400 pixels. Let's make it half its original size at 300x200.\nAlso, in the details of the tile at the bottom, we have to add the tag : \"SpikeTrap\" without the quotation marks in the field provided by the Tagger module.\n####################################################################*/\n\n// Let's pre-load the animations we'll need so that every client has the animations in cache and it doesn't mess the delays.\nawait Sequencer.Preloader.preloadForClients([\n  \"jb2a.spike_trap.10x05ft.top.holes.normal.01\", \n  \"jb2a.spike_trap.10x05ft.top.holes.still_frame.deployed\",\n  \"jb2a.spike_trap.10x05ft.top.holes.rearming.01\",\n])\nconst wait = (delay) => new Promise((resolve) => setTimeout(resolve, delay)) \nlet sourcePos = await Tagger.getByTag(\"SpikeTrap\"); // this will return an array of tiles which contain the tag \"SpikeTrap\"\nconst trapSize = { width: 300, height: 200 }; // Instead of repeating this for every Sequencer effect, I'm defining it at the top\nawait wait(100);\n\nasync function trapTrigger() {\nfor (const source of sourcePos) { // This will execute the Sequence for each tile of the array with the Tag\n   new Sequence()\n      .effect()\n        .file(\"jb2a.spike_trap.10x05ft.top.holes.normal.01\")\n        .atLocation(source)\n        .size(trapSize)\n        .belowTokens()\n        .fadeOut( 250,{ ease: \"linear\", delay: -2400 })\n        .waitUntilFinished(-2700)\n      .effect()\n        .file(\"jb2a.spike_trap.10x05ft.top.holes.still_frame.deployed\")\n        .atLocation(source)\n        .size(trapSize)\n        .belowTokens()\n        .persist() // Persist means we'll keep this still-frame displayed until we decide to switch to the re-arming Sequence\n        .name('SpikeTrap-Deployed')\n    .play();\n}\n}\n\nasync function trapRearm(){\n  for (const source of sourcePos) {\n    new Sequence()\n      .effect()\n        .file(\"jb2a.spike_trap.10x05ft.top.holes.rearming.01\")\n        .atLocation(source)\n        .size(trapSize)\n        .belowTokens()\n      .play()\n  }\n  await wait(600)\n  Sequencer.EffectManager.endEffects({name: 'SpikeTrap-Deployed'}) // This will remove the still-frame we persisted earlier\n}\n\n// At this point of the macro, we have defined what we want to happen when we execute the trapTrigger() function and when we execute the trapRearm() function.\n// We need a way for the macro to know which one to use depending on if the still-frame is displayed or not.\n\nconst effect = Sequencer.EffectManager.getEffects({name: 'SpikeTrap-Deployed'}); \n\nif(!effect.length){ // If the array of persisting effect is empty, let's trigger the trap, otherwise we re-arm it.\n  await trapTrigger()\n}\nelse{\n  await trapRearm()\n}","folder":null,"sort":0,"permission":{"default":0,"u7AwIDe7bKx1FJ7L":3},"flags":{"advanced-macros":{"runAsGM":false},"core":{"sourceId":"Macro.zoiy7LQR5FYDLj0f"}},"_id":"Lp6mlLMsD0yzufPG"}
{"name":"Bless","type":"script","author":"BEL3Iav6K058rvXZ","img":"modules/JB2A_DnD5e/Library/1st_Level/Bless/Bless_01_Regular_Yellow_Thumb.webp","scope":"global","command":"/*\n####################################################\n   This macro needs the Sequencer module to work.\n   Also, you need to target at least one token.\n####################################################\n*/\n//You can find its documentation here on Github : https://github.com/fantasycalendar/FoundryVTT-Sequencer/wiki\n\n//Bless has an intro for when the spell is cast and a looped version to make it last until it is dismissed either from the Sequencer Effect Manager, or by running this macro once more.\n\n//Let's make an array of all targetted tokens\nlet targets = Array.from(game.user.targets);\n\n//Now, for each target, we'll check if a sequencer effect with a specific name exists. \n//If it does, we'll end it, otherwise we'll start one.\nfor(let target of targets){\n    let blessEffects = Sequencer.EffectManager.getEffects({ name: `${target.name}-Bless_${target.id}` });\n\n    if(blessEffects.length){\n        await Sequencer.EffectManager.endEffects({ name: `${target.name}-Bless_${target.id}` })\n    }\n    else{\n    //Let's first define which tokens are targeted\n    \n    //For each target of the targets array, we'll play a sequence\n    \n        new Sequence()\n        .effect()\n        //Here's how we call on to an asset using our database registered with Sequencer.\n        //Without the database, it would look something like this : \n        //.file(\"modules/jb2a_patreon/Library/1st_Level/Bless/Bless_01_Regular_Yellow_Intro_400x400.webm\")\n        \n            .file(\"jb2a.bless.200px.intro.yellow\")\n            //Where do we want the animation to be played ? on the target we defined in the for loop.\n            .atLocation(target)\n            .belowTokens()\n            //We want the next asset, which will be the looped version, to start slightly before the end of the intro to make the transition smoother\n            .waitUntilFinished(-500) \n        //Now, let's call the looped version. Same principle as for the intro       \n        .effect()\n            .file(\"jb2a.bless.200px.loop.yellow\")\n            .atLocation(target)\n            .belowTokens()\n            .persist()\n            .name(`${target.name}-Bless_${target.id}`) \n            .waitUntilFinished(-500)        \n        //I seperated this last looped version to be able to add a Fadeout at the end of 1000ms or 1 second before the end of the animation.\n        .effect()\n            .file(\"jb2a.bless.200px.loop.yellow\")\n            .atLocation(target)\n            .belowTokens()\n            .fadeOut(1000)\n        .play()\n        \n    }\n}","folder":null,"sort":0,"flags":{"advanced-macros":{"runAsGM":false,"runForSpecificUser":""},"core":{"sourceId":"Macro.40JOS43fUORukZmw"}},"_id":"NhSjJ3IP13sAMxv7","ownership":{"BEL3Iav6K058rvXZ":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.2.1","coreVersion":"10.291","createdTime":null,"modifiedTime":1717069777509,"lastModifiedBy":"n1PqRj2wSLmNmxBt"}}
{"name":"Energy Field","type":"script","author":"BEL3Iav6K058rvXZ","img":"modules/JB2A_DnD5e/Library/Generic/Energy/EnergyFieldTop_02_Regular_Blue_Thumb.webp","scope":"global","command":"/*\n####################################################\n   This macro needs the Sequencer module to work.\n   Also, you need to select a token\n####################################################\n*/\n\nconst effectScale = 1.6; // The scale will be depending on the token size already. this serves as a multiplier if you want all of them smaller or larger.\nconst effectFade = 1000; // How long do you wish the fade in and fade out to be (in milliseconds)?\nlet effectColor = \"blue\"; // Different colors are available, you can check which ones in the Sequencer Database Manager.\n\n//In this loop, we'll apply the effect on the selected token, unless an effect with the same name already exists, in which case, we'll dismiss it.\nconst energyFieldEffects = Sequencer.EffectManager.getEffects({ object: token, name: \"EnergyFieldBlue\" }); \nif(energyFieldEffects.length){\n    await Sequencer.EffectManager.endEffects({ object: token, name: \"EnergyFieldBlue\" })\n}\nelse{\n    new Sequence() \n        .effect()\n            .attachTo(token)        \n            .file(`jb2a.energy_field.02.below.${effectColor}`)\n            .belowTokens()//by default, the effect would be played above the tokens, we want this one to be played underneath so we can place the overlay above it\n            .scaleToObject(effectScale)\n            .fadeIn(effectFade, {ease: \"easeOutCubic\"})\n            .fadeOut(effectFade, {ease: \"easeOutCubic\"})\n            .persist()\n            .name(\"EnergyFieldBlue\")\n        .effect()\n            .attachTo(token)\n            .file(`jb2a.energy_field.02.above.${effectColor}`)\n            .scaleToObject(effectScale)\n            .fadeIn(effectFade, {ease: \"easeOutCubic\"})\n            .fadeOut(effectFade, {ease: \"easeOutCubic\"})\n            .persist()\n            .name(\"EnergyFieldBlue\")\n            .play();\n}","folder":null,"sort":0,"flags":{"core":{"sourceId":"Macro.KiPOhDcj3o8N4emD"},"advanced-macros":{"runForSpecificUser":""}},"_id":"PUrID8s6oNTnXKtQ","ownership":{"BEL3Iav6K058rvXZ":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.2.1","coreVersion":"10.291","createdTime":null,"modifiedTime":1717069895135,"lastModifiedBy":"n1PqRj2wSLmNmxBt"}}
{"name":"Energy Strands","type":"script","author":"BEL3Iav6K058rvXZ","img":"modules/JB2A_DnD5e/Library/Generic/Marker/EnergyStrands_01_Regular_Blue_Thumb.webp","scope":"global","command":"/*\n####################################################\n   This macro needs the Sequencer module to work.\n   Also, you need to select a token\n####################################################\n*/\n\nconst effectScale = 1.6; // The scale will be depending on the token size already. this serves as a multiplier if you want all of them smaller or larger.\nconst effectFade = 1000; // How long do you wish the fade in and fade out to be (in milliseconds)?\nconst effectColor = \"blue\";\n// More colors available in the Patreon pack.\n\nconst energyStrandEffects = Sequencer.EffectManager.getEffects({ object: token, name: \"EnergyFieldBlue\" }); \nif(energyStrandEffects.length){\n    await Sequencer.EffectManager.endEffects({ object: token, name: \"EnergyFieldBlue\" })\n}\nelse{\n    new Sequence() \n        .effect()\n            .attachTo(token)        \n            .file(`jb2a.energy_strands.complete.${effectColor}.01`)\n            .belowTokens()//by default, the effect would be played above the tokens, we want this one to be played underneath so we can place the overlay above it\n            .scaleToObject(effectScale)\n            .fadeIn(effectFade, {ease: \"easeOutCubic\"})\n            .fadeOut(effectFade, {ease: \"easeOutCubic\"})\n            .persist()\n            .name(\"EnergyFieldBlue\")\n        .effect()\n            .attachTo(token)\n            .file(`jb2a.energy_strands.overlay.${effectColor}.01`)\n            .scaleToObject(effectScale)\n            .fadeIn(effectFade, {ease: \"easeOutCubic\"})\n            .fadeOut(effectFade, {ease: \"easeOutCubic\"})\n            .persist()\n            .name(\"EnergyFieldBlue\")\n            .play();\n}","folder":null,"sort":0,"flags":{"core":{"sourceId":"Macro.HkjvnmGTtESQyGBo"},"advanced-macros":{"runForSpecificUser":""}},"_id":"aemLITe41fKoUoSq","ownership":{"BEL3Iav6K058rvXZ":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.2.1","coreVersion":"10.291","createdTime":null,"modifiedTime":1717069989818,"lastModifiedBy":"n1PqRj2wSLmNmxBt"}}
{"name":"Bomb Throw","type":"script","author":"57wlqmR4nbpd6oQC","img":"modules/JB2A_DnD5e/Library/Generic/Weapon_Attacks/Ranged/ThrowBomb01_01_Regular_Black_Thumb.webp","scope":"global","command":"/*\n####################################################\n   This macro needs the Sequencer module to work.\n   Also, you need to target at least one token and select the one who will throw the bomb.\n####################################################\n*/\n\n// Let's create a function with arguments. That means that we can call this function later and define each argument (here they're called dbThrow, dbFracture and dbExplosion);\n// If you look at the end of the macro, we're using each arg to call a specific Database path. (i.e: await grenade('dbPath01', 'dbPath02', 'dbPath03'))\nasync function bombAnimation(dbThrow, dbFracture, dbExplosion, dbGroundImpact){\n    let source = token; // this is the first selected token\n    let targets = Array.from(game.user.targets); // This is an array that will contain all targeted tokens (we need at least one to know where to throw the potion or grenade)\n        for(let target of targets){ // The for loop will iterate for each target, if more than one token is targeted. Otherwise it will run it only once\n        new Sequence()\n        .effect() \n            .file(dbThrow)\n            .atLocation(source)\n            .stretchTo(target)\n            .waitUntilFinished(-150)\n        .effect()\n            .file(dbFracture)\n            .atLocation(target)\n            .scaleToObject(1.2) \n        .effect()\n            .file(dbExplosion)\n            .atLocation(target)\n        .effect()\n            .file(dbGroundImpact)\n            .atLocation(target)\n            .belowTokens()\n            .scaleToObject(2)\n            .scaleIn(0.1, 100, {ease: \"easeOutExpo\"})\n            .duration(5000)\n            .fadeOut(3250, {ease: \"easeInSine\"})    \n        .play();\n        \n        let delay = Sequencer.Helpers.random_int_between(600, 1000) // neat little helper from Sequencer giving us a whole number between two values\n        await Sequencer.Helpers.wait(delay) // another helper that allows us to delay the time between each loop (when we have more than one target)\n        \n        }\n    }\nawait bombAnimation('jb2a.throwable.throw.bomb.01.black','jb2a.explosion.shrapnel.bomb.01.black','jb2a.explosion.08.orange','jb2a.impact.ground_crack.orange');","folder":null,"sort":0,"flags":{"core":{"sourceId":"Macro.nvEzRX1QqW2iReIg"},"advanced-macros":{"runForSpecificUser":""}},"_id":"dVmaXjoQ31pAJqaJ","ownership":{"default":0,"57wlqmR4nbpd6oQC":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.2.1","coreVersion":"10.291","createdTime":null,"modifiedTime":1717069877914,"lastModifiedBy":"n1PqRj2wSLmNmxBt"}}
{"name":"Shield","type":"script","author":"BEL3Iav6K058rvXZ","img":"modules/JB2A_DnD5e/Library/1st_Level/Shield/Shield_01_Regular_Blue_Thumb.webp","scope":"global","command":"/*\n####################################################\n   This macro needs the Sequencer module to work.\n   Also, you need to select a token\n####################################################\n*/\n// You can find its documentation on Github : https://github.com/fantasycalendar/FoundryVTT-Sequencer/wiki\n\n// Since we've made a \"complete\" animation of Shield, you don't need to combine intro-loop^-outro anymore. \n// The Sequencer module will know, if you add .persist(), that you want the intro transitionning to the loop and stay on the looped animation until dismissed, which will then make the transition to the ourtro part of the animation.\n\nconst shieldEffects = Sequencer.EffectManager.getEffects({ object: token, name: \"Shield\" }); \nif(shieldEffects.length){\n    await Sequencer.EffectManager.endEffects({ object: token, name: \"Shield\" })\n}\nelse{\n\n    new Sequence()\n        .effect()\n            .file(\"jb2a.shield.01.complete.01.blue\")\n            .scaleToObject(1.5)\n            .attachTo(token)\n            .persist()\n            .name(\"Shield\")\n        .play()\n}","folder":null,"sort":0,"flags":{"core":{"sourceId":"Macro.R7tnPORKQZaZVVAQ"},"advanced-macros":{"runAsGM":false,"runForSpecificUser":""}},"_id":"gcMRfTnslkDCFHCh","ownership":{"BEL3Iav6K058rvXZ":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.2.1","coreVersion":"10.291","createdTime":null,"modifiedTime":1717070380543,"lastModifiedBy":"n1PqRj2wSLmNmxBt"}}
{"name":"MoltenEarth Orange Shield","type":"script","author":"BEL3Iav6K058rvXZ","img":"modules/JB2A_DnD5e/Library/Generic/Fire/ShieldMoltenEarthAbove01_01_Regular_Orange_Thumb.webp","scope":"global","command":"/*\n####################################################\n   This macro needs the Sequencer module to work.\n   Also, you need to select a token\n####################################################\n*/\n//It is intended for animated assets like ShieldEldritchWeb | ShieldIce | ShieldFire | ShieldMoltenEarth\n\nconst effectScale = 1.6; // The scale will be depending on the token size already. this serves as a multiplier if you want all of them smaller or larger.\nconst effectFade = 1000; // How long do you wish the fade in and fade out to be (in milliseconds)?\nconst effectColor = \"orange\";\n\nconst energyStrandEffects = Sequencer.EffectManager.getEffects({ object: token, name: \"MoltenEarth Shield\" }); \nif(energyStrandEffects.length){\n    await Sequencer.EffectManager.endEffects({ object: token, name: \"MoltenEarth Shield\" })\n}\nelse{\n    new Sequence() \n        .effect()\n            .attachTo(token)        \n            .file(`jb2a.shield_themed.below.molten_earth.01.${effectColor}`)\n            .belowTokens()//by default, the effect would be played above the tokens, we want this one to be played underneath so we can place the overlay above it\n            .scaleToObject(effectScale)\n            .fadeIn(effectFade, {ease: \"easeOutCubic\"})\n            .fadeOut(effectFade, {ease: \"easeOutCubic\"})\n            .persist()\n            .name(\"MoltenEarth Shield\")\n        .effect()\n            .attachTo(token)\n            .file(`jb2a.shield_themed.above.molten_earth.01.${effectColor}`)\n            .scaleToObject(effectScale)\n            .fadeIn(effectFade, {ease: \"easeOutCubic\"})\n            .fadeOut(effectFade, {ease: \"easeOutCubic\"})\n            .persist()\n            .name(\"MoltenEarth Shield\")\n            .play();\n}","folder":null,"sort":0,"flags":{"core":{"sourceId":"Macro.KiPOhDcj3o8N4emD"},"advanced-macros":{"runForSpecificUser":""}},"_id":"kpWYzI3ckcFxmALA","ownership":{"BEL3Iav6K058rvXZ":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.2.1","coreVersion":"10.291","createdTime":null,"modifiedTime":1717070367377,"lastModifiedBy":"n1PqRj2wSLmNmxBt"}}
{"name":"Melee_Attack_Advanced_A-A_v8","type":"script","scope":"global","author":"n1PqRj2wSLmNmxBt","img":"modules/JB2A_DnD5e/Library/Generic/Weapon_Attacks/Melee/Group04/MeleeAttack04_Katana01_Thumb.webp","command":"//Macro created by Gazkhan - Jules\n//Modified by Sisimshow\n\n/*********************\n * STORING VARIABLES \n *********************/\n\n// This represents how many pixels are in one grid square.\nconst gridSize = canvas.grid.size;\n\n// Here, we're picking up on the information Automated Animation is feeding and storing what we need in their respective variables.\nlet source = args[1]?.sourceToken ?? token;\nlet targets = args[1]?.allTargets ?? game.user.targets;\n\n// just in case the user hasn't targetted a token, let's add a quick warning\nif (!targets || targets?.length === 0) {\n    return ui.notifications.warn(\"Please target at least one token\")\n}\n\n// Everything in args[2] represents the information we manually add to the auto-recognition entry, via the \"Send In Args\" field.\n// We also make sure there's a fallback by default so it doesn't just error out.\nconst enableTrail = args[2]?.enableTrail ?? false;\nconst enableImpact = args[2]?.enableImpact ?? false;\nconst enableSound = args[2]?.enableSound ?? false;\nconst enableSwitchDistance = args[2]?.enableSwitchDistance ?? false;\nconst enableReturn = args[2]?.enableReturn ?? false;\nconst enableBlood = args[2]?.enableBlood ?? false;\nconst enableShake = args[2]?.enableShake ?? false;\nconst debug = args[2]?.debug ?? false;\n\nconst weaponGroup = args[2]?.weaponGroup ?? \"melee_attack.01\";\nconst weapon = args[2]?.weapon ?? \"butterflysword.01\";\nconst trail = args[2]?.trail ?? \"\";\nconst color = args[2]?.color ?? \"blue\";\nconst impact = args[2]?.impact ?? \"\";\nconst impactScale = args[2].impactScale ?? 1.5;\nconst soundFileMelee = args[2]?.soundFileMelee ?? \"\";\nconst soundFileRange = args[2]?.soundFileRange ?? \"\";\nconst delaySound = args[2]?.delaySound ?? 300;\nconst switchDistanceFt = args[2]?.switchDistanceFt ?? 5;\nconst range = args[2]?.range ?? \"\";\nconst returnFile = args[2]?.return ?? \"\";\nconst delayBetweenAttacks = args[2]?.delayBetweenAttacks ?? 1000;\n\nfunction log(string, variable){\n    return console.log(`%c ${string}`, 'color: #bada55', variable)\n}\n\n\n\n// Let's reconstruct the database path and fetch the array of all the variations for the chosen weapon\nconst dbPath = `jb2a.${weaponGroup}.${weapon}`;\nconst entries = Sequencer.Database.getEntry(dbPath) ?? null;\n\n// The length of the array will represent how many entries there are, \n// which we'll use later on to randomly pick the appropriate one.\nconst entriesLength = entries.length;\n\nif(debug){\n\n\n\n    log(\"source: \", source);\n    log(\"targets: \", targets);\n    log(\"weapon group: \", weaponGroup);\n    log(\"weapon: \", weapon);\n    log(\"trail: \", trail);\n    log(\"color: \", color);\n    log(\"impact: \", impact);\n    log(\"soundFileMelee: \", soundFileMelee);\n    log(\"soundFileRange: \", soundFileRange);\n    log(\"enableBlood: \", enableBlood);\n    log(\"enableSound: \", enableSound);\n    log(\"enableShake: \", enableShake);\n    log(\"enableTrail: \", enableTrail);\n    log(\"dbPath: \", dbPath);\n    log(\"entries: \", entries);\n    log(\"entries length: \", entriesLength);\n\n}\n\n\n/******************************************\n * MAIN ANIMATION FUNCTIONS INITIALIZATION*\n * ****************************************/\n\nasync function meleeAttack(target, randMelee, randTrail, impact, isMirrored, targetScale, within5ft) {\n    const sourceScale = { x: source?.document?.texture?.scaleX ?? 1, y: source?.document?.texture?.scaleY ?? 1 }\n    \n    // Here is some Maths that we use for the \"Shake\" animation of the targets, move along... nothing to see here :D\n    const amplitude = Sequencer.Helpers.random_float_between(0.0, 0.2);\n    let hitRay = new Ray(source, target);\n    const shakeDirection = { x: Math.sign(hitRay.dx), y: Math.sign(hitRay.dy) };\n    const values = {\n        x: [0, -amplitude * shakeDirection.y, amplitude * shakeDirection.y, (-amplitude * shakeDirection.y) / 4, (amplitude * shakeDirection.y) / 4, 0],\n        y: [0, amplitude * shakeDirection.x, -amplitude * shakeDirection.x, (amplitude * shakeDirection.x) / 4, (-amplitude * shakeDirection.x) / 4, 0]\n    }\n    const interval = 50;\n    const easeOption = \"easeInOutSine\";\n\n    if(debug){\n        log(\"THIS IS A: \", \"MELEE ATTACK\")\n        log(\"within 5 feet?: \", within5ft)\n        log(\"randow melee: \", randMelee)\n        log(\"random trail: \", randTrail)\n        log(\"target scale: \", targetScale)\n        log(\"source scale: \", sourceScale)\n    }\n\n    // Below is the Sequencer code for all the animations\n    // The wiki for Sequencer is the best resource to learn about it: \n    // https://fantasycomputer.works/FoundryVTT-Sequencer/#/\n    // check it out, follow the tutorials from Wasp, the developer, everything is there!\n    new Sequence()\n\n        .effect()\n        .from(source)\n        .scale({ x: sourceScale.x, y: sourceScale.y })\n        .anchor(0.5)\n        .duration(1500)\n        .zIndex(5)\n        .playIf(within5ft)\n\n        .effect()\n        .from(source)\n        .scale({ x: sourceScale.x, y: sourceScale.y })\n        .anchor(0.5)\n        .duration(1500)\n        .zIndex(5)\n        .playIf(!within5ft)\n\n        .animation()\n        .on(source)\n\n        .effect()\n        .file(`${randTrail}`)\n        .atLocation(target)\n        .rotateTowards(source)\n        .rotate(180)\n        .animateProperty(\"sprite\", \"position.x\", { from: -(2.5*gridSize + hitRay.distance), to: -2.5*gridSize, duration: 500+hitRay.distance, ease: \"easeOutQuint\"})\n        .scale(0.5)\n        .mirrorY(isMirrored)\n        .zIndex(11)\n        .playIf(enableTrail)\n\n        .effect()\n        .file(`${randMelee}`)\n        .atLocation(target)\n        .rotateTowards(source)\n        .rotate(180)\n        .animateProperty(\"sprite\", \"position.x\", { from: -(2.5*gridSize + hitRay.distance), to: -2.5*gridSize, duration: 500+hitRay.distance, ease: \"easeOutQuint\"})\n        .scale(0.5)\n        .mirrorY(isMirrored)\n        .zIndex(10)\n        .waitUntilFinished(-1000) // By design, The hit should always be 1 second from the end of the weapon attack and the trail animations\n\n\n\n        .animation()\n        .on(source)\n\n        .sound()\n        .file(soundFileMelee)\n        .playIf(enableSound)\n\n        .effect()\n        .file(`${impact}`)\n        .atLocation(target)\n        .scaleToObject(impactScale, { uniform: true })\n        .zIndex(12)\n        .playIf(enableImpact)\n\n        //START - BLOOD SPLATTER EFFECT\n        .effect()\n        .file('jb2a.liquid.splash_side.red')\n        .atLocation(target)\n        .rotateTowards(source)\n        .randomRotation()\n        .scaleToObject(1.5, { uniform: true })\n        .playIf(enableBlood)\n        .zIndex(12)\n        //END - BLOOD SPLATTER EFFECT\n\n        // START OF SHAKE SECTION\n        .animation()\n        .on(target)\n        .fadeOut(50)\n        .playIf(enableShake)\n\n        .effect()\n        .from(target)\n        .loopProperty(\"spriteContainer\", \"position.x\", {\n            values: values.x,\n            duration: interval - ((interval * amplitude) / 2),\n            gridUnits: true,\n            ease: easeOption\n        })\n        .loopProperty(\"spriteContainer\", \"position.y\", {\n            values: values.y,\n            duration: interval - ((interval * amplitude) / 2),\n            gridUnits: true,\n            ease: easeOption\n        })\n        .scale({ x: targetScale.x, y: targetScale.y })\n        .duration(interval * 9)\n        .playIf(enableShake)\n        .zIndex(1)\n        .waitUntilFinished(-150)\n\n        .animation()\n        .on(target)\n        .fadeIn(50)\n        .playIf(enableShake)\n        // END OF SHAKE SECTION\n\n        .play();\n};\n\nasync function rangedAttack(target, targetScale) {\n    if(debug){\n        log(\"THIS IS A: \", \"RANGED ATTACK\")\n        log(\"target scale: \", targetScale)\n    }\n\n    const amplitude = Sequencer.Helpers.random_float_between(0.0, 0.2);\n    let hitRay = new Ray(source, target);\n    const shakeDirection = { x: Math.sign(hitRay.dx), y: Math.sign(hitRay.dy) };\n    const values = {\n        x: [0, -amplitude * shakeDirection.y, amplitude * shakeDirection.y, (-amplitude * shakeDirection.y) / 4, (amplitude * shakeDirection.y) / 4, 0],\n        y: [0, amplitude * shakeDirection.x, -amplitude * shakeDirection.x, (amplitude * shakeDirection.x) / 4, (-amplitude * shakeDirection.x) / 4, 0]\n    }\n    const interval = 50;\n    const easeOption = \"easeInOutSine\";\n\n    new Sequence()\n\n        .sound()\n        .file(soundFileRange)\n        .playIf(enableSound)\n        .delay(delaySound)\n\n        .effect()\n        .file(range)\n        .atLocation(source)\n        .stretchTo(target)\n        .waitUntilFinished(-800)\n        .zIndex(10)\n\n        .effect()\n        .file(`${impact}`)\n        .atLocation(target)\n        .scaleToObject(1.2, { uniform: true })\n        .zIndex(12)\n        .playIf(enableImpact)\n\n        .effect()\n        .file(returnFile)\n        .atLocation(source)\n        .stretchTo(target)\n        .zIndex(10)\n        .playIf(enableReturn)\n\n        //START - BLOOD SPLATTER EFFECT\n        .effect()\n        .file('jb2a.liquid.splash_side.red')\n        .atLocation(target)\n        .rotateTowards(source)\n        .randomRotation()\n        .scaleToObject(1.5, { uniform: true })\n        .zIndex(11)\n        .playIf(enableBlood)\n        //END - BLOOD SPLATTER EFFECT\n\n        // START OF SHAKE SECTION\n        .animation()\n        .on(target)\n        .fadeOut(50)\n        .playIf(enableShake)\n\n        .effect()\n        .from(target)\n        .loopProperty(\"spriteContainer\", \"position.x\", {\n            values: values.x,\n            duration: interval - ((interval * amplitude) / 2),\n            gridUnits: true,\n            ease: easeOption\n        })\n        .loopProperty(\"spriteContainer\", \"position.y\", {\n            values: values.y,\n            duration: interval - ((interval * amplitude) / 2),\n            gridUnits: true,\n            ease: easeOption\n        })\n        .scale({ x: targetScale.x, y: targetScale.y })\n        .duration(interval * 9)\n        .playIf(enableShake)\n        .zIndex(1)\n        .waitUntilFinished(-150)\n\n        .animation()\n        .on(target)\n        .fadeIn(50)\n        .playIf(enableShake)\n        // END OF SHAKE SECTION\n\n        .play()\n}\n\n/**************************\n * ANIMATION CALL AND LOOP*\n **************************/\n\n// We will loop through this code for each targeted token and \n// pick a different random number each loop in order to have more\n// probability to pick a different animation everytime\nfor (let target of targets) {\n\n\n    let targetScale = { x: target?.document?.texture?.scaleX ?? 1, y: target?.document?.texture?.scaleY ?? 1 }\n    // Arrays start at 0. This will return a random integer which we'll use to pick a random attack variation\n    // and its corresponding trail.\n    let rand = Math.floor(Math.random() * ((entriesLength -1) + 1))\n    // Here, we rebuild the database paths and pass them along to the animation function.\n    let randMelee = `${dbPath}.${rand}`;\n    let randTrail;\n    enableTrail? randTrail =`jb2a.${weaponGroup}.${trail}.${color}.${rand}` : randTrail = 'jb2a.antilife_shell.blue_no_circle'\n    \n    // Let's add to the randomisation by mirroring the animation half the time, on top of the random attack variation.\n    let isMirrored = Math.random() < 0.5; // 50% probability. 0.1 would make it 10%, 0.2 20%...etc\n\n    const targetBounds = target.bounds.pad(gridSize * (switchDistanceFt / 5 - 1 + 0.5), gridSize * (switchDistanceFt / 5 - 1 + 0.5));\n    const sourceBounds = source.bounds;\n    const within5ft = (target.bounds.pad(gridSize * (0.5), gridSize * (0.5))).intersects(sourceBounds);\n    const withinSwitchDistance = targetBounds.intersects(sourceBounds);\n\n    // This is the code which actually calls the animation function.\n    if (withinSwitchDistance || !enableSwitchDistance) {\n        await meleeAttack(target, randMelee, randTrail, impact, isMirrored, targetScale, within5ft)\n        await Sequencer.Helpers.wait(delayBetweenAttacks)\n    }\n    else {\n        await rangedAttack(target, targetScale)\n        await Sequencer.Helpers.wait(delayBetweenAttacks)\n    }\n\n    if(debug){\n        log(\"random integer: \", rand)\n        log(\"randow melee: \", randMelee)\n        log(\"random trail: \", randTrail)\n        log(\"target scale: \", targetScale)\n        log(\"switch Distance\", switchDistanceFt)\n        log(\"within switch distance: \", withinSwitchDistance)\n    }\n}","flags":{"advanced-macros":{"runAsGM":false,"runForSpecificUser":""},"core":{"sourceId":"Macro.Cs0UbR2yVheE2F9h"}},"_stats":{"systemId":"dnd5e","systemVersion":"2.2.1","coreVersion":"10.291","createdTime":1674733916603,"modifiedTime":1717070479380,"lastModifiedBy":"n1PqRj2wSLmNmxBt"},"ownership":{"default":0,"n1PqRj2wSLmNmxBt":3},"folder":null,"sort":0,"_id":"mcmSlAuvRLbI7TUa"}
{"name":"Weapon Throw with Return","type":"script","author":"BEL3Iav6K058rvXZ","img":"modules/JB2A_DnD5e/Library/Generic/Weapon_Attacks/Ranged/Dagger01_01_Regular_White_Return_Thumb.webp","scope":"global","command":"/*\n#########################################################################################\n   This macro needs the Sequencer module to work.\n   Also, you need to target at least one token and select the token throwing the weapon\n#########################################################################################\n*/\n//You can find the documentation for Sequencer on Github : https://github.com/fantasycalendar/FoundryVTT-Sequencer/wiki\n\nlet targets = Array.from(game.user.targets);\n\nfor(let target of targets){\n    new Sequence()\n        .effect()\n    //First it will play the throw sequence of the Dagger01 animation.\n            .file(\"jb2a.dagger.throw.01.white\")\n            .atLocation(token)\n            .stretchTo(target)\n            //OPTIONAL\n            //You can adjust the value below to play the return part before or after the throwing animation ends.\n            //The current value should make the transition seamless or barely noticeable.\n            //A negative value will play the return part before the throwing animation ends. And a positive value will add a pause between the throw and the return animation. \n            .waitUntilFinished(-700) //In milliseconds  \n        .effect()\n    //Then it will transition to the return animation of the Dagger01.\n            .file(\"jb2a.dagger.return.01.white\")\n            .atLocation(token)\n            .stretchTo(target)\n    .play()\n}","folder":null,"sort":0,"flags":{"core":{"sourceId":"Macro.kSfIaywHwfY3sKXI"},"advanced-macros":{"runForSpecificUser":""}},"_id":"v24ACH5xsHghmsJD","ownership":{"BEL3Iav6K058rvXZ":3},"_stats":{"systemId":"dnd5e","systemVersion":"2.2.1","coreVersion":"10.291","createdTime":null,"modifiedTime":1717070451461,"lastModifiedBy":"n1PqRj2wSLmNmxBt"}}
