From c1107f7c8d7904cab2c1925fa42cb389c1d8dd93 Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sun, 15 May 2022 22:01:46 -0500 Subject: [PATCH] add growth/shrink --- .../warpgate_spells/growth-shrink-warpgate.js | 160 ++++++++++++++++++ ...sloth-speed.js => sloth-speed-warpgate.js} | 0 packs/macros.db | 17 ++ 3 files changed, 177 insertions(+) create mode 100644 macros/warpgate_spells/growth-shrink-warpgate.js rename macros/warpgate_spells/{sloth-speed.js => sloth-speed-warpgate.js} (100%) diff --git a/macros/warpgate_spells/growth-shrink-warpgate.js b/macros/warpgate_spells/growth-shrink-warpgate.js new file mode 100644 index 0000000..e473949 --- /dev/null +++ b/macros/warpgate_spells/growth-shrink-warpgate.js @@ -0,0 +1,160 @@ +const GROWTHICON = 'icons/magic/control/silhouette-grow-shrink-blue.webp' +const SHRINKICON = 'icons/magic/control/silhouette-grow-shrink-tan.webp' + +let tokens = []; +let targets = Array.from(game.user.targets); +if (targets.length > 0) { + tokens = targets; +} else if (canvas.tokens.controlled.length > 0) { + tokens = canvas.tokens.controlled; +} +if (tokens.length > 0) { + main(tokens); +} else { + ui.notifications.error("Please select or target a token"); +} + +async function main(tokens) { + let tokenList = tokens.map(t => t.name).join(", "); + let menuOptions = { + title: 'Growth/Shrink', + defaultButton: "Cancel", + options: {} + }; + let menuData = { + inputs: [ + { type: 'header', label: 'Growth/Shrink' }, + { type: 'info', label: `Affected Tokens: ${tokenList}` }, + { type: 'number', label: 'Number of steps (2pp ea)' }, + { type: 'info', label: "Grow or Shrink" }, + { type: 'radio', label: 'Growth', options: ['isspeed', true] }, + { type: 'radio', label: 'Shrink', options: ['isspeed', false] }, + ], + buttons: [ + { label: "Apply", value: "apply" }, + { label: "Cancel", value: "cancel" } + ] + } + let { buttons, inputs } = await warpgate.menu(menuData, menuOptions); + if (buttons && buttons != "cancel") { + let direction = inputs[4] || inputs[5]; + let steps = inputs[2]; + createEffect(tokens, steps, direction, buttons); + } +} + +async function createEffect(tokens, steps, direction, buttons) { + const effectName = direction + const effectId = direction + const effectIcon = (direction == "Growth" ? GROWTHICON : SHRINKICON) + for (const token of tokens) { + let tokenDoc = token.document; + let mode = foundry.CONST.ACTIVE_EFFECT_MODES.ADD; + let effectData = { + icon: effectIcon, + id: effectId, + label: effectName, + duration: {rounds: 5}, + flags: { + swade: { + expiration: 3, + loseTurnOnHold: true + } + }, + changes: [] + }; + let strDie = token.actor.data.data.attributes.strength.die.sides; + let size = token.actor.data.data.stats.size; + let strDieChange = 0; + let strModChange = 0; + let sizeChange = 0; + if (direction == "Growth") { + strDieChange = 2 * steps; + sizeChange = steps; + while (strDie + strDieChange > 12) { + strDieChange -= 2; + strModChange += 1; + } + } else { + let stepCount = steps; + while (size + sizeChange > -2 && stepCount > 0) { + stepCount -= 1; + strDieChange -= 2; + sizeChange -= 1; + } + if (strDie + strDieChange < 4) { + strDieChange = (4 - strDie); + } + } + effectData.changes.push( + { + key: 'data.stats.size', + mode: mode, + value: sizeChange + } + ) + effectData.changes.push( + { + key: 'data.attributes.strength.die.sides', + mode: mode, + value: strDieChange, + } + ) + effectData.changes.push( + { + key: 'data.attributes.strength.die.modifier', + mode: mode, + value: strModChange + } + ) + size += sizeChange; + let scale = 0; + let height = 1; + let width = 1; + switch (size) { + case -2: scale = 0.6; break; + case -1: scale = 0.8; break + case 0: break; + case 1: scale = 1.2; break; + case 2: scale = 1.5; break; + case 3: scale = 2; break; + case 4: height = 2; width = 2; scale = 1; break; + case 5: height = 2; width = 2; scale = 1.2; break; + case 6: height = 2; width = 2; scale = 1.5; break; + case 7: height = 2; width = 2; scale = 1.5; break; + case 8: height = 3; width = 3; scale = 1; break; + case 9: height = 3; width = 3; scale = 1.2; break; + case 10: height = 3; width = 3; scale = 1.4; break; + case 11: height = 3; width = 3; scale = 1.6; break; + } + if (size < -2) { + scale = 0.5; + } else if (size > 11) { + scale = 1 + height = 4 + width = 4 + } + let tempMutate = { + token: { + scale: scale, + height: height, + width: width + } + } + let mutate = { + embedded: { + ActiveEffect: { + } + } + }; + mutate.embedded.ActiveEffect[effectName] = effectData; + let mutateOptions = { + comparisonKeys: { 'ActiveEffect': 'label' }, + name: effectName, + description: effectName, + } + await warpgate.mutate(token.document, tempMutate, {}, mutateOptions); + mutateOptions.permanent = true; + await warpgate.mutate(token.document, mutate, {}, mutateOptions); + } +} \ No newline at end of file diff --git a/macros/warpgate_spells/sloth-speed.js b/macros/warpgate_spells/sloth-speed-warpgate.js similarity index 100% rename from macros/warpgate_spells/sloth-speed.js rename to macros/warpgate_spells/sloth-speed-warpgate.js diff --git a/packs/macros.db b/packs/macros.db index 7e3c22b..3b57364 100644 --- a/packs/macros.db +++ b/packs/macros.db @@ -36,3 +36,20 @@ {"_id":"wa7ZoYUhNcjrNEmN","name":"#[CF_tempEntity]","type":"chat","author":"HXnQ3GTDyHZ7E1ev","img":"icons/svg/dice-target.svg","scope":"global","command":"","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000","name":"SWADE Spell Effects (WarpGate)","children":["ye1BuJD7kKGAyReU","fzkUWlTKCJ68nEzL","uB67GR2V90kmvyVs","p94dkSmOgfuoC28K",null,"c8lz4DUmw6afCYRC","9KVvOhKLlyZHrQ76","79YiKPX3WcmBeMzm","4SRoZduQrF2o3MZK","VzTYSKRXvpOTquUO","ZMWoKCwGTBTufQaF","U6ysKunxzRsvhnR6","yV3XNCfgHpGrREt0","tjaqN9gedJpYFgbu"],"folderPath":[]},"scene-packer":{"hash":"3d9a8396d815dcef72c41f01fa0318a9a20c0bb4"}}} {"_id":"yV3XNCfgHpGrREt0","name":"Sanctuary","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"icons/magic/defensive/shield-barrier-flaming-diamond-blue-yellow.webp","scope":"global","command":"const powerEffectApply = game.macros.getName(\"Power Effect\");\n\nreturn await powerEffectApply.execute(\"Sanctuary\");","folder":null,"sort":0,"permission":{"default":0,"ygiRButlaf23fX9p":3},"flags":{"advanced-macros":{"runAsGM":false},"combat-utility-belt":{"macroTrigger":""},"core":{"sourceId":"Macro.01dTmSPBq0xJQJcm"},"scene-packer":{"sourceId":"Macro.fzA6qQ1PyNgV8FqE","hash":"a45f562cc1f65a09386c3a6f9006b1fad3650f78"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"}}} {"_id":"ye1BuJD7kKGAyReU","name":"Arcane Protection","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"icons/magic/defensive/shield-barrier-deflect-gold.webp","scope":"global","command":"const powerEffectApply = game.macros.getName(\"Power Effect\");\n\nreturn await powerEffectApply.execute(\"Arcane Protection\");","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"advanced-macros":{"runAsGM":false},"combat-utility-belt":{"macroTrigger":""},"core":{"sourceId":"Macro.01dTmSPBq0xJQJcm"},"scene-packer":{"sourceId":"Macro.ye1BuJD7kKGAyReU","hash":"0d06d7cc1e1d6d1b9767648e0519e61253496a1c"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"}}} +{"_id":"ye1BuJD7kKGAyReU","name":"Arcane Protection","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"icons/magic/defensive/shield-barrier-deflect-gold.webp","scope":"global","command":"const powerEffectApply = game.macros.getName(\"Power Effect\");\n\nreturn await powerEffectApply.execute(\"Arcane Protection\");","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"advanced-macros":{"runAsGM":false},"combat-utility-belt":{"macroTrigger":""},"core":{"sourceId":"Macro.01dTmSPBq0xJQJcm"},"scene-packer":{"sourceId":"Macro.ye1BuJD7kKGAyReU","hash":"0d06d7cc1e1d6d1b9767648e0519e61253496a1c"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"}}} +{"_id":"fzkUWlTKCJ68nEzL","name":"Boost/Lower Trait","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"icons/magic/movement/chevrons-down-yellow.webp","scope":"global","command":"const UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp'\nconst DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp'\n\nlet tokens = [];\nlet targets = Array.from(game.user.targets);\nif (targets.length > 0) {\n tokens = targets;\n} else if (canvas.tokens.controlled.length > 0) {\n tokens = canvas.tokens.controlled;\n}\nif (tokens.length > 0) {\n main(tokens);\n} else {\n ui.notifications.error(\"Please select or target a token\");\n}\n\nasync function main(tokens) {\n let traitOptions = [\n \"Agility\",\n \"Smarts\",\n \"Spirit\",\n \"Strength\",\n \"Vigor\"\n ];\n let allSkills = [];\n let traits = {\n \"Agility\": {\n type: \"attribute\",\n name: \"Agility\",\n modkey: \"data.attributes.agility.die.modifier\",\n diekey: \"data.attributes.agility.die.sides\"\n },\n \"Smarts\": {\n type: \"attribute\",\n name: \"Smarts\",\n modkey: \"data.attributes.smarts.die.modifier\",\n diekey: \"data.attributes.smarts.die.sides\"\n },\n \"Spirit\": {\n type: \"attribute\",\n name: \"Spirit\",\n modkey: \"data.attributes.spirit.die.modifier\",\n diekey: \"data.attributes.spirit.die.sides\"\n },\n \"Strength\": {\n type: \"attribute\",\n name: \"Strength\",\n modkey: \"data.attributes.strength.die.modifier\",\n diekey: \"data.attributes.strength.die.sides\"\n },\n \"Vigor\": {\n type: \"attribute\",\n name: \"Vigor\",\n modkey: \"data.attributes.vigor.die.modifier\",\n diekey: \"data.attributes.vigor.die.sides\"\n }\n };\n let tokenList = tokens.map(t => t.name).join(\", \");\n for (const token of tokens) {\n let skills = token.actor.items.filter(e => e.type == \"skill\");\n for (const skill of skills) {\n let name = skill.data.name\n traits[name] = {\n type: \"skill\",\n name: name,\n modkey: `@Skill{${name}}[data.die.modifier]`,\n diekey: `@Skill{${name}}[data.die.sides]`\n };\n if (name != 'Unskilled' && !allSkills.find(v => v == name)) {\n allSkills.push(name);\n }\n }\n }\n traitOptions = traitOptions.concat(allSkills.sort());\n let menuOptions = {\n title: 'Boost/Lower Trait',\n defaultButton: \"Cancel\",\n options: {}\n };\n let menuData = {\n inputs: [\n {type: 'header', label: 'Boost/Lower Trait'},\n {type: 'info', label: `Affected Tokens: ${tokenList}`}, \n {type: 'select', label: 'Trait', options: traitOptions},\n {type: 'info', label: \"Boost or Lower?\"},\n {type: 'radio', label: 'Boost', options: ['boostlower', true]},\n {type: 'radio', label: 'Lower', options: ['boostlower', false]},\n ],\n buttons: [\n {label: \"Apply\", value: \"apply\"},\n {label: \"Apply with raise\", value: \"raise\"},\n {label: \"Cancel\", value: \"cancel\"}\n ]\n }\n let {buttons, inputs} = await warpgate.menu(menuData, menuOptions);\n if (buttons != \"cancel\") {\n let trait = inputs[2];\n let direction = inputs[4] || inputs[5];\n createEffect(tokens, traits[trait], direction, buttons);\n }\n}\n\nfunction getDottedPart(obj, key) {\n let value = obj;\n for (const part of key.split(\".\")) {\n value = value[part];\n }\n return value;\n}\n\nasync function createEffect(tokens, trait, direction, buttons) {\n const raise = (buttons == 'raise');\n const effectName = `${raise ? \"Major\" : \"Minor\"} ${direction} ${trait.name}`;\n const effectId = `${raise ? \"Major\" : \"Minor\"}${direction}${trait.name}`;\n const effectIcon = (direction == 'Boost' ? UPICON : DOWNICON)\n for (const token of tokens) {\n let tokenDoc = token.document;\n let currentDie = 0;\n let currentMod = 0;\n if (trait.type == 'attribute') {\n currentDie = getDottedPart(token.actor.data, trait.diekey);\n currentMod = getDottedPart(token.actor.data, trait.modkey);\n } else {\n let skill = token.actor.items.filter(s => s.type == 'skill').find(\n s => s.data.name == trait.name)\n if (skill) {\n currentDie = skill.data.data.die.sides;\n currentMod = skill.data.data.die.modifier;\n } else {\n currentDie = 4;\n currentMod = -2;\n }\n }\n if (currentDie == 0) {\n continue;\n }\n if (currentDie == 4 && direction == \"Lower\") {\n continue;\n }\n let diemod = 2;\n let modmod = 0;\n if (direction == \"Lower\") {\n diemod = -2;\n }\n if (currentDie == 6 && direction == \"Lower\" && raise) {\n diemod = -1\n } else if (currentDie == 12 && direction == \"Boost\") {\n diemod = 0;\n modmod = 1;\n }\n if (raise) {\n diemod *= 2;\n modmod *= 2;\n }\n if (currentDie == 10 && direction == \"Boost\" && raise) {\n diemod = 2;\n modmod = 1;\n }\n if (currentDie == 4 && currentMod == -2 && direction == \"Boost\") {\n diemod = (raise ? 2 : 0);\n modmod = 2;\n }\n let effectData = {\n icon: effectIcon,\n id: effectId,\n label: effectName,\n flags: {\n swade: {\n expiration: 3,\n loseTurnOnHold: true\n }\n },\n changes: []\n };\n let mode = foundry.CONST.ACTIVE_EFFECT_MODES.ADD;\n if (diemod != 0) {\n effectData.changes.push({ key: trait.diekey, mode: mode, value: diemod, priority: 0 });\n }\n if (modmod != 0) {\n effectData.changes.push({ key: trait.modkey, mode: mode, value: modmod, priority: 0 });\n }\n if (direction == \"Boost\") {\n effectData.duration = { rounds: 5 };\n }\n let mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n };\n mutate.embedded.ActiveEffect[effectName] = effectData;\n let mutateOptions = {\n comparisonKeys: { 'ActiveEffect': 'label' },\n name: effectName,\n permanent: false,\n description: effectName,\n }\n if (trait.type == 'skill' && direction == 'Boost' && !token.actor.items.getName(trait.name)) {\n let itemmutate = { embedded: { Item: {} } }\n itemmutate.embedded.Item[trait.name] = {\n \"name\": trait.name,\n \"type\": \"skill\",\n \"img\": \"systems/swade/assets/icons/skills/uncertainty.svg\",\n \"data\": {\n \"description\": \"See SWADE. Auto added as untrained for Boost Trait.\",\n \"notes\": \"\",\n \"additionalStats\": {},\n \"attribute\": trait.attribute,\n \"isCoreSkill\": false,\n \"die\": {\n \"sides\": 4,\n \"modifier\": -2\n },\n \"wild-die\": {\n \"sides\": 6\n }\n }\n }\n await warpgate.mutate(token.document, itemmutate, {}, mutateOptions);\n }\n mutateOptions.permanent = true;\n await warpgate.mutate(token.document, mutate, {}, mutateOptions);\n }\n}","folder":null,"sort":0,"permission":{"default":0,"ygiRButlaf23fX9p":3},"flags":{"scene-packer":{"hash":"de40818571bebaf7d7b661be5880490654328fb3","sourceId":"Macro.ETjGUe4hbN0D9kV3","defaultPermission":2},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"},"core":{"sourceId":"Macro.ETjGUe4hbN0D9kV3"}}} +{"_id":"uB67GR2V90kmvyVs","name":"Deflection (SWADE)","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"icons/magic/defensive/shield-barrier-deflect-teal.webp","scope":"global","command":"const ICON = 'icons/magic/defensive/shield-barrier-deflect-teal.webp'\n\nlet tokens = [];\nlet targets = Array.from(game.user.targets);\nif (targets.length > 0) {\n tokens = targets;\n} else if (canvas.tokens.controlled.length > 0) {\n tokens = canvas.tokens.controlled;\n}\nif (tokens.length > 0) {\n main(tokens);\n} else {\n ui.notifications.error(\"Please select or target a token\");\n}\n\nasync function main(tokens) {\n let tokenList = tokens.map(t => t.name).join(\", \");\n let dialogOptions = {\n title: \"Deflection\",\n content: `Apply Deflection to ${tokenList}`,\n default: \"cancel\",\n buttons: [\n {label: \"Apply (-2)\", value: \"apply\"},\n {label: \"Apply with raise (-4)\", value: \"raise\"},\n {label: \"Cancel\", value: \"cancel\"}\n ]\n }\n let choice = await warpgate.buttonDialog(dialogOptions);\n if (choice != \"cancel\") {\n createEffect(tokens, choice);\n }\n}\n\nasync function createEffect(tokens, choice) {\n let effectName = 'Deflection';\n let effectId = `deflection${choice}`;\n let changes = []\n if (choice == \"raise\") {\n effectName = \"Major \" + effectName;\n }\n const effectIcon = ICON;\n for (const token of tokens) {\n let effectData = {\n icon: effectIcon,\n id: effectId,\n label: effectName,\n duration: {rounds: 5},\n flags: {\n swade: {\n expiration: 3,\n loseTurnOnHold: true\n }\n },\n changes: [\n {key: 'data.stats.parry.modifier', mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE, value: 0, priority: 0}\n ],\n };\n let mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n };\n mutate.embedded.ActiveEffect[effectName] = effectData;\n let mutateOptions = {\n comparisonKeys: {'ActiveEffect': 'label'},\n name: effectName,\n permanent: true,\n description: effectName,\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions);\n }\n}","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"scene-packer":{"hash":"5aaf1e3ca287022321b0e6c7b610e1a42175d2b2","sourceId":"Macro.uB67GR2V90kmvyVs"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"},"core":{"sourceId":"Compendium.swade-mb-shared.macros.uB67GR2V90kmvyVs"}}} +{"_id":"p94dkSmOgfuoC28K","name":"Deflection (SWPF)","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"icons/magic/defensive/shield-barrier-deflect-teal.webp","scope":"global","command":"const ICON = 'icons/magic/defensive/shield-barrier-deflect-teal.webp'\n\nlet tokens = [];\nlet targets = Array.from(game.user.targets);\nif (targets.length > 0) {\n tokens = targets;\n} else if (canvas.tokens.controlled.length > 0) {\n tokens = canvas.tokens.controlled;\n}\nif (tokens.length > 0) {\n main(tokens);\n} else {\n ui.notifications.error(\"Please select or target a token\");\n}\n\nasync function main(tokens) {\n let tokenList = tokens.map(t => t.name).join(\", \");\n let dialogOptions = {\n title: \"Deflection\",\n content: `Apply Deflection to ${tokenList}`,\n default: \"cancel\",\n buttons: [\n {label: \"Apply (melee)\", value: \"melee\"},\n {label: \"Apply (ranged)\", value: \"ranged\"},\n {label: \"Apply with raise (both)\", value: \"raise\"},\n {label: \"Cancel\", value: \"cancel\"}\n ]\n }\n let choice = await warpgate.buttonDialog(dialogOptions);\n if (choice != \"cancel\") {\n createEffect(tokens, choice);\n }\n}\n\nasync function createEffect(tokens, choice) {\n let effectName = 'Deflection';\n let effectId = `deflection${choice}`;\n let changes = []\n switch (choice) {\n case 'melee':\n effectName = \"Melee \" + effectName;\n break\n case 'ranged':\n effectName = \"Ranged \" + effectName;\n break \n }\n const effectIcon = ICON;\n for (const token of tokens) {\n let effectData = {\n icon: effectIcon,\n id: effectId,\n label: effectName,\n duration: {rounds: 5},\n flags: {\n swade: {\n expiration: 3,\n loseTurnOnHold: true\n }\n },\n changes: [\n {key: 'data.stats.parry.modifier', mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE, value: 0, priority: 0}\n ],\n };\n let mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n };\n mutate.embedded.ActiveEffect[effectName] = effectData;\n let mutateOptions = {\n comparisonKeys: {'ActiveEffect': 'label'},\n name: effectName,\n permanent: true,\n description: effectName,\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions);\n }\n}","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"scene-packer":{"hash":"9fef11ff303f385dcc039b421c26212cdee832c2","sourceId":"Macro.p94dkSmOgfuoC28K"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"},"advanced-macros":{"runAsGM":false},"core":{"sourceId":"Compendium.swade-mb-shared.macros.p94dkSmOgfuoC28K"}}} +{"_id":"K51dscyigZyR1Kma","name":"Elemental Manipulation","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"icons/magic/symbols/elements-air-earth-fire-water.webp","scope":"global","command":"const ICON = 'icons/magic/symbols/elements-air-earth-fire-water.webp'\n\nlet tokens = [];\nlet targets = Array.from(game.user.targets);\nif (targets.length > 0) {\n tokens = targets;\n} else if (canvas.tokens.controlled.length > 0) {\n tokens = canvas.tokens.controlled;\n}\nif (tokens.length > 0) {\n main(tokens);\n} else {\n ui.notifications.error(\"Please select or target a token\");\n}\n\nasync function main(tokens) {\n let tokenList = tokens.map(t => t.name).join(\", \");\n let dialogOptions = {\n title: \"Elemental Manipulation\",\n content: `Apply Elemental Manipulation to ${tokenList}`,\n default: \"cancel\",\n buttons: [\n {label: \"Apply\", value: \"apply\"},\n {label: \"Apply with raise\", value: \"raise\"},\n {label: \"Cancel\", value: \"cancel\"}\n ]\n }\n let choice = await warpgate.buttonDialog(dialogOptions);\n if (choice != \"cancel\") {\n createEffect(tokens, choice);\n }\n}\n\nasync function createEffect(tokens, choice) {\n let effectName = 'Elemental Manipulation';\n let effectId = 'elementalmanipulation';\n const effectIcon = ICON;\n let changes = [];\n for (const token of tokens) {\n let effectData = {\n icon: effectIcon,\n id: effectId,\n label: effectName,\n duration: {rounds: 5},\n flags: {\n swade: {\n expiration: 3,\n loseTurnOnHold: true\n }\n },\n changes: changes,\n };\n let range = token.actor.data.data.attributes.smarts.die.sides.toString()\n let itemMutate = {\n embedded: {\n Item: {\n \"Elemental Manipulation: Thrown Rocks\": {\n \"name\": \"Elemental Manipulation: Thrown Rock\",\n \"type\": \"weapon\",\n \"img\": \"icons/magic/earth/projectile-stone-ball-orange.webp\",\n \"data\": {\n \"description\": \"\",\n \"notes\": \"\",\n \"additionalStats\": {},\n \"quantity\": 1,\n \"weight\": 0,\n \"price\": 0,\n \"equippable\": true,\n \"equipped\": true,\n \"isArcaneDevice\": false,\n \"isVehicular\": false,\n \"mods\": 1,\n \"actions\": {\n \"skill\": \"Athletics\",\n \"skillMod\": \"\",\n \"dmgMod\": \"\",\n \"additional\": {}\n },\n \"bonusDamageDie\": 6,\n \"damage\": \"2d4\",\n \"range\": range,\n \"rof\": \"1\",\n \"ap\": 0,\n \"parry\": 0,\n \"minStr\": \"\",\n \"shots\": 0,\n \"currentShots\": 0,\n \"ammo\": \"\",\n \"autoReload\": false\n },\n \"effects\": [],\n \"folder\": null,\n \"sort\": 0,\n \"permission\": { \"default\": 0 },\n \"flags\": {}\n },\n \"Elemental Manipulation: Fire Blast\": {\n \"name\": \"Elemental Manipulation: Fire Blast\",\n \"type\": \"weapon\",\n \"img\": \"icons/magic/fire/explosion-fireball-medium-orange.webp\",\n \"data\": {\n \"description\": \"\",\n \"notes\": \"\",\n \"additionalStats\": {},\n \"quantity\": 1,\n \"weight\": 0,\n \"price\": 0,\n \"equippable\": true,\n \"equipped\": true,\n \"isArcaneDevice\": false,\n \"isVehicular\": false,\n \"mods\": 1,\n \"actions\": {\n \"skill\": \"Athletics\",\n \"skillMod\": \"\",\n \"dmgMod\": \"\",\n \"additional\": {}\n },\n \"bonusDamageDie\": 6,\n \"damage\": \"2d4\",\n \"range\": range,\n \"rof\": \"1\",\n \"ap\": 0,\n \"parry\": 0,\n \"minStr\": \"\",\n \"shots\": 0,\n \"currentShots\": 0,\n \"ammo\": \"\",\n \"autoReload\": false\n },\n \"effects\": [],\n \"folder\": null,\n \"sort\": 0,\n \"permission\": { \"default\": 0 },\n \"flags\": {}\n }\n }\n }\n }\n let mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n };\n mutate.embedded.ActiveEffect[effectName] = effectData;\n let mutateOptions = {\n comparisonKeys: {'ActiveEffect': 'label'},\n name: effectName,\n permanent: true,\n description: effectName,\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions);\n mutateOptions.permanent = false;\n await warpgate.mutate(token.document, itemMutate, {}, mutateOptions);\n }\n}","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"scene-packer":{"hash":"0318a6a5650fcdfffa0a670ca22c559c503bc575","sourceId":"Macro.K51dscyigZyR1Kma"},"advanced-macros":{"runAsGM":false},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"}}} +{"_id":"c8lz4DUmw6afCYRC","name":"Environmental Protection","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"icons/magic/defensive/armor-shield-barrier-steel.webp","scope":"global","command":"const powerEffectApply = game.macros.getName(\"Power Effect\");\n\nreturn await powerEffectApply.execute(\"Environmental Protection\");","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"advanced-macros":{"runAsGM":false},"combat-utility-belt":{"macroTrigger":""},"core":{"sourceId":"Macro.01dTmSPBq0xJQJcm"},"scene-packer":{"sourceId":"Macro.c8lz4DUmw6afCYRC","hash":"0df93d946a1860cbef3fffcc10cb152cc5e41735"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"}}} +{"_id":"9KVvOhKLlyZHrQ76","name":"Fly","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"systems/swade/assets/icons/status/status_flying.svg","scope":"global","command":"const powerEffectApply = game.macros.getName(\"Power Effect\");\n\nreturn await powerEffectApply.execute(\"Fly\");","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"advanced-macros":{"runAsGM":false},"combat-utility-belt":{"macroTrigger":""},"core":{"sourceId":"Macro.01dTmSPBq0xJQJcm"},"scene-packer":{"sourceId":"Macro.9KVvOhKLlyZHrQ76","hash":"48cfba28bf13ab364cef9bdc7953f64c23d9c5e4"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"}}} +{"_id":"OAC1Ofm7iEjU9KAm","name":"Growth/Shrink","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"icons/magic/control/silhouette-grow-shrink-blue.webp","scope":"global","command":"const GROWTHICON = 'icons/magic/control/silhouette-grow-shrink-blue.webp'\nconst SHRINKICON = 'icons/magic/control/silhouette-grow-shrink-tan.webp'\n\nlet tokens = [];\nlet targets = Array.from(game.user.targets);\nif (targets.length > 0) {\n tokens = targets;\n} else if (canvas.tokens.controlled.length > 0) {\n tokens = canvas.tokens.controlled;\n}\nif (tokens.length > 0) {\n main(tokens);\n} else {\n ui.notifications.error(\"Please select or target a token\");\n}\n\nasync function main(tokens) {\n let tokenList = tokens.map(t => t.name).join(\", \");\n let menuOptions = {\n title: 'Growth/Shrink',\n defaultButton: \"Cancel\",\n options: {}\n };\n let menuData = {\n inputs: [\n { type: 'header', label: 'Growth/Shrink' },\n { type: 'info', label: `Affected Tokens: ${tokenList}` },\n { type: 'number', label: 'Number of steps (2pp ea)' },\n { type: 'info', label: \"Grow or Shrink\" },\n { type: 'radio', label: 'Growth', options: ['isspeed', true] },\n { type: 'radio', label: 'Shrink', options: ['isspeed', false] },\n ],\n buttons: [\n { label: \"Apply\", value: \"apply\" },\n { label: \"Cancel\", value: \"cancel\" }\n ]\n }\n let { buttons, inputs } = await warpgate.menu(menuData, menuOptions);\n if (buttons && buttons != \"cancel\") {\n let direction = inputs[4] || inputs[5];\n let steps = inputs[2];\n createEffect(tokens, steps, direction, buttons);\n }\n}\n\nasync function createEffect(tokens, steps, direction, buttons) {\n const effectName = direction\n const effectId = direction\n const effectIcon = (direction == \"Growth\" ? GROWTHICON : SHRINKICON)\n for (const token of tokens) {\n let tokenDoc = token.document;\n let mode = foundry.CONST.ACTIVE_EFFECT_MODES.ADD;\n let effectData = {\n icon: effectIcon,\n id: effectId,\n label: effectName,\n duration: {rounds: 5},\n flags: {\n swade: {\n expiration: 3,\n loseTurnOnHold: true\n }\n },\n changes: []\n };\n let strDie = token.actor.data.data.attributes.strength.die.sides;\n let size = token.actor.data.data.stats.size;\n let strDieChange = 0;\n let strModChange = 0;\n let sizeChange = 0;\n if (direction == \"Growth\") {\n strDieChange = 2 * steps;\n sizeChange = steps;\n while (strDie + strDieChange > 12) {\n strDieChange -= 2;\n strModChange += 1;\n }\n } else {\n let stepCount = steps;\n while (size + sizeChange > -2 && stepCount > 0) {\n stepCount -= 1;\n strDieChange -= 2;\n sizeChange -= 1;\n }\n if (strDie + strDieChange < 4) {\n strDieChange = (4 - strDie);\n }\n }\n effectData.changes.push(\n {\n key: 'data.stats.size',\n mode: mode,\n value: sizeChange\n }\n )\n effectData.changes.push(\n {\n key: 'data.attributes.strength.die.sides',\n mode: mode,\n value: strDieChange,\n }\n )\n effectData.changes.push(\n {\n key: 'data.attributes.strength.die.modifier',\n mode: mode,\n value: strModChange\n }\n )\n size += sizeChange;\n let scale = 0;\n let height = 1;\n let width = 1;\n switch (size) {\n case -2: scale = 0.6; break;\n case -1: scale = 0.8; break\n case 0: break;\n case 1: scale = 1.2; break;\n case 2: scale = 1.5; break;\n case 3: scale = 2; break;\n case 4: height = 2; width = 2; scale = 1; break;\n case 5: height = 2; width = 2; scale = 1.2; break;\n case 6: height = 2; width = 2; scale = 1.5; break;\n case 7: height = 2; width = 2; scale = 1.5; break;\n case 8: height = 3; width = 3; scale = 1; break;\n case 9: height = 3; width = 3; scale = 1.2; break;\n case 10: height = 3; width = 3; scale = 1.4; break;\n case 11: height = 3; width = 3; scale = 1.6; break;\n }\n if (size < -2) {\n scale = 0.5;\n } else if (size > 11) {\n scale = 1\n height = 4\n width = 4\n }\n let tempMutate = {\n token: {\n scale: scale,\n height: height,\n width: width\n }\n }\n let mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n };\n mutate.embedded.ActiveEffect[effectName] = effectData;\n let mutateOptions = {\n comparisonKeys: { 'ActiveEffect': 'label' },\n name: effectName,\n description: effectName,\n }\n await warpgate.mutate(token.document, tempMutate, {}, mutateOptions);\n mutateOptions.permanent = true;\n await warpgate.mutate(token.document, mutate, {}, mutateOptions);\n }\n}","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"scene-packer":{"hash":"fec641bdb49b373724c0d05e62323c04e5c2fe08","sourceId":"Macro.OAC1Ofm7iEjU9KAm"},"advanced-macros":{"runAsGM":false},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"}}} +{"_id":"79YiKPX3WcmBeMzm","name":"Intangibility","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"icons/magic/control/debuff-energy-hold-levitate-blue-yellow.webp","scope":"global","command":"const powerEffectApply = game.macros.getName(\"Power Effect\");\n\nreturn await powerEffectApply.execute(\"Intangibility\");","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"advanced-macros":{"runAsGM":false},"combat-utility-belt":{"macroTrigger":""},"core":{"sourceId":"Macro.01dTmSPBq0xJQJcm"},"scene-packer":{"sourceId":"Macro.79YiKPX3WcmBeMzm","hash":"48cfba28bf13ab364cef9bdc7953f64c23d9c5e4"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"}}} +{"_id":"4SRoZduQrF2o3MZK","name":"Invisibility","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"systems/swade/assets/icons/status/status_invisible.svg","scope":"global","command":"const powerEffectApply = game.macros.getName(\"Power Effect\");\n\nreturn await powerEffectApply.execute(\"Invisibility\");","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"advanced-macros":{"runAsGM":false},"combat-utility-belt":{"macroTrigger":""},"core":{"sourceId":"Macro.01dTmSPBq0xJQJcm"},"scene-packer":{"sourceId":"Macro.4SRoZduQrF2o3MZK","hash":"86acbda4ecfadba35cb7adb877aea4bc164c06a6"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"}}} +{"_id":"VzTYSKRXvpOTquUO","name":"Power Effect","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"icons/magic/symbols/rune-sigil-green.webp","scope":"global","command":"const POWERS = new Map([\n ['Invisibility', {\n icon: 'systems/swade/assets/icons/status/status_invisible.svg',\n duration: {rounds: 5},\n extra: {expiration: 3, loseTurnOnHold: true},\n changes: []\n }],\n ['Intangibility', {\n icon: 'icons/magic/control/debuff-energy-hold-levitate-blue-yellow.webp',\n duration: {rounds: 5},\n extra: {expiration: 3, loseTurnOnHold: true},\n changes: []\n }],\n ['Fly', {\n icon: 'systems/swade/assets/icons/status/status_flying.svg',\n duration: {rounds: 5},\n extra: {expiration: 3, loseTurnOnHold: true},\n changes: []\n }],\n ['Sanctuary', {\n icon: 'icons/magic/defensive/shield-barrier-flaming-diamond-blue-yellow.webp',\n duration: {rounds: 5},\n extra: {expiration: 3, loseTurnOnHold: true},\n changes: []\n }],\n ['Arcane Protection', {\n icon: 'icons/magic/defensive/shield-barrier-deflect-gold.webp',\n duration: {rounds: 5},\n extra: {expiration: 3, loseTurnOnHold: true},\n changes: []\n }],\n ['Environmental Protection', {\n icon: 'icons/magic/defensive/armor-shield-barrier-steel.webp',\n duration: {seconds: 3600},\n extra: {expiration: 3, loseTurnOnHold: true},\n changes: []\n }]\n]);\nlet argEffectName = \"\";\ntry {\n if (args !== undefined && POWERS.has(args[0])) {\n argEffectName = args[0];\n }\n} catch (error) {}\n\n\nlet tokens = [];\nlet targets = Array.from(game.user.targets);\nif (targets.length > 0) {\n tokens = targets;\n} else if (canvas.tokens.controlled.length > 0) {\n tokens = canvas.tokens.controlled;\n}\nif (tokens.length > 0) {\n main(tokens);\n} else {\n ui.notifications.error(\"Please select or target a token\");\n}\n\nasync function main(tokens) {\n let tokenList = tokens.map(t => t.name).join(\", \");\n let powers = [...POWERS].map(p => p[0]).sort();\n if (argEffectName) {\n let dialogOptions = {\n title: argEffectName,\n content: `Apply ${argEffectName} to ${tokenList}`,\n default: \"cancel\",\n buttons: [\n {label: \"Apply\", value: \"apply\"},\n {label: \"Apply with raise\", value: \"raise\"},\n {label: \"Cancel\", value: \"cancel\"}\n ]\n }\n let choice = await warpgate.buttonDialog(dialogOptions);\n if (choice != \"cancel\") {\n const power = POWERS.get(argEffectName);\n createEffect(tokens, choice, argEffectName, power);\n }\n } else {\n powers.unshift('');\n let menuOptions = {\n title: 'Apply Power',\n defaultButton: \"Cancel\",\n options: {}\n }\n let menuData = {\n inputs: [\n {type: 'info', label: `Affected Tokens: ${tokenList}`},\n {type: 'select', label: 'Power', options: powers},\n ],\n buttons: [\n {label: \"Apply\", value: \"apply\"},\n {label: \"Apply with raise\", value: \"raise\"},\n {label: \"Cancel\", value: \"cancel\"}\n ]\n }\n let {buttons, inputs} = await warpgate.menu(menuData, menuOptions);\n if (buttons != \"cancel\" && inputs[1] != '') {\n const power = POWERS.get(inputs[1]);\n createEffect(tokens, buttons, inputs[1], power);\n }\n }\n}\n\nasync function createEffect(tokens, choice, powerName, power) {\n let effectName = powerName;\n let effectId = effectName.toLowerCase().replaceAll(/[^a-z0-9]/ig, '');\n const effectIcon = power.icon;\n let changes = power.changes;\n if (choice == 'raise') {\n effectName = `Major ${effectName}`;\n }\n for (const token of tokens) {\n let effectData = {\n icon: effectIcon,\n id: effectId,\n label: effectName,\n duration: power.duration,\n changes: changes,\n };\n if (power.extra) {\n effectData.flags = {'swade': power.extra};\n }\n let mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n };\n mutate.embedded.ActiveEffect[effectName] = effectData;\n let mutateOptions = {\n comparisonKeys: {'ActiveEffect': 'label'},\n name: effectName,\n permanent: true,\n description: effectName,\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions);\n }\n}","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"scene-packer":{"hash":"f58d43809e7c8b4acb768083c2d10ee6c90d1183","sourceId":"Macro.VzTYSKRXvpOTquUO"},"core":{"sourceId":"Macro.VzTYSKRXvpOTquUO"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"},"advanced-macros":{"runAsGM":false}}} +{"_id":"ZMWoKCwGTBTufQaF","name":"Protection (SWADE)","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"systems/swade/assets/icons/status/status_protection.svg","scope":"global","command":"const ICON = 'systems/swade/assets/icons/status/status_protection.svg'\n\nlet tokens = [];\nlet targets = Array.from(game.user.targets);\nif (targets.length > 0) {\n tokens = targets;\n} else if (canvas.tokens.controlled.length > 0) {\n tokens = canvas.tokens.controlled;\n}\nif (tokens.length > 0) {\n main(tokens);\n} else {\n ui.notifications.error(\"Please select or target a token\");\n}\n\nasync function main(tokens) {\n let tokenList = tokens.map(t => t.name).join(\", \");\n let dialogOptions = {\n title: \"Protection\",\n content: `Apply Protection to ${tokenList}`,\n default: \"cancel\",\n buttons: [\n {label: \"Apply (+2 armor)\", value: \"apply\"},\n {label: \"Apply with raise (+4 armor)\", value: \"raise\"},\n {label: \"Cancel\", value: \"cancel\"}\n ]\n }\n let choice = await warpgate.buttonDialog(dialogOptions);\n if (choice != \"cancel\") {\n createEffect(tokens, choice);\n }\n}\n\nasync function createEffect(tokens, choice) {\n let effectName = 'Protection';\n let effectId = 'protection';\n const effectIcon = ICON;\n let changes = [\n {\n key: 'data.stats.toughness.armor',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE,\n value: 2,\n priority: 0\n }\n ];\n if (choice == 'raise') {\n changes[0].value = 4\n }\n for (const token of tokens) {\n let effectData = {\n icon: effectIcon,\n id: effectId,\n label: effectName,\n duration: {rounds: 5},\n flags: {\n swade: {\n expiration: 3,\n loseTurnOnHold: true\n }\n },\n changes: changes,\n };\n let mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n };\n mutate.embedded.ActiveEffect[effectName] = effectData;\n let mutateOptions = {\n comparisonKeys: {'ActiveEffect': 'label'},\n name: effectName,\n permanent: true,\n description: effectName,\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions);\n }\n}","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"scene-packer":{"hash":"e57a55958fcf779fbae52d3964558fc71347c868","sourceId":"Macro.ZMWoKCwGTBTufQaF"},"core":{"sourceId":"Macro.U6ysKunxzRsvhnR6"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"}}} +{"_id":"U6ysKunxzRsvhnR6","name":"Protection (SWPF)","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"systems/swade/assets/icons/status/status_protection.svg","scope":"global","command":"const ICON = 'systems/swade/assets/icons/status/status_protection.svg'\n\nlet tokens = [];\nlet targets = Array.from(game.user.targets);\nif (targets.length > 0) {\n tokens = targets;\n} else if (canvas.tokens.controlled.length > 0) {\n tokens = canvas.tokens.controlled;\n}\nif (tokens.length > 0) {\n main(tokens);\n} else {\n ui.notifications.error(\"Please select or target a token\");\n}\n\nasync function main(tokens) {\n let tokenList = tokens.map(t => t.name).join(\", \");\n let dialogOptions = {\n title: \"Protection\",\n content: `Apply Protection to ${tokenList}`,\n default: \"cancel\",\n buttons: [\n {label: \"Apply (+2 armor)\", value: \"apply\"},\n {label: \"Apply with raise (+2 toughness)\", value: \"raise\"},\n {label: \"Cancel\", value: \"cancel\"}\n ]\n }\n let choice = await warpgate.buttonDialog(dialogOptions);\n if (choice != \"cancel\") {\n createEffect(tokens, choice);\n }\n}\n\nasync function createEffect(tokens, choice) {\n let effectName = 'Protection';\n let effectId = 'protection';\n const effectIcon = ICON;\n let changes = [\n {\n key: 'data.stats.toughness.armor',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE,\n value: 2,\n priority: 0\n }\n ];\n if (choice == 'raise') {\n changes[0].key = 'data.stats.toughness.value';\n }\n for (const token of tokens) {\n let effectData = {\n icon: effectIcon,\n id: effectId,\n label: effectName,\n duration: {rounds: 5},\n flags: {\n swade: {\n expiration: 3,\n loseTurnOnHold: true\n }\n },\n changes: changes,\n };\n let mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n };\n mutate.embedded.ActiveEffect[effectName] = effectData;\n let mutateOptions = {\n comparisonKeys: {'ActiveEffect': 'label'},\n name: effectName,\n permanent: true,\n description: effectName,\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions);\n }\n}","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"scene-packer":{"hash":"957aefe73814ccfb53a7ae2d2cbfa68bc3200c6d","sourceId":"Macro.U6ysKunxzRsvhnR6"},"core":{"sourceId":"Macro.U6ysKunxzRsvhnR6"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"}}} +{"_id":"yV3XNCfgHpGrREt0","name":"Sanctuary","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"icons/magic/defensive/shield-barrier-flaming-diamond-blue-yellow.webp","scope":"global","command":"const powerEffectApply = game.macros.getName(\"Power Effect\");\n\nreturn await powerEffectApply.execute(\"Sanctuary\");","folder":null,"sort":0,"permission":{"default":0,"ygiRButlaf23fX9p":3},"flags":{"advanced-macros":{"runAsGM":false},"combat-utility-belt":{"macroTrigger":""},"core":{"sourceId":"Macro.01dTmSPBq0xJQJcm"},"scene-packer":{"sourceId":"Macro.fzA6qQ1PyNgV8FqE","hash":"a45f562cc1f65a09386c3a6f9006b1fad3650f78"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"}}} +{"_id":"FngiDIs9HR2p0eY1","name":"Sloth/Speed","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"icons/skills/movement/feet-winged-boots-glowing-yellow.webp","scope":"global","command":"const SPEEDICON = 'icons/skills/movement/feet-winged-boots-glowing-yellow.webp'\nconst SLOTHICON = 'icons/magic/control/encase-creature-spider-hold.webp'\n\nlet tokens = [];\nlet targets = Array.from(game.user.targets);\nif (targets.length > 0) {\n tokens = targets;\n} else if (canvas.tokens.controlled.length > 0) {\n tokens = canvas.tokens.controlled;\n}\nif (tokens.length > 0) {\n main(tokens);\n} else {\n ui.notifications.error(\"Please select or target a token\");\n}\n\nasync function main(tokens) {\n let tokenList = tokens.map(t => t.name).join(\", \");\n let menuOptions = {\n title: 'Sloth/Speed',\n defaultButton: \"Cancel\",\n options: {}\n };\n let menuData = {\n inputs: [\n { type: 'header', label: 'Sloth/Speed' },\n { type: 'info', label: `Affected Tokens: ${tokenList}` },\n { type: 'info', label: \"Speed or Sloth\" },\n { type: 'radio', label: 'Speed', options: ['isspeed', true] },\n { type: 'radio', label: 'Sloth', options: ['isspeed', false] },\n ],\n buttons: [\n { label: \"Apply\", value: \"apply\" },\n { label: \"Apply with raise\", value: \"raise\" },\n { label: \"Cancel\", value: \"cancel\" }\n ]\n }\n let { buttons, inputs } = await warpgate.menu(menuData, menuOptions);\n if (buttons != \"cancel\") {\n let direction = inputs[3] || inputs[4];\n createEffect(tokens, direction, buttons);\n }\n}\n\nasync function createEffect(tokens, direction, buttons) {\n const raise = (buttons == 'raise');\n const effectName = `${raise ? \"Major\" : \"Minor\"} ${direction}`;\n const effectId = `${raise ? \"Major\" : \"Minor\"}${direction}`;\n const effectIcon = (direction == \"Speed\" ? SPEEDICON : SLOTHICON)\n for (const token of tokens) {\n let tokenDoc = token.document;\n let effectData = {\n icon: effectIcon,\n id: effectId,\n label: effectName,\n flags: {\n swade: {\n expiration: 3,\n loseTurnOnHold: true\n }\n },\n changes: []\n };\n let mode = foundry.CONST.ACTIVE_EFFECT_MODES.MULTIPLY;\n if (direction == \"Speed\") {\n effectData.duration = { rounds: 5 };\n effectData.changes.push({\n key: 'data.stats.speed.value',\n mode: mode,\n value: 2\n })\n } else {\n effectData.changes.push({\n key: 'data.stats.speed.value',\n mode: mode,\n value: 0.5\n })\n }\n let mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n };\n mutate.embedded.ActiveEffect[effectName] = effectData;\n let mutateOptions = {\n comparisonKeys: { 'ActiveEffect': 'label' },\n name: effectName,\n permanent: true,\n description: effectName,\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions);\n }\n}","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"scene-packer":{"hash":"0318a6a5650fcdfffa0a670ca22c559c503bc575","sourceId":"Macro.FngiDIs9HR2p0eY1"},"advanced-macros":{"runAsGM":false},"core":{"sourceId":"Macro.FngiDIs9HR2p0eY1"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"}}} +{"_id":"tjaqN9gedJpYFgbu","name":"Smite","type":"script","author":"HXnQ3GTDyHZ7E1ev","img":"systems/swade/assets/icons/status/status_smite.svg","scope":"global","command":"const ICON = 'systems/swade/assets/icons/status/status_smite.svg'\n\nlet tokens = [];\nlet targets = Array.from(game.user.targets);\nif (targets.length > 0) {\n tokens = targets;\n} else if (canvas.tokens.controlled.length > 0) {\n tokens = canvas.tokens.controlled;\n}\nif (tokens.length > 0) {\n main(tokens);\n} else {\n ui.notifications.error(\"Please select or target a token\");\n}\n\nasync function main(tokens) {\n let tokenList = tokens.map(t => t.name).join(\", \");\n let menuOptions = {\n title: 'Smite',\n defaultButton: \"cancel\",\n options: {}\n }\n let menuData = {\n inputs: [\n {type: 'header', label: 'Smite'},\n {type: 'info', label: `Apply Smite to ${tokenList}`},\n ],\n buttons: [\n {label: \"Apply\", value: \"apply\"},\n {label: \"Apply with Raise\", value: \"raise\"},\n {label: \"Cancel\", value: \"cancel\"}\n ]\n }\n let tokenWeapons = {};\n let index = 1;\n for (const token of tokens) {\n index += 2;\n tokenWeapons[token.id] = index;\n menuData.inputs.push({type: 'info', label: `

${token.name}

`});\n let weapons = token.actor.items.filter(i => i.type == 'weapon').map(i => i.name);\n weapons.unshift(\"\");\n menuData.inputs.push({type: 'select', label: token.name, options: weapons});\n }\n let {buttons, inputs} = await warpgate.menu(menuData, menuOptions);\n for (let tokenid in tokenWeapons) {\n tokenWeapons[tokenid] = inputs[tokenWeapons[tokenid]];\n }\n if (buttons != \"cancel\") {\n await createEffect(tokens, tokenWeapons, buttons);\n }\n console.log(buttons, tokenWeapons);\n}\n\nasync function createEffect(tokens, tokenWeapons, choice) {\n const effectIcon = ICON;\n const changeValue = (choice == 'raise' ? \"+4\" : \"+2\");\n for (const token of tokens) {\n const weaponName = tokenWeapons[token.id];\n const weaponId = token.actor.items.getName(weaponName)?.id\n const changeKey = `@Weapon{${weaponName}}[data.damage]`\n if (!weaponId) {\n continue\n }\n const effectName = `Smite (${weaponName})`;\n const effectId = `smite${choice}_${weaponId}`;\n let effectData = {\n icon: effectIcon,\n id: effectId,\n label: effectName,\n duration: {rounds: 5},\n flags: {\n swade: {\n expiration: 3,\n loseTurnOnHold: true\n }\n },\n changes: [\n {\n key: changeKey,\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: changeValue,\n priority: 0\n }\n ],\n };\n let mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n };\n mutate.embedded.ActiveEffect[effectName] = effectData;\n let mutateOptions = {\n comparisonKeys: {'ActiveEffect': 'label'},\n name: effectName,\n permanent: true,\n description: effectName,\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions);\n }\n}","folder":null,"sort":0,"permission":{"default":0,"ygiRButlaf23fX9p":3},"flags":{"advanced-macros":{"runAsGM":false},"combat-utility-belt":{"macroTrigger":""},"core":{"sourceId":"Macro.MXSe0F5osRtleDV4"},"scene-packer":{"sourceId":"Macro.MXSe0F5osRtleDV4","hash":"a74182d3f48775895d7f8e9b4b0af22194eaa82c"},"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000"}}} +{"_id":"wa7ZoYUhNcjrNEmN","name":"#[CF_tempEntity]","type":"chat","author":"HXnQ3GTDyHZ7E1ev","img":"icons/svg/dice-target.svg","scope":"global","command":"","folder":null,"sort":0,"permission":{"default":0,"HXnQ3GTDyHZ7E1ev":3},"flags":{"cf":{"id":"temp_g9ptj9b0b4s","path":"SWADE Spell Effects (WarpGate)","color":"#000000","name":"SWADE Spell Effects (WarpGate)","children":["ye1BuJD7kKGAyReU","fzkUWlTKCJ68nEzL","uB67GR2V90kmvyVs","p94dkSmOgfuoC28K","K51dscyigZyR1Kma","c8lz4DUmw6afCYRC","9KVvOhKLlyZHrQ76",null,"79YiKPX3WcmBeMzm","4SRoZduQrF2o3MZK","VzTYSKRXvpOTquUO","ZMWoKCwGTBTufQaF","U6ysKunxzRsvhnR6","yV3XNCfgHpGrREt0","FngiDIs9HR2p0eY1","tjaqN9gedJpYFgbu"],"folderPath":[]},"scene-packer":{"hash":"3d9a8396d815dcef72c41f01fa0318a9a20c0bb4"}}}