From 21117466438c8303c6f7abce841192e7e4540f6d Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Sun, 5 Mar 2023 22:50:34 -0600 Subject: [PATCH 1/7] add unreleased to changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd5d1a8..2857240 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + + + ## 0.9.0 - Initial 'public' release -- 2.30.2 From c8a153d5148c6014fd444262cbfbd7e5689a4baf Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Mon, 6 Mar 2023 11:48:28 -0600 Subject: [PATCH 2/7] add confusion effect macro Closes #8 --- CHANGELOG.md | 2 ++ macros/confusion.js | 62 ++++++++++++++++++++++++++++++++++++++++++ packs/effect-macros.db | 21 +++++++------- 3 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 macros/confusion.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 2857240..c224f18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- Confusion effect macro ## 0.9.0 diff --git a/macros/confusion.js b/macros/confusion.js new file mode 100644 index 0000000..a60049c --- /dev/null +++ b/macros/confusion.js @@ -0,0 +1,62 @@ +swadeMBHelpers.runOnTargetOrSelectedTokens(main) + +async function main (tokens) { + const tokenList = tokens.map(t => t.name).join(', ') + const menuOptions = { + title: 'Confusion', + defaultButton: 'Cancel', + options: {} + } + + const menuData = { + inputs: [ + { type: 'header', label: 'Confusion' }, + { type: 'info', label: `Apply Confusion to ${tokenList}` }, + { type: 'checkbox', label: 'Greater (adds shaken)', options: false } + ], + buttons: [ + { label: 'Distracted', value: 'distracted' }, + { label: 'Vulnerable', value: 'vulnerable' }, + { label: 'Raise (both)', value: 'raise' }, + { label: 'Cancel', value: 'cancel' } + ] + } + + const { buttons, inputs } = await warpgate.menu(menuData, menuOptions) + const greater = (inputs[2] === 'Greater (adds shaken)') + if (buttons && buttons !== 'cancel') { + await createEffect(tokens, buttons, greater) + } +} + +function getStatus (label, name) { + const effect = JSON.parse(JSON.stringify( + CONFIG.statusEffects.find(se => se.label === label))) + effect.label = name + effect.flags.core = { statusId: effect.id } + effect.id = name + return effect +} + +async function createEffect (tokens, choice, greater) { + const effects = [] + if (choice === 'distracted' || choice === 'raise') { + effects.push(getStatus('SWADE.Distr', 'Distracted')) + } + if (choice === 'vulnerable' || choice === 'raise') { + effects.push(getStatus('SWADE.Vuln', 'Vulnerable')) + } + if (greater) { + effects.push(getStatus('SWADE.Shaken', 'Shaken')) + } + for (const token of tokens) { + const mutateOptions = swadeMBHelpers.defaultMutationOptions('Confusion') + const mutate = { + embedded: { ActiveEffect: {} } + } + for (const effect of effects) { + mutate.embedded.ActiveEffect[effect.id] = effect + } + await warpgate.mutate(token.document, mutate, {}, mutateOptions) + } +} diff --git a/packs/effect-macros.db b/packs/effect-macros.db index 6d2e7ed..1dd5883 100644 --- a/packs/effect-macros.db +++ b/packs/effect-macros.db @@ -1,10 +1,11 @@ -{"name":"Boost/Lower Trait","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/life/cross-embers-glow-yellow-purple.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n let traitOptions = [\n 'Agility', 'Smarts', 'Spirit', 'Strength', 'Vigor'\n ]\n const allSkills = []\n const traits = {}\n for (const traitName of traitOptions) {\n const lower = traitName.toLowerCase()\n traits[traitName] = {\n name: traitName,\n type: 'attribute',\n modkey: `system.attributes.${lower}.die.modifier`,\n diekey: `system.attributes.${lower}.die.sides`\n }\n }\n\n const tokenList = tokens.map(t => t.name).join(', ')\n for (const token of tokens) {\n const skills = token.actor.items.filter(item => item.type === 'skill')\n for (const skill of skills) {\n const name = skill.name\n traits[name] = {\n type: 'skill',\n name,\n modkey: `@Skill{${name}}[system.die.modifier]`,\n diekey: `@Skill{${name}}[system.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\n const menuOptions = {\n title: 'Boost/Lower Trait',\n defaultButton: 'Cancel',\n options: {}\n }\n const 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: ['isBoost', true] },\n { type: 'radio', label: 'Lower', options: ['isBoost', false] },\n { type: 'checkbox', label: 'Greater', options: false },\n { type: 'checkbox', label: 'Strong (lower only)', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n action: buttons,\n name: inputs[2],\n trait: traits[inputs[2]],\n direction: inputs[4] || inputs[5],\n greater: inputs[6],\n strong: inputs[7]\n }\n createEffect(tokens, options)\n }\n}\n\nconst UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp'\nconst DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp'\n\nasync function createEffect (tokens, options) {\n const raise = (options.action === 'raise')\n const icon = (options.direction === 'Boost' ? UPICON : DOWNICON)\n let namePart = `${options.direction} ${options.trait.name}`\n const mode = CONST.ACTIVE_EFFECT_MODES.ADD\n const mods = []\n if (options.strong && options.direction === 'Lower') {\n mods.push('strong')\n }\n if (options.greater) {\n mods.push('greater')\n }\n if (mods.length > 0) {\n namePart = `${namePart} (${mods.join(', ')})`\n }\n const minorEffect = swadeMBHelpers.createEffectDocument(\n icon, `minor ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n const majorEffect = swadeMBHelpers.createEffectDocument(\n icon, `major ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n if (options.direction === 'Lower' && options.greater === 'Greater') {\n minorEffect.changes.push({\n key: options.trait.modkey,\n mode,\n value: '-2',\n priority: 0\n })\n }\n const mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n }\n mutate.embedded.ActiveEffect[minorEffect.id] = minorEffect\n if (raise) {\n mutate.embedded.ActiveEffect[majorEffect.id] = majorEffect\n }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(namePart)\n for (const token of tokens) {\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677458254287,"modifiedTime":1678055458558,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"1AqIFHAcX5TRdE8X","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Smite","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_smite.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Smite',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Smite' },\n { type: 'info', label: `Apply Smite to ${tokenList}` },\n { type: 'checkbox', label: 'Greater', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with Raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const tokenWeapons = {}\n let index = 2\n for (const token of tokens) {\n index += 2\n tokenWeapons[token.id] = index\n menuData.inputs.push({ type: 'info', label: `

${token.name}

` })\n const weapons = token.actor.items.filter(i => i.type === 'weapon').map(\n i => { return { value: i.name, html: i.name } })\n weapons.unshift({ value: '', html: 'None' })\n menuData.inputs.push({ type: 'select', label: token.name, options: weapons })\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n for (const tokenId in tokenWeapons) {\n tokenWeapons[tokenId] = inputs[tokenWeapons[tokenId]]\n }\n const greater = (inputs[2] === 'Greater')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, tokenWeapons, buttons, greater)\n }\n}\n\nasync function createEffect (tokens, tokenWeapons, choice, greater) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Smite')\n const effectIcon = baseEffect.icon\n const effectId = baseEffect.id\n let changeValue = (choice === 'raise' ? '+4' : '+2')\n if (greater) {\n changeValue = (choice === 'raise' ? '+6' : '+4')\n }\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}}[system.damage]`\n if (!weaponId) {\n continue\n }\n const effectName = `${choice === 'raise' ? 'major' : 'minor'} Smite${greater ? '(greater)' : ''} (${weaponName})`\n const changes = [\n {\n key: changeKey,\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: changeValue,\n priority: 0\n }\n ]\n const mutate = swadeMBHelpers.createMutationWithEffect(\n effectIcon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.1GnCpp1vjEucgNGk"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677548889704,"modifiedTime":1678055458558,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"C1vGk7AKQDpcvKyP","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Deflection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/defensive/shield-barrier-deflect-teal.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/defensive/shield-barrier-deflect-teal.webp'\n let effectName = 'Deflection'\n if (choice === 'raise') {\n effectName = `${effectName} (all)`\n } else {\n effectName = `${effectName} (${choice})`\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677645552357,"modifiedTime":1678055458558,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"HYTiftQW0pwwOQGH","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Glow","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/light/explosion-star-blue-large.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Glow',\n content: `Apply Glow to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/light/explosion-star-blue-large.webp'\n const effectName = 'Glow'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.5,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'starlight'\n },\n bright: 0,\n color: '#0f3fff',\n coloration: 1,\n contrast: 0,\n dim: 0.5,\n luminosity: 0.5,\n saturation: 0,\n shadows: 0\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677704975699,"modifiedTime":1678055458559,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"JcZ9kxBZJpw8KLQ6","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Shroud","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/perception/silhouette-stealth-shadow.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Shroud',\n content: `Apply Shroud to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/perception/silhouette-stealth-shadow.webp'\n const effectName = 'Shroud'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.1,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'roiling'\n },\n bright: 0,\n color: null,\n coloration: 0,\n contrast: 0,\n dim: 0.1,\n luminosity: -0.15,\n saturation: 0,\n shadows: 0.25\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677649631598,"modifiedTime":1678055458559,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"QpillIBvZmuHeuTV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Summon","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/symbols/runes-star-orange.webp","scope":"global","command":"const ACTORFOLDER = 'Summonables'\nconst SUMMONICON = 'icons/magic/symbols/runes-star-orange.webp'\n\nswadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const token = tokens[0]\n const tokenList = token.name\n const folder = swadeMBHelpers.getActorFolderByPath(ACTORFOLDER)\n const actors = swadeMBHelpers.getActorsInFolder(folder)\n const menuOptions = {\n title: 'Summon Creature',\n defaultButton: 'cancel',\n options: {}\n }\n const menuData = {\n inputs: [\n { type: 'header', label: 'Summon Creature' },\n { type: 'info', label: `${tokenList} is summoning` },\n {\n type: 'select',\n label: 'Ally to summon',\n options: Object.keys(actors).sort().map(k => { return { value: actors[k].id, html: k } })\n },\n { type: 'number', label: 'Number to spawn (+half base cost per)', options: 1 }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const summonData = {\n raise: (buttons === 'raise'),\n actorId: inputs[2],\n number: inputs[3]\n }\n summonData.actor = game.actors.get(summonData.actorId)\n summonData.actorName = summonData.actor.name\n summonData.icon = summonData.actor.prototypeToken.texture.src\n summonData.token = summonData.actor.prototypeToken\n\n doWork(summonData, token)\n }\n}\n\nasync function doWork (summonData, token) {\n console.log('Summon ', token, summonData)\n const effectName = `Summoned ${summonData.actorName} (${summonData.number})`\n const tokenEffectMutation = swadeMBHelpers.createMutationWithEffect(SUMMONICON, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, tokenEffectMutation, {}, mutateOptions)\n\n const spawnOptions = {\n controllingActor: token.actor,\n duplicates: summonData.number,\n comparisonKeys: { ActiveEffect: 'label' },\n crosshairs: {\n size: 1,\n icon: summonData.icon,\n label: `Summon ${summonData.actorName}`,\n drawOutline: false,\n rememberControlled: true\n }\n }\n const spawnMutation = {\n token: {\n actorLink: false,\n name: `${token.name}'s ${summonData.token.name}`\n }\n }\n await warpgate.spawn(summonData.actorName, spawnMutation, {}, spawnOptions)\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677996503821,"modifiedTime":1678055458503,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"RV09eJi9iG5bfupo","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Protection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_protection.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Protection')\n const changes = [\n {\n key: 'system.stats.toughness.armor',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE,\n value: 2,\n priority: 0\n }\n ]\n let effectName = 'minor Protection'\n if (choice === 'raise') {\n changes[0].key = 'system.stats.toughness.value'\n effectName = 'major Protection'\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(\n baseEffect.icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677630174987,"modifiedTime":1678055458559,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"YETsNWOWfIxyLPdC","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Lingering Damage","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/acid/dissolve-arm-flesh.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Lingering Damage',\n content: `Apply Lingering Damage to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'Ok', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok') {\n await createEffect(tokens)\n }\n}\n\nasync function createEffect (tokens) {\n const icon = 'icons/magic/acid/dissolve-arm-flesh.webp'\n const effectName = 'Lingering Damage'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 1, [])\n mutate.embedded.ActiveEffect['Lingering Damage'].flags.swade.expiration =\n CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnPrompt\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677800587229,"modifiedTime":1678055458559,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"txJBrqgVNO3jpvFG","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Hinder","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/movement/abstract-ribbons-red-orange.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hinder',\n content: `Apply Hinder to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/movement/abstract-ribbons-red-orange.webp'\n const effectName = 'Hinder'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: -2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678055458559,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"uvHTdYUn5l3Z1rAV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Hurry","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/skills/movement/feet-winged-boots-blue.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hurry',\n content: `Apply Hurry to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/skills/movement/feet-winged-boots-blue.webp'\n const effectName = 'Hurry'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: 2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678055458560,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"yG1ZQO30ZlntYJp7","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Boost/Lower Trait","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/life/cross-embers-glow-yellow-purple.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n let traitOptions = [\n 'Agility', 'Smarts', 'Spirit', 'Strength', 'Vigor'\n ]\n const allSkills = []\n const traits = {}\n for (const traitName of traitOptions) {\n const lower = traitName.toLowerCase()\n traits[traitName] = {\n name: traitName,\n type: 'attribute',\n modkey: `system.attributes.${lower}.die.modifier`,\n diekey: `system.attributes.${lower}.die.sides`\n }\n }\n\n const tokenList = tokens.map(t => t.name).join(', ')\n for (const token of tokens) {\n const skills = token.actor.items.filter(item => item.type === 'skill')\n for (const skill of skills) {\n const name = skill.name\n traits[name] = {\n type: 'skill',\n name,\n modkey: `@Skill{${name}}[system.die.modifier]`,\n diekey: `@Skill{${name}}[system.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\n const menuOptions = {\n title: 'Boost/Lower Trait',\n defaultButton: 'Cancel',\n options: {}\n }\n const 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: ['isBoost', true] },\n { type: 'radio', label: 'Lower', options: ['isBoost', false] },\n { type: 'checkbox', label: 'Greater', options: false },\n { type: 'checkbox', label: 'Strong (lower only)', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n action: buttons,\n name: inputs[2],\n trait: traits[inputs[2]],\n direction: inputs[4] || inputs[5],\n greater: inputs[6],\n strong: inputs[7]\n }\n createEffect(tokens, options)\n }\n}\n\nconst UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp'\nconst DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp'\n\nasync function createEffect (tokens, options) {\n const raise = (options.action === 'raise')\n const icon = (options.direction === 'Boost' ? UPICON : DOWNICON)\n let namePart = `${options.direction} ${options.trait.name}`\n const mode = CONST.ACTIVE_EFFECT_MODES.ADD\n const mods = []\n if (options.strong && options.direction === 'Lower') {\n mods.push('strong')\n }\n if (options.greater) {\n mods.push('greater')\n }\n if (mods.length > 0) {\n namePart = `${namePart} (${mods.join(', ')})`\n }\n const minorEffect = swadeMBHelpers.createEffectDocument(\n icon, `minor ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n const majorEffect = swadeMBHelpers.createEffectDocument(\n icon, `major ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n if (options.direction === 'Lower' && options.greater === 'Greater') {\n minorEffect.changes.push({\n key: options.trait.modkey,\n mode,\n value: '-2',\n priority: 0\n })\n }\n const mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n }\n mutate.embedded.ActiveEffect[minorEffect.id] = minorEffect\n if (raise) {\n mutate.embedded.ActiveEffect[majorEffect.id] = majorEffect\n }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(namePart)\n for (const token of tokens) {\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677458254287,"modifiedTime":1678124792933,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"1AqIFHAcX5TRdE8X","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Smite","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_smite.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Smite',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Smite' },\n { type: 'info', label: `Apply Smite to ${tokenList}` },\n { type: 'checkbox', label: 'Greater', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with Raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const tokenWeapons = {}\n let index = 2\n for (const token of tokens) {\n index += 2\n tokenWeapons[token.id] = index\n menuData.inputs.push({ type: 'info', label: `

${token.name}

` })\n const weapons = token.actor.items.filter(i => i.type === 'weapon').map(\n i => { return { value: i.name, html: i.name } })\n weapons.unshift({ value: '', html: 'None' })\n menuData.inputs.push({ type: 'select', label: token.name, options: weapons })\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n for (const tokenId in tokenWeapons) {\n tokenWeapons[tokenId] = inputs[tokenWeapons[tokenId]]\n }\n const greater = (inputs[2] === 'Greater')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, tokenWeapons, buttons, greater)\n }\n}\n\nasync function createEffect (tokens, tokenWeapons, choice, greater) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Smite')\n const effectIcon = baseEffect.icon\n const effectId = baseEffect.id\n let changeValue = (choice === 'raise' ? '+4' : '+2')\n if (greater) {\n changeValue = (choice === 'raise' ? '+6' : '+4')\n }\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}}[system.damage]`\n if (!weaponId) {\n continue\n }\n const effectName = `${choice === 'raise' ? 'major' : 'minor'} Smite${greater ? '(greater)' : ''} (${weaponName})`\n const changes = [\n {\n key: changeKey,\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: changeValue,\n priority: 0\n }\n ]\n const mutate = swadeMBHelpers.createMutationWithEffect(\n effectIcon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.1GnCpp1vjEucgNGk"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677548889704,"modifiedTime":1678124792933,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"C1vGk7AKQDpcvKyP","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Deflection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/defensive/shield-barrier-deflect-teal.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/defensive/shield-barrier-deflect-teal.webp'\n let effectName = 'Deflection'\n if (choice === 'raise') {\n effectName = `${effectName} (all)`\n } else {\n effectName = `${effectName} (${choice})`\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677645552357,"modifiedTime":1678124792933,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"HYTiftQW0pwwOQGH","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Glow","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/light/explosion-star-blue-large.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Glow',\n content: `Apply Glow to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/light/explosion-star-blue-large.webp'\n const effectName = 'Glow'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.5,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'starlight'\n },\n bright: 0,\n color: '#0f3fff',\n coloration: 1,\n contrast: 0,\n dim: 0.5,\n luminosity: 0.5,\n saturation: 0,\n shadows: 0\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677704975699,"modifiedTime":1678124792933,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"JcZ9kxBZJpw8KLQ6","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Confusion","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/control/hypnosis-mesmerism-swirl.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Confusion',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Confusion' },\n { type: 'info', label: `Apply Confusion to ${tokenList}` },\n { type: 'checkbox', label: 'Greater (adds shaken)', options: false }\n ],\n buttons: [\n { label: 'Distracted', value: 'distracted' },\n { label: 'Vulnerable', value: 'vulnerable' },\n { label: 'Raise (both)', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n const greater = (inputs[2] === 'Greater (adds shaken)')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, buttons, greater)\n }\n}\n\nfunction getStatus (label, name) {\n const effect = JSON.parse(JSON.stringify(\n CONFIG.statusEffects.find(se => se.label === label)))\n effect.flags.core = { statusId: effect.id }\n effect.id = name\n return effect\n}\n\nasync function createEffect (tokens, choice, greater) {\n const effects = []\n if (choice === 'distracted' || choice === 'raise') {\n effects.push(getStatus('SWADE.Distr', 'Distracted'))\n }\n if (choice === 'vulnerable' || choice === 'raise') {\n effects.push(getStatus('SWADE.Vuln', 'Vulnerable'))\n }\n if (greater) {\n effects.push(getStatus('SWADE.Shaken', 'Shaken'))\n }\n for (const token of tokens) {\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Confusion')\n const mutate = {\n embedded: { ActiveEffect: {} }\n }\n for (const effect of effects) {\n mutate.embedded.ActiveEffect[effect.id] = effect\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678082334572,"modifiedTime":1678124792864,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"L2IstecV7ivcrgUI","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Shroud","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/perception/silhouette-stealth-shadow.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Shroud',\n content: `Apply Shroud to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/perception/silhouette-stealth-shadow.webp'\n const effectName = 'Shroud'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.1,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'roiling'\n },\n bright: 0,\n color: null,\n coloration: 0,\n contrast: 0,\n dim: 0.1,\n luminosity: -0.15,\n saturation: 0,\n shadows: 0.25\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677649631598,"modifiedTime":1678124792933,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"QpillIBvZmuHeuTV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Summon","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/symbols/runes-star-orange.webp","scope":"global","command":"const ACTORFOLDER = 'Summonables'\nconst SUMMONICON = 'icons/magic/symbols/runes-star-orange.webp'\n\nswadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const token = tokens[0]\n const tokenList = token.name\n const folder = swadeMBHelpers.getActorFolderByPath(ACTORFOLDER)\n const actors = swadeMBHelpers.getActorsInFolder(folder)\n const menuOptions = {\n title: 'Summon Creature',\n defaultButton: 'cancel',\n options: {}\n }\n const menuData = {\n inputs: [\n { type: 'header', label: 'Summon Creature' },\n { type: 'info', label: `${tokenList} is summoning` },\n {\n type: 'select',\n label: 'Ally to summon',\n options: Object.keys(actors).sort().map(k => { return { value: actors[k].id, html: k } })\n },\n { type: 'number', label: 'Number to spawn (+half base cost per)', options: 1 }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const summonData = {\n raise: (buttons === 'raise'),\n actorId: inputs[2],\n number: inputs[3]\n }\n summonData.actor = game.actors.get(summonData.actorId)\n summonData.actorName = summonData.actor.name\n summonData.icon = summonData.actor.prototypeToken.texture.src\n summonData.token = summonData.actor.prototypeToken\n\n doWork(summonData, token)\n }\n}\n\nasync function doWork (summonData, token) {\n console.log('Summon ', token, summonData)\n const effectName = `Summoned ${summonData.actorName} (${summonData.number})`\n const tokenEffectMutation = swadeMBHelpers.createMutationWithEffect(SUMMONICON, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, tokenEffectMutation, {}, mutateOptions)\n\n const spawnOptions = {\n controllingActor: token.actor,\n duplicates: summonData.number,\n comparisonKeys: { ActiveEffect: 'label' },\n crosshairs: {\n size: 1,\n icon: summonData.icon,\n label: `Summon ${summonData.actorName}`,\n drawOutline: false,\n rememberControlled: true\n }\n }\n const spawnMutation = {\n token: {\n actorLink: false,\n name: `${token.name}'s ${summonData.token.name}`\n }\n }\n await warpgate.spawn(summonData.actorName, spawnMutation, {}, spawnOptions)\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677996503821,"modifiedTime":1678124792933,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"RV09eJi9iG5bfupo","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Protection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_protection.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Protection')\n const changes = [\n {\n key: 'system.stats.toughness.armor',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE,\n value: 2,\n priority: 0\n }\n ]\n let effectName = 'minor Protection'\n if (choice === 'raise') {\n changes[0].key = 'system.stats.toughness.value'\n effectName = 'major Protection'\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(\n baseEffect.icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677630174987,"modifiedTime":1678124792934,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"YETsNWOWfIxyLPdC","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Lingering Damage","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/acid/dissolve-arm-flesh.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Lingering Damage',\n content: `Apply Lingering Damage to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'Ok', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok') {\n await createEffect(tokens)\n }\n}\n\nasync function createEffect (tokens) {\n const icon = 'icons/magic/acid/dissolve-arm-flesh.webp'\n const effectName = 'Lingering Damage'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 1, [])\n mutate.embedded.ActiveEffect['Lingering Damage'].flags.swade.expiration =\n CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnPrompt\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677800587229,"modifiedTime":1678124792934,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"txJBrqgVNO3jpvFG","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Hinder","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/movement/abstract-ribbons-red-orange.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hinder',\n content: `Apply Hinder to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/movement/abstract-ribbons-red-orange.webp'\n const effectName = 'Hinder'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: -2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678124792934,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"uvHTdYUn5l3Z1rAV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Hurry","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/skills/movement/feet-winged-boots-blue.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hurry',\n content: `Apply Hurry to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/skills/movement/feet-winged-boots-blue.webp'\n const effectName = 'Hurry'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: 2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678124792934,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"yG1ZQO30ZlntYJp7","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -- 2.30.2 From 9607e07fdc3d4883ac53195953e88233aac551a3 Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Mon, 6 Mar 2023 22:21:36 -0600 Subject: [PATCH 3/7] link protection and smite to system effects --- CHANGELOG.md | 4 ++++ macros/protection.js | 1 + macros/smite.js | 2 +- packs/effect-macros.db | 22 +++++++++++----------- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c224f18..6d73d93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Confusion effect macro +### Changed + +- Protection and Smite macros now linked to swade system effects + ## 0.9.0 - Initial 'public' release diff --git a/macros/protection.js b/macros/protection.js index bd94d27..d35e5ad 100644 --- a/macros/protection.js +++ b/macros/protection.js @@ -38,6 +38,7 @@ async function createEffect (tokens, choice) { for (const token of tokens) { const mutate = swadeMBHelpers.createMutationWithEffect( baseEffect.icon, effectName, 5, changes) + mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id } const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName) await warpgate.mutate(token.document, mutate, {}, mutateOptions) } diff --git a/macros/smite.js b/macros/smite.js index 4fb5453..41402d0 100644 --- a/macros/smite.js +++ b/macros/smite.js @@ -45,7 +45,6 @@ async function main (tokens) { async function createEffect (tokens, tokenWeapons, choice, greater) { const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Smite') const effectIcon = baseEffect.icon - const effectId = baseEffect.id let changeValue = (choice === 'raise' ? '+4' : '+2') if (greater) { changeValue = (choice === 'raise' ? '+6' : '+4') @@ -68,6 +67,7 @@ async function createEffect (tokens, tokenWeapons, choice, greater) { ] const mutate = swadeMBHelpers.createMutationWithEffect( effectIcon, effectName, 5, changes) + mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id } const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName) await warpgate.mutate(token.document, mutate, {}, mutateOptions) } diff --git a/packs/effect-macros.db b/packs/effect-macros.db index 1dd5883..18ea3e3 100644 --- a/packs/effect-macros.db +++ b/packs/effect-macros.db @@ -1,11 +1,11 @@ -{"name":"Boost/Lower Trait","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/life/cross-embers-glow-yellow-purple.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n let traitOptions = [\n 'Agility', 'Smarts', 'Spirit', 'Strength', 'Vigor'\n ]\n const allSkills = []\n const traits = {}\n for (const traitName of traitOptions) {\n const lower = traitName.toLowerCase()\n traits[traitName] = {\n name: traitName,\n type: 'attribute',\n modkey: `system.attributes.${lower}.die.modifier`,\n diekey: `system.attributes.${lower}.die.sides`\n }\n }\n\n const tokenList = tokens.map(t => t.name).join(', ')\n for (const token of tokens) {\n const skills = token.actor.items.filter(item => item.type === 'skill')\n for (const skill of skills) {\n const name = skill.name\n traits[name] = {\n type: 'skill',\n name,\n modkey: `@Skill{${name}}[system.die.modifier]`,\n diekey: `@Skill{${name}}[system.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\n const menuOptions = {\n title: 'Boost/Lower Trait',\n defaultButton: 'Cancel',\n options: {}\n }\n const 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: ['isBoost', true] },\n { type: 'radio', label: 'Lower', options: ['isBoost', false] },\n { type: 'checkbox', label: 'Greater', options: false },\n { type: 'checkbox', label: 'Strong (lower only)', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n action: buttons,\n name: inputs[2],\n trait: traits[inputs[2]],\n direction: inputs[4] || inputs[5],\n greater: inputs[6],\n strong: inputs[7]\n }\n createEffect(tokens, options)\n }\n}\n\nconst UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp'\nconst DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp'\n\nasync function createEffect (tokens, options) {\n const raise = (options.action === 'raise')\n const icon = (options.direction === 'Boost' ? UPICON : DOWNICON)\n let namePart = `${options.direction} ${options.trait.name}`\n const mode = CONST.ACTIVE_EFFECT_MODES.ADD\n const mods = []\n if (options.strong && options.direction === 'Lower') {\n mods.push('strong')\n }\n if (options.greater) {\n mods.push('greater')\n }\n if (mods.length > 0) {\n namePart = `${namePart} (${mods.join(', ')})`\n }\n const minorEffect = swadeMBHelpers.createEffectDocument(\n icon, `minor ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n const majorEffect = swadeMBHelpers.createEffectDocument(\n icon, `major ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n if (options.direction === 'Lower' && options.greater === 'Greater') {\n minorEffect.changes.push({\n key: options.trait.modkey,\n mode,\n value: '-2',\n priority: 0\n })\n }\n const mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n }\n mutate.embedded.ActiveEffect[minorEffect.id] = minorEffect\n if (raise) {\n mutate.embedded.ActiveEffect[majorEffect.id] = majorEffect\n }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(namePart)\n for (const token of tokens) {\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677458254287,"modifiedTime":1678124792933,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"1AqIFHAcX5TRdE8X","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Smite","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_smite.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Smite',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Smite' },\n { type: 'info', label: `Apply Smite to ${tokenList}` },\n { type: 'checkbox', label: 'Greater', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with Raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const tokenWeapons = {}\n let index = 2\n for (const token of tokens) {\n index += 2\n tokenWeapons[token.id] = index\n menuData.inputs.push({ type: 'info', label: `

${token.name}

` })\n const weapons = token.actor.items.filter(i => i.type === 'weapon').map(\n i => { return { value: i.name, html: i.name } })\n weapons.unshift({ value: '', html: 'None' })\n menuData.inputs.push({ type: 'select', label: token.name, options: weapons })\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n for (const tokenId in tokenWeapons) {\n tokenWeapons[tokenId] = inputs[tokenWeapons[tokenId]]\n }\n const greater = (inputs[2] === 'Greater')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, tokenWeapons, buttons, greater)\n }\n}\n\nasync function createEffect (tokens, tokenWeapons, choice, greater) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Smite')\n const effectIcon = baseEffect.icon\n const effectId = baseEffect.id\n let changeValue = (choice === 'raise' ? '+4' : '+2')\n if (greater) {\n changeValue = (choice === 'raise' ? '+6' : '+4')\n }\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}}[system.damage]`\n if (!weaponId) {\n continue\n }\n const effectName = `${choice === 'raise' ? 'major' : 'minor'} Smite${greater ? '(greater)' : ''} (${weaponName})`\n const changes = [\n {\n key: changeKey,\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: changeValue,\n priority: 0\n }\n ]\n const mutate = swadeMBHelpers.createMutationWithEffect(\n effectIcon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.1GnCpp1vjEucgNGk"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677548889704,"modifiedTime":1678124792933,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"C1vGk7AKQDpcvKyP","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Deflection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/defensive/shield-barrier-deflect-teal.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/defensive/shield-barrier-deflect-teal.webp'\n let effectName = 'Deflection'\n if (choice === 'raise') {\n effectName = `${effectName} (all)`\n } else {\n effectName = `${effectName} (${choice})`\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677645552357,"modifiedTime":1678124792933,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"HYTiftQW0pwwOQGH","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Glow","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/light/explosion-star-blue-large.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Glow',\n content: `Apply Glow to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/light/explosion-star-blue-large.webp'\n const effectName = 'Glow'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.5,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'starlight'\n },\n bright: 0,\n color: '#0f3fff',\n coloration: 1,\n contrast: 0,\n dim: 0.5,\n luminosity: 0.5,\n saturation: 0,\n shadows: 0\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677704975699,"modifiedTime":1678124792933,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"JcZ9kxBZJpw8KLQ6","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Confusion","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/control/hypnosis-mesmerism-swirl.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Confusion',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Confusion' },\n { type: 'info', label: `Apply Confusion to ${tokenList}` },\n { type: 'checkbox', label: 'Greater (adds shaken)', options: false }\n ],\n buttons: [\n { label: 'Distracted', value: 'distracted' },\n { label: 'Vulnerable', value: 'vulnerable' },\n { label: 'Raise (both)', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n const greater = (inputs[2] === 'Greater (adds shaken)')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, buttons, greater)\n }\n}\n\nfunction getStatus (label, name) {\n const effect = JSON.parse(JSON.stringify(\n CONFIG.statusEffects.find(se => se.label === label)))\n effect.flags.core = { statusId: effect.id }\n effect.id = name\n return effect\n}\n\nasync function createEffect (tokens, choice, greater) {\n const effects = []\n if (choice === 'distracted' || choice === 'raise') {\n effects.push(getStatus('SWADE.Distr', 'Distracted'))\n }\n if (choice === 'vulnerable' || choice === 'raise') {\n effects.push(getStatus('SWADE.Vuln', 'Vulnerable'))\n }\n if (greater) {\n effects.push(getStatus('SWADE.Shaken', 'Shaken'))\n }\n for (const token of tokens) {\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Confusion')\n const mutate = {\n embedded: { ActiveEffect: {} }\n }\n for (const effect of effects) {\n mutate.embedded.ActiveEffect[effect.id] = effect\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678082334572,"modifiedTime":1678124792864,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"L2IstecV7ivcrgUI","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Shroud","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/perception/silhouette-stealth-shadow.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Shroud',\n content: `Apply Shroud to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/perception/silhouette-stealth-shadow.webp'\n const effectName = 'Shroud'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.1,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'roiling'\n },\n bright: 0,\n color: null,\n coloration: 0,\n contrast: 0,\n dim: 0.1,\n luminosity: -0.15,\n saturation: 0,\n shadows: 0.25\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677649631598,"modifiedTime":1678124792933,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"QpillIBvZmuHeuTV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Summon","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/symbols/runes-star-orange.webp","scope":"global","command":"const ACTORFOLDER = 'Summonables'\nconst SUMMONICON = 'icons/magic/symbols/runes-star-orange.webp'\n\nswadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const token = tokens[0]\n const tokenList = token.name\n const folder = swadeMBHelpers.getActorFolderByPath(ACTORFOLDER)\n const actors = swadeMBHelpers.getActorsInFolder(folder)\n const menuOptions = {\n title: 'Summon Creature',\n defaultButton: 'cancel',\n options: {}\n }\n const menuData = {\n inputs: [\n { type: 'header', label: 'Summon Creature' },\n { type: 'info', label: `${tokenList} is summoning` },\n {\n type: 'select',\n label: 'Ally to summon',\n options: Object.keys(actors).sort().map(k => { return { value: actors[k].id, html: k } })\n },\n { type: 'number', label: 'Number to spawn (+half base cost per)', options: 1 }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const summonData = {\n raise: (buttons === 'raise'),\n actorId: inputs[2],\n number: inputs[3]\n }\n summonData.actor = game.actors.get(summonData.actorId)\n summonData.actorName = summonData.actor.name\n summonData.icon = summonData.actor.prototypeToken.texture.src\n summonData.token = summonData.actor.prototypeToken\n\n doWork(summonData, token)\n }\n}\n\nasync function doWork (summonData, token) {\n console.log('Summon ', token, summonData)\n const effectName = `Summoned ${summonData.actorName} (${summonData.number})`\n const tokenEffectMutation = swadeMBHelpers.createMutationWithEffect(SUMMONICON, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, tokenEffectMutation, {}, mutateOptions)\n\n const spawnOptions = {\n controllingActor: token.actor,\n duplicates: summonData.number,\n comparisonKeys: { ActiveEffect: 'label' },\n crosshairs: {\n size: 1,\n icon: summonData.icon,\n label: `Summon ${summonData.actorName}`,\n drawOutline: false,\n rememberControlled: true\n }\n }\n const spawnMutation = {\n token: {\n actorLink: false,\n name: `${token.name}'s ${summonData.token.name}`\n }\n }\n await warpgate.spawn(summonData.actorName, spawnMutation, {}, spawnOptions)\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677996503821,"modifiedTime":1678124792933,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"RV09eJi9iG5bfupo","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Protection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_protection.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Protection')\n const changes = [\n {\n key: 'system.stats.toughness.armor',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE,\n value: 2,\n priority: 0\n }\n ]\n let effectName = 'minor Protection'\n if (choice === 'raise') {\n changes[0].key = 'system.stats.toughness.value'\n effectName = 'major Protection'\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(\n baseEffect.icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677630174987,"modifiedTime":1678124792934,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"YETsNWOWfIxyLPdC","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Lingering Damage","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/acid/dissolve-arm-flesh.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Lingering Damage',\n content: `Apply Lingering Damage to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'Ok', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok') {\n await createEffect(tokens)\n }\n}\n\nasync function createEffect (tokens) {\n const icon = 'icons/magic/acid/dissolve-arm-flesh.webp'\n const effectName = 'Lingering Damage'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 1, [])\n mutate.embedded.ActiveEffect['Lingering Damage'].flags.swade.expiration =\n CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnPrompt\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677800587229,"modifiedTime":1678124792934,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"txJBrqgVNO3jpvFG","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Hinder","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/movement/abstract-ribbons-red-orange.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hinder',\n content: `Apply Hinder to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/movement/abstract-ribbons-red-orange.webp'\n const effectName = 'Hinder'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: -2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678124792934,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"uvHTdYUn5l3Z1rAV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Hurry","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/skills/movement/feet-winged-boots-blue.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hurry',\n content: `Apply Hurry to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/skills/movement/feet-winged-boots-blue.webp'\n const effectName = 'Hurry'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: 2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678124792934,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"yG1ZQO30ZlntYJp7","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Boost/Lower Trait","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/life/cross-embers-glow-yellow-purple.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n let traitOptions = [\n 'Agility', 'Smarts', 'Spirit', 'Strength', 'Vigor'\n ]\n const allSkills = []\n const traits = {}\n for (const traitName of traitOptions) {\n const lower = traitName.toLowerCase()\n traits[traitName] = {\n name: traitName,\n type: 'attribute',\n modkey: `system.attributes.${lower}.die.modifier`,\n diekey: `system.attributes.${lower}.die.sides`\n }\n }\n\n const tokenList = tokens.map(t => t.name).join(', ')\n for (const token of tokens) {\n const skills = token.actor.items.filter(item => item.type === 'skill')\n for (const skill of skills) {\n const name = skill.name\n traits[name] = {\n type: 'skill',\n name,\n modkey: `@Skill{${name}}[system.die.modifier]`,\n diekey: `@Skill{${name}}[system.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\n const menuOptions = {\n title: 'Boost/Lower Trait',\n defaultButton: 'Cancel',\n options: {}\n }\n const 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: ['isBoost', true] },\n { type: 'radio', label: 'Lower', options: ['isBoost', false] },\n { type: 'checkbox', label: 'Greater', options: false },\n { type: 'checkbox', label: 'Strong (lower only)', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n action: buttons,\n name: inputs[2],\n trait: traits[inputs[2]],\n direction: inputs[4] || inputs[5],\n greater: inputs[6],\n strong: inputs[7]\n }\n createEffect(tokens, options)\n }\n}\n\nconst UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp'\nconst DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp'\n\nasync function createEffect (tokens, options) {\n const raise = (options.action === 'raise')\n const icon = (options.direction === 'Boost' ? UPICON : DOWNICON)\n let namePart = `${options.direction} ${options.trait.name}`\n const mode = CONST.ACTIVE_EFFECT_MODES.ADD\n const mods = []\n if (options.strong && options.direction === 'Lower') {\n mods.push('strong')\n }\n if (options.greater) {\n mods.push('greater')\n }\n if (mods.length > 0) {\n namePart = `${namePart} (${mods.join(', ')})`\n }\n const minorEffect = swadeMBHelpers.createEffectDocument(\n icon, `minor ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n const majorEffect = swadeMBHelpers.createEffectDocument(\n icon, `major ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n if (options.direction === 'Lower' && options.greater === 'Greater') {\n minorEffect.changes.push({\n key: options.trait.modkey,\n mode,\n value: '-2',\n priority: 0\n })\n }\n const mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n }\n mutate.embedded.ActiveEffect[minorEffect.id] = minorEffect\n if (raise) {\n mutate.embedded.ActiveEffect[majorEffect.id] = majorEffect\n }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(namePart)\n for (const token of tokens) {\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677458254287,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"1AqIFHAcX5TRdE8X","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Smite","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_smite.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Smite',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Smite' },\n { type: 'info', label: `Apply Smite to ${tokenList}` },\n { type: 'checkbox', label: 'Greater', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with Raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const tokenWeapons = {}\n let index = 2\n for (const token of tokens) {\n index += 2\n tokenWeapons[token.id] = index\n menuData.inputs.push({ type: 'info', label: `

${token.name}

` })\n const weapons = token.actor.items.filter(i => i.type === 'weapon').map(\n i => { return { value: i.name, html: i.name } })\n weapons.unshift({ value: '', html: 'None' })\n menuData.inputs.push({ type: 'select', label: token.name, options: weapons })\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n for (const tokenId in tokenWeapons) {\n tokenWeapons[tokenId] = inputs[tokenWeapons[tokenId]]\n }\n const greater = (inputs[2] === 'Greater')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, tokenWeapons, buttons, greater)\n }\n}\n\nasync function createEffect (tokens, tokenWeapons, choice, greater) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Smite')\n const effectIcon = baseEffect.icon\n let changeValue = (choice === 'raise' ? '+4' : '+2')\n if (greater) {\n changeValue = (choice === 'raise' ? '+6' : '+4')\n }\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}}[system.damage]`\n if (!weaponId) {\n continue\n }\n const effectName = `${choice === 'raise' ? 'major' : 'minor'} Smite${greater ? '(greater)' : ''} (${weaponName})`\n const changes = [\n {\n key: changeKey,\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: changeValue,\n priority: 0\n }\n ]\n const mutate = swadeMBHelpers.createMutationWithEffect(\n effectIcon, effectName, 5, changes)\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.1GnCpp1vjEucgNGk"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677548889704,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"C1vGk7AKQDpcvKyP","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Deflection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/defensive/shield-barrier-deflect-teal.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/defensive/shield-barrier-deflect-teal.webp'\n let effectName = 'Deflection'\n if (choice === 'raise') {\n effectName = `${effectName} (all)`\n } else {\n effectName = `${effectName} (${choice})`\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677645552357,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"HYTiftQW0pwwOQGH","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Glow","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/light/explosion-star-blue-large.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Glow',\n content: `Apply Glow to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/light/explosion-star-blue-large.webp'\n const effectName = 'Glow'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.5,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'starlight'\n },\n bright: 0,\n color: '#0f3fff',\n coloration: 1,\n contrast: 0,\n dim: 0.5,\n luminosity: 0.5,\n saturation: 0,\n shadows: 0\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677704975699,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"JcZ9kxBZJpw8KLQ6","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Confusion","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/control/hypnosis-mesmerism-swirl.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Confusion',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Confusion' },\n { type: 'info', label: `Apply Confusion to ${tokenList}` },\n { type: 'checkbox', label: 'Greater (adds shaken)', options: false }\n ],\n buttons: [\n { label: 'Distracted', value: 'distracted' },\n { label: 'Vulnerable', value: 'vulnerable' },\n { label: 'Raise (both)', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n const greater = (inputs[2] === 'Greater (adds shaken)')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, buttons, greater)\n }\n}\n\nfunction getStatus (label, name) {\n const effect = JSON.parse(JSON.stringify(\n CONFIG.statusEffects.find(se => se.label === label)))\n effect.flags.core = { statusId: effect.id }\n effect.id = name\n return effect\n}\n\nasync function createEffect (tokens, choice, greater) {\n const effects = []\n if (choice === 'distracted' || choice === 'raise') {\n effects.push(getStatus('SWADE.Distr', 'Distracted'))\n }\n if (choice === 'vulnerable' || choice === 'raise') {\n effects.push(getStatus('SWADE.Vuln', 'Vulnerable'))\n }\n if (greater) {\n effects.push(getStatus('SWADE.Shaken', 'Shaken'))\n }\n for (const token of tokens) {\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Confusion')\n const mutate = {\n embedded: { ActiveEffect: {} }\n }\n for (const effect of effects) {\n mutate.embedded.ActiveEffect[effect.id] = effect\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678082334572,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"L2IstecV7ivcrgUI","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Shroud","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/perception/silhouette-stealth-shadow.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Shroud',\n content: `Apply Shroud to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/perception/silhouette-stealth-shadow.webp'\n const effectName = 'Shroud'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.1,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'roiling'\n },\n bright: 0,\n color: null,\n coloration: 0,\n contrast: 0,\n dim: 0.1,\n luminosity: -0.15,\n saturation: 0,\n shadows: 0.25\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677649631598,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"QpillIBvZmuHeuTV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Summon","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/symbols/runes-star-orange.webp","scope":"global","command":"const ACTORFOLDER = 'Summonables'\nconst SUMMONICON = 'icons/magic/symbols/runes-star-orange.webp'\n\nswadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const token = tokens[0]\n const tokenList = token.name\n const folder = swadeMBHelpers.getActorFolderByPath(ACTORFOLDER)\n const actors = swadeMBHelpers.getActorsInFolder(folder)\n const menuOptions = {\n title: 'Summon Creature',\n defaultButton: 'cancel',\n options: {}\n }\n const menuData = {\n inputs: [\n { type: 'header', label: 'Summon Creature' },\n { type: 'info', label: `${tokenList} is summoning` },\n {\n type: 'select',\n label: 'Ally to summon',\n options: Object.keys(actors).sort().map(k => { return { value: actors[k].id, html: k } })\n },\n { type: 'number', label: 'Number to spawn (+half base cost per)', options: 1 }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const summonData = {\n raise: (buttons === 'raise'),\n actorId: inputs[2],\n number: inputs[3]\n }\n summonData.actor = game.actors.get(summonData.actorId)\n summonData.actorName = summonData.actor.name\n summonData.icon = summonData.actor.prototypeToken.texture.src\n summonData.token = summonData.actor.prototypeToken\n\n doWork(summonData, token)\n }\n}\n\nasync function doWork (summonData, token) {\n console.log('Summon ', token, summonData)\n const effectName = `Summoned ${summonData.actorName} (${summonData.number})`\n const tokenEffectMutation = swadeMBHelpers.createMutationWithEffect(SUMMONICON, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, tokenEffectMutation, {}, mutateOptions)\n\n const spawnOptions = {\n controllingActor: token.actor,\n duplicates: summonData.number,\n comparisonKeys: { ActiveEffect: 'label' },\n crosshairs: {\n size: 1,\n icon: summonData.icon,\n label: `Summon ${summonData.actorName}`,\n drawOutline: false,\n rememberControlled: true\n }\n }\n const spawnMutation = {\n token: {\n actorLink: false,\n name: `${token.name}'s ${summonData.token.name}`\n }\n }\n await warpgate.spawn(summonData.actorName, spawnMutation, {}, spawnOptions)\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677996503821,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"RV09eJi9iG5bfupo","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Protection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_protection.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Protection')\n const changes = [\n {\n key: 'system.stats.toughness.armor',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE,\n value: 2,\n priority: 0\n }\n ]\n let effectName = 'minor Protection'\n if (choice === 'raise') {\n changes[0].key = 'system.stats.toughness.value'\n effectName = 'major Protection'\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(\n baseEffect.icon, effectName, 5, changes)\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677630174987,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"YETsNWOWfIxyLPdC","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Lingering Damage","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/acid/dissolve-arm-flesh.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Lingering Damage',\n content: `Apply Lingering Damage to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'Ok', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok') {\n await createEffect(tokens)\n }\n}\n\nasync function createEffect (tokens) {\n const icon = 'icons/magic/acid/dissolve-arm-flesh.webp'\n const effectName = 'Lingering Damage'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 1, [])\n mutate.embedded.ActiveEffect['Lingering Damage'].flags.swade.expiration =\n CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnPrompt\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677800587229,"modifiedTime":1678162795694,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"txJBrqgVNO3jpvFG","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Hinder","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/movement/abstract-ribbons-red-orange.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hinder',\n content: `Apply Hinder to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/movement/abstract-ribbons-red-orange.webp'\n const effectName = 'Hinder'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: -2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678162795694,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"uvHTdYUn5l3Z1rAV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Hurry","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/skills/movement/feet-winged-boots-blue.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hurry',\n content: `Apply Hurry to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/skills/movement/feet-winged-boots-blue.webp'\n const effectName = 'Hurry'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: 2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678162795694,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"yG1ZQO30ZlntYJp7","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -- 2.30.2 From 18e059a785bb1c282f728fa270dc37b829eadc94 Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Mon, 6 Mar 2023 23:06:51 -0600 Subject: [PATCH 4/7] Add entangle effect closes #11 --- CHANGELOG.md | 1 + macros/entangle.js | 74 ++++++++++++++++++++++++++++++++++++++++++ packs/effect-macros.db | 12 +++++++ 3 files changed, 87 insertions(+) create mode 100644 macros/entangle.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d73d93..77cac74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Confusion effect macro +- Entangle effect macro ### Changed diff --git a/macros/entangle.js b/macros/entangle.js new file mode 100644 index 0000000..0f47916 --- /dev/null +++ b/macros/entangle.js @@ -0,0 +1,74 @@ +swadeMBHelpers.runOnTargetOrSelectedTokens(main) + +async function main (tokens) { + const tokenList = tokens.map(t => t.name).join(', ') + const menuOptions = { + title: 'Entangle', + defaultButton: 'Cancel', + options: {} + } + + const menuData = { + inputs: [ + { type: 'header', label: 'Entangle' }, + { type: 'info', label: `Apply Entangle to ${tokenList}` }, + { type: 'radio', label: 'Not Damaging', options: ['dmg', true] }, + { type: 'radio', label: 'Damaging', options: ['dmg', false] }, + { type: 'radio', label: 'Deadly', options: ['dmg', false] }, + { type: 'checkbox', label: 'Tough', options: false } + ], + buttons: [ + { label: 'Entangled', value: 'apply' }, + { label: 'Bound (raise)', value: 'raise' }, + { label: 'Cancel', value: 'cancel' } + ] + } + + const { buttons, inputs } = await warpgate.menu(menuData, menuOptions) + if (buttons && buttons !== 'cancel') { + const options = { + apply: (buttons === 'raise' ? 'bound' : 'entangled'), + damage: (inputs[3] ? '2d4' : (inputs[4] ? '2d6' : null)), + tough: (!!inputs[5]) + } + await createEffect(tokens, options) + } +} + +function getStatus (label, name) { + const effect = JSON.parse(JSON.stringify( + CONFIG.statusEffects.find(se => se.label === label))) + effect.label = name + if (!effect.flags) { + effect.flags = {} + } + effect.flags.core = { statusId: effect.id } + effect.id = name + return effect +} + +async function createEffect (tokens, options) { + const effectSearch = (options.apply === 'bound' ? 'SWADE.Bound' : 'SWADE.Entangled') + const effectName = (options.apply === 'bound' ? 'Bound' : 'Entangled') + const effect = getStatus(effectSearch, effectName) + const extraIcon = 'icons/magic/nature/root-vine-barrier-wall-brown.webp' + const extraEffect = swadeMBHelpers.createEffectDocument(extraIcon, 'Entangle Modifier', 1, []) + + if (options.damage) { + extraEffect.id = `${extraEffect.id} - ${options.damage} dmg` + extraEffect.label = `${extraEffect.label} - ${options.damage} dmg` + } + if (options.tough) { + extraEffect.id = `Tough ${extraEffect.id}` + extraEffect.label = `Tough ${extraEffect.label}` + } + for (const token of tokens) { + const mutateOptions = swadeMBHelpers.defaultMutationOptions('Entangle') + const mutate = { embedded: { ActiveEffect: {} } } + mutate.embedded.ActiveEffect[effect.id] = effect + if (options.damage || options.tough) { + mutate.embedded.ActiveEffect[extraEffect.id] = extraEffect + } + await warpgate.mutate(token.document, mutate, {}, mutateOptions) + } +} diff --git a/packs/effect-macros.db b/packs/effect-macros.db index 18ea3e3..317ab02 100644 --- a/packs/effect-macros.db +++ b/packs/effect-macros.db @@ -9,3 +9,15 @@ {"name":"Lingering Damage","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/acid/dissolve-arm-flesh.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Lingering Damage',\n content: `Apply Lingering Damage to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'Ok', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok') {\n await createEffect(tokens)\n }\n}\n\nasync function createEffect (tokens) {\n const icon = 'icons/magic/acid/dissolve-arm-flesh.webp'\n const effectName = 'Lingering Damage'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 1, [])\n mutate.embedded.ActiveEffect['Lingering Damage'].flags.swade.expiration =\n CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnPrompt\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677800587229,"modifiedTime":1678162795694,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"txJBrqgVNO3jpvFG","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} {"name":"Hinder","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/movement/abstract-ribbons-red-orange.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hinder',\n content: `Apply Hinder to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/movement/abstract-ribbons-red-orange.webp'\n const effectName = 'Hinder'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: -2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678162795694,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"uvHTdYUn5l3Z1rAV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} {"name":"Hurry","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/skills/movement/feet-winged-boots-blue.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hurry',\n content: `Apply Hurry to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/skills/movement/feet-winged-boots-blue.webp'\n const effectName = 'Hurry'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: 2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678162795694,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"yG1ZQO30ZlntYJp7","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Entangle","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/nature/root-vine-barrier-wall-brown.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Entangle',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Entangle' },\n { type: 'info', label: `Apply Entangle to ${tokenList}` },\n { type: 'radio', label: 'Not Damaging', options: ['dmg', true] },\n { type: 'radio', label: 'Damaging', options: ['dmg', false] },\n { type: 'radio', label: 'Deadly', options: ['dmg', false] },\n { type: 'checkbox', label: 'Tough', options: false }\n ],\n buttons: [\n { label: 'Entangled', value: 'apply' },\n { label: 'Bound (raise)', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n apply: (buttons === 'raise' ? 'bound' : 'entangled'),\n damage: (inputs[3] ? '2d4' : (inputs[4] ? '2d6' : null)),\n tough: (!!inputs[5])\n }\n await createEffect(tokens, options)\n }\n}\n\nfunction getStatus (label, name) {\n const effect = JSON.parse(JSON.stringify(\n CONFIG.statusEffects.find(se => se.label === label)))\n effect.label = name\n if (!effect.flags) {\n effect.flags = {}\n }\n effect.flags.core = { statusId: effect.id }\n effect.id = name\n return effect\n}\n\nasync function createEffect (tokens, options) {\n const effectSearch = (options.apply === 'bound' ? 'SWADE.Bound' : 'SWADE.Entangled')\n const effectName = (options.apply === 'bound' ? 'Bound' : 'Entangled')\n const effect = getStatus(effectSearch, effectName)\n const extraIcon = 'icons/magic/nature/root-vine-barrier-wall-brown.webp'\n const extraEffect = swadeMBHelpers.createEffectDocument(extraIcon, 'Entangle Modifier', 1, [])\n\n if (options.damage) {\n extraEffect.id = `${extraEffect.id} - ${options.damage} dmg`\n extraEffect.label = `${extraEffect.label} - ${options.damage} dmg`\n }\n if (options.tough) {\n extraEffect.id = `Tough ${extraEffect.id}`\n extraEffect.label = `Tough ${extraEffect.label}`\n }\n for (const token of tokens) {\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Entangle')\n const mutate = { embedded: { ActiveEffect: {} } }\n mutate.embedded.ActiveEffect[effect.id] = effect\n if (options.damage || options.tough) {\n mutate.embedded.ActiveEffect[extraEffect.id] = extraEffect\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.2TOeRNCJT3T2px8D"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678164427219,"modifiedTime":1678165566624,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"2TOeRNCJT3T2px8D","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Boost/Lower Trait","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/life/cross-embers-glow-yellow-purple.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n let traitOptions = [\n 'Agility', 'Smarts', 'Spirit', 'Strength', 'Vigor'\n ]\n const allSkills = []\n const traits = {}\n for (const traitName of traitOptions) {\n const lower = traitName.toLowerCase()\n traits[traitName] = {\n name: traitName,\n type: 'attribute',\n modkey: `system.attributes.${lower}.die.modifier`,\n diekey: `system.attributes.${lower}.die.sides`\n }\n }\n\n const tokenList = tokens.map(t => t.name).join(', ')\n for (const token of tokens) {\n const skills = token.actor.items.filter(item => item.type === 'skill')\n for (const skill of skills) {\n const name = skill.name\n traits[name] = {\n type: 'skill',\n name,\n modkey: `@Skill{${name}}[system.die.modifier]`,\n diekey: `@Skill{${name}}[system.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\n const menuOptions = {\n title: 'Boost/Lower Trait',\n defaultButton: 'Cancel',\n options: {}\n }\n const 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: ['isBoost', true] },\n { type: 'radio', label: 'Lower', options: ['isBoost', false] },\n { type: 'checkbox', label: 'Greater', options: false },\n { type: 'checkbox', label: 'Strong (lower only)', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n action: buttons,\n name: inputs[2],\n trait: traits[inputs[2]],\n direction: inputs[4] || inputs[5],\n greater: inputs[6],\n strong: inputs[7]\n }\n createEffect(tokens, options)\n }\n}\n\nconst UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp'\nconst DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp'\n\nasync function createEffect (tokens, options) {\n const raise = (options.action === 'raise')\n const icon = (options.direction === 'Boost' ? UPICON : DOWNICON)\n let namePart = `${options.direction} ${options.trait.name}`\n const mode = CONST.ACTIVE_EFFECT_MODES.ADD\n const mods = []\n if (options.strong && options.direction === 'Lower') {\n mods.push('strong')\n }\n if (options.greater) {\n mods.push('greater')\n }\n if (mods.length > 0) {\n namePart = `${namePart} (${mods.join(', ')})`\n }\n const minorEffect = swadeMBHelpers.createEffectDocument(\n icon, `minor ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n const majorEffect = swadeMBHelpers.createEffectDocument(\n icon, `major ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n if (options.direction === 'Lower' && options.greater === 'Greater') {\n minorEffect.changes.push({\n key: options.trait.modkey,\n mode,\n value: '-2',\n priority: 0\n })\n }\n const mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n }\n mutate.embedded.ActiveEffect[minorEffect.id] = minorEffect\n if (raise) {\n mutate.embedded.ActiveEffect[majorEffect.id] = majorEffect\n }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(namePart)\n for (const token of tokens) {\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677458254287,"modifiedTime":1678165566682,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"1AqIFHAcX5TRdE8X","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Smite","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_smite.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Smite',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Smite' },\n { type: 'info', label: `Apply Smite to ${tokenList}` },\n { type: 'checkbox', label: 'Greater', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with Raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const tokenWeapons = {}\n let index = 2\n for (const token of tokens) {\n index += 2\n tokenWeapons[token.id] = index\n menuData.inputs.push({ type: 'info', label: `

${token.name}

` })\n const weapons = token.actor.items.filter(i => i.type === 'weapon').map(\n i => { return { value: i.name, html: i.name } })\n weapons.unshift({ value: '', html: 'None' })\n menuData.inputs.push({ type: 'select', label: token.name, options: weapons })\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n for (const tokenId in tokenWeapons) {\n tokenWeapons[tokenId] = inputs[tokenWeapons[tokenId]]\n }\n const greater = (inputs[2] === 'Greater')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, tokenWeapons, buttons, greater)\n }\n}\n\nasync function createEffect (tokens, tokenWeapons, choice, greater) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Smite')\n const effectIcon = baseEffect.icon\n let changeValue = (choice === 'raise' ? '+4' : '+2')\n if (greater) {\n changeValue = (choice === 'raise' ? '+6' : '+4')\n }\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}}[system.damage]`\n if (!weaponId) {\n continue\n }\n const effectName = `${choice === 'raise' ? 'major' : 'minor'} Smite${greater ? '(greater)' : ''} (${weaponName})`\n const changes = [\n {\n key: changeKey,\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: changeValue,\n priority: 0\n }\n ]\n const mutate = swadeMBHelpers.createMutationWithEffect(\n effectIcon, effectName, 5, changes)\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.1GnCpp1vjEucgNGk"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677548889704,"modifiedTime":1678165566682,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"C1vGk7AKQDpcvKyP","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Deflection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/defensive/shield-barrier-deflect-teal.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/defensive/shield-barrier-deflect-teal.webp'\n let effectName = 'Deflection'\n if (choice === 'raise') {\n effectName = `${effectName} (all)`\n } else {\n effectName = `${effectName} (${choice})`\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677645552357,"modifiedTime":1678165566682,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"HYTiftQW0pwwOQGH","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Glow","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/light/explosion-star-blue-large.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Glow',\n content: `Apply Glow to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/light/explosion-star-blue-large.webp'\n const effectName = 'Glow'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.5,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'starlight'\n },\n bright: 0,\n color: '#0f3fff',\n coloration: 1,\n contrast: 0,\n dim: 0.5,\n luminosity: 0.5,\n saturation: 0,\n shadows: 0\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677704975699,"modifiedTime":1678165566683,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"JcZ9kxBZJpw8KLQ6","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Confusion","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/control/hypnosis-mesmerism-swirl.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Confusion',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Confusion' },\n { type: 'info', label: `Apply Confusion to ${tokenList}` },\n { type: 'checkbox', label: 'Greater (adds shaken)', options: false }\n ],\n buttons: [\n { label: 'Distracted', value: 'distracted' },\n { label: 'Vulnerable', value: 'vulnerable' },\n { label: 'Raise (both)', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n const greater = (inputs[2] === 'Greater (adds shaken)')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, buttons, greater)\n }\n}\n\nfunction getStatus (label, name) {\n const effect = JSON.parse(JSON.stringify(\n CONFIG.statusEffects.find(se => se.label === label)))\n effect.flags.core = { statusId: effect.id }\n effect.id = name\n return effect\n}\n\nasync function createEffect (tokens, choice, greater) {\n const effects = []\n if (choice === 'distracted' || choice === 'raise') {\n effects.push(getStatus('SWADE.Distr', 'Distracted'))\n }\n if (choice === 'vulnerable' || choice === 'raise') {\n effects.push(getStatus('SWADE.Vuln', 'Vulnerable'))\n }\n if (greater) {\n effects.push(getStatus('SWADE.Shaken', 'Shaken'))\n }\n for (const token of tokens) {\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Confusion')\n const mutate = {\n embedded: { ActiveEffect: {} }\n }\n for (const effect of effects) {\n mutate.embedded.ActiveEffect[effect.id] = effect\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678082334572,"modifiedTime":1678165566683,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"L2IstecV7ivcrgUI","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Shroud","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/perception/silhouette-stealth-shadow.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Shroud',\n content: `Apply Shroud to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/perception/silhouette-stealth-shadow.webp'\n const effectName = 'Shroud'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.1,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'roiling'\n },\n bright: 0,\n color: null,\n coloration: 0,\n contrast: 0,\n dim: 0.1,\n luminosity: -0.15,\n saturation: 0,\n shadows: 0.25\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677649631598,"modifiedTime":1678165566683,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"QpillIBvZmuHeuTV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Summon","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/symbols/runes-star-orange.webp","scope":"global","command":"const ACTORFOLDER = 'Summonables'\nconst SUMMONICON = 'icons/magic/symbols/runes-star-orange.webp'\n\nswadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const token = tokens[0]\n const tokenList = token.name\n const folder = swadeMBHelpers.getActorFolderByPath(ACTORFOLDER)\n const actors = swadeMBHelpers.getActorsInFolder(folder)\n const menuOptions = {\n title: 'Summon Creature',\n defaultButton: 'cancel',\n options: {}\n }\n const menuData = {\n inputs: [\n { type: 'header', label: 'Summon Creature' },\n { type: 'info', label: `${tokenList} is summoning` },\n {\n type: 'select',\n label: 'Ally to summon',\n options: Object.keys(actors).sort().map(k => { return { value: actors[k].id, html: k } })\n },\n { type: 'number', label: 'Number to spawn (+half base cost per)', options: 1 }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const summonData = {\n raise: (buttons === 'raise'),\n actorId: inputs[2],\n number: inputs[3]\n }\n summonData.actor = game.actors.get(summonData.actorId)\n summonData.actorName = summonData.actor.name\n summonData.icon = summonData.actor.prototypeToken.texture.src\n summonData.token = summonData.actor.prototypeToken\n\n doWork(summonData, token)\n }\n}\n\nasync function doWork (summonData, token) {\n console.log('Summon ', token, summonData)\n const effectName = `Summoned ${summonData.actorName} (${summonData.number})`\n const tokenEffectMutation = swadeMBHelpers.createMutationWithEffect(SUMMONICON, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, tokenEffectMutation, {}, mutateOptions)\n\n const spawnOptions = {\n controllingActor: token.actor,\n duplicates: summonData.number,\n comparisonKeys: { ActiveEffect: 'label' },\n crosshairs: {\n size: 1,\n icon: summonData.icon,\n label: `Summon ${summonData.actorName}`,\n drawOutline: false,\n rememberControlled: true\n }\n }\n const spawnMutation = {\n token: {\n actorLink: false,\n name: `${token.name}'s ${summonData.token.name}`\n }\n }\n await warpgate.spawn(summonData.actorName, spawnMutation, {}, spawnOptions)\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677996503821,"modifiedTime":1678165566683,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"RV09eJi9iG5bfupo","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Protection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_protection.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Protection')\n const changes = [\n {\n key: 'system.stats.toughness.armor',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE,\n value: 2,\n priority: 0\n }\n ]\n let effectName = 'minor Protection'\n if (choice === 'raise') {\n changes[0].key = 'system.stats.toughness.value'\n effectName = 'major Protection'\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(\n baseEffect.icon, effectName, 5, changes)\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677630174987,"modifiedTime":1678165566683,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"YETsNWOWfIxyLPdC","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Lingering Damage","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/acid/dissolve-arm-flesh.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Lingering Damage',\n content: `Apply Lingering Damage to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'Ok', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok') {\n await createEffect(tokens)\n }\n}\n\nasync function createEffect (tokens) {\n const icon = 'icons/magic/acid/dissolve-arm-flesh.webp'\n const effectName = 'Lingering Damage'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 1, [])\n mutate.embedded.ActiveEffect['Lingering Damage'].flags.swade.expiration =\n CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnPrompt\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677800587229,"modifiedTime":1678165566683,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"txJBrqgVNO3jpvFG","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Hinder","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/movement/abstract-ribbons-red-orange.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hinder',\n content: `Apply Hinder to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/movement/abstract-ribbons-red-orange.webp'\n const effectName = 'Hinder'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: -2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678165566684,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"uvHTdYUn5l3Z1rAV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Hurry","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/skills/movement/feet-winged-boots-blue.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hurry',\n content: `Apply Hurry to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/skills/movement/feet-winged-boots-blue.webp'\n const effectName = 'Hurry'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: 2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678165566684,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"yG1ZQO30ZlntYJp7","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -- 2.30.2 From 1aaa6fb193b72c1fbb5a0aa0b71b3bd87f870bea Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Mon, 6 Mar 2023 23:39:56 -0600 Subject: [PATCH 5/7] Add blind effect macro Closes #6 --- CHANGELOG.md | 1 + macros/blind.js | 45 ++++++++++++++++++++++++++++++++++++++++++ packs/effect-macros.db | 36 ++++++++++++--------------------- 3 files changed, 59 insertions(+), 23 deletions(-) create mode 100644 macros/blind.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 77cac74..223155e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Confusion effect macro - Entangle effect macro +- Blind effect macro ### Changed diff --git a/macros/blind.js b/macros/blind.js new file mode 100644 index 0000000..30ad41e --- /dev/null +++ b/macros/blind.js @@ -0,0 +1,45 @@ +swadeMBHelpers.runOnTargetOrSelectedTokens(main) + +async function main (tokens) { + const tokenList = tokens.map(t => t.name).join(', ') + const menuOptions = { + title: 'Blind', + defaultButton: 'Cancel', + options: {} + } + + const menuData = { + inputs: [ + { type: 'header', label: 'Blind' }, + { type: 'info', label: `Apply Blind to ${tokenList}` }, + { type: 'checkbox', label: 'Strong', options: false } + ], + buttons: [ + { label: 'Apply', value: 'apply' }, + { label: 'Raise', value: 'raise' }, + { label: 'Cancel', value: 'cancel' } + ] + } + + const { buttons, inputs } = await warpgate.menu(menuData, menuOptions) + if (buttons && buttons !== 'cancel') { + const options = { + raise: (buttons === 'raise'), + strong: (!!inputs[2]) + } + await createEffect(tokens, options) + } +} + +async function createEffect (tokens, options) { + const effectDetails = (options.raise ? '-4' : '-2') + const effectEnd = (options.strong ? 'Vigor -2' : 'Vigor') + const effectName = `Blind (${effectDetails}) ${effectEnd} ends` + const baseEffect = CONFIG.statusEffects.find(se => se.label === 'EFFECT.StatusBlind') + for (const token of tokens) { + const mutate = swadeMBHelpers.createMutationWithEffect(baseEffect.icon, effectName, 1, []) + mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id } + const mutateOptions = swadeMBHelpers.defaultMutationOptions('Blind') + await warpgate.mutate(token.document, mutate, {}, mutateOptions) + } +} diff --git a/packs/effect-macros.db b/packs/effect-macros.db index 317ab02..1627e08 100644 --- a/packs/effect-macros.db +++ b/packs/effect-macros.db @@ -1,23 +1,13 @@ -{"name":"Boost/Lower Trait","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/life/cross-embers-glow-yellow-purple.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n let traitOptions = [\n 'Agility', 'Smarts', 'Spirit', 'Strength', 'Vigor'\n ]\n const allSkills = []\n const traits = {}\n for (const traitName of traitOptions) {\n const lower = traitName.toLowerCase()\n traits[traitName] = {\n name: traitName,\n type: 'attribute',\n modkey: `system.attributes.${lower}.die.modifier`,\n diekey: `system.attributes.${lower}.die.sides`\n }\n }\n\n const tokenList = tokens.map(t => t.name).join(', ')\n for (const token of tokens) {\n const skills = token.actor.items.filter(item => item.type === 'skill')\n for (const skill of skills) {\n const name = skill.name\n traits[name] = {\n type: 'skill',\n name,\n modkey: `@Skill{${name}}[system.die.modifier]`,\n diekey: `@Skill{${name}}[system.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\n const menuOptions = {\n title: 'Boost/Lower Trait',\n defaultButton: 'Cancel',\n options: {}\n }\n const 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: ['isBoost', true] },\n { type: 'radio', label: 'Lower', options: ['isBoost', false] },\n { type: 'checkbox', label: 'Greater', options: false },\n { type: 'checkbox', label: 'Strong (lower only)', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n action: buttons,\n name: inputs[2],\n trait: traits[inputs[2]],\n direction: inputs[4] || inputs[5],\n greater: inputs[6],\n strong: inputs[7]\n }\n createEffect(tokens, options)\n }\n}\n\nconst UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp'\nconst DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp'\n\nasync function createEffect (tokens, options) {\n const raise = (options.action === 'raise')\n const icon = (options.direction === 'Boost' ? UPICON : DOWNICON)\n let namePart = `${options.direction} ${options.trait.name}`\n const mode = CONST.ACTIVE_EFFECT_MODES.ADD\n const mods = []\n if (options.strong && options.direction === 'Lower') {\n mods.push('strong')\n }\n if (options.greater) {\n mods.push('greater')\n }\n if (mods.length > 0) {\n namePart = `${namePart} (${mods.join(', ')})`\n }\n const minorEffect = swadeMBHelpers.createEffectDocument(\n icon, `minor ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n const majorEffect = swadeMBHelpers.createEffectDocument(\n icon, `major ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n if (options.direction === 'Lower' && options.greater === 'Greater') {\n minorEffect.changes.push({\n key: options.trait.modkey,\n mode,\n value: '-2',\n priority: 0\n })\n }\n const mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n }\n mutate.embedded.ActiveEffect[minorEffect.id] = minorEffect\n if (raise) {\n mutate.embedded.ActiveEffect[majorEffect.id] = majorEffect\n }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(namePart)\n for (const token of tokens) {\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677458254287,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"1AqIFHAcX5TRdE8X","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Smite","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_smite.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Smite',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Smite' },\n { type: 'info', label: `Apply Smite to ${tokenList}` },\n { type: 'checkbox', label: 'Greater', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with Raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const tokenWeapons = {}\n let index = 2\n for (const token of tokens) {\n index += 2\n tokenWeapons[token.id] = index\n menuData.inputs.push({ type: 'info', label: `

${token.name}

` })\n const weapons = token.actor.items.filter(i => i.type === 'weapon').map(\n i => { return { value: i.name, html: i.name } })\n weapons.unshift({ value: '', html: 'None' })\n menuData.inputs.push({ type: 'select', label: token.name, options: weapons })\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n for (const tokenId in tokenWeapons) {\n tokenWeapons[tokenId] = inputs[tokenWeapons[tokenId]]\n }\n const greater = (inputs[2] === 'Greater')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, tokenWeapons, buttons, greater)\n }\n}\n\nasync function createEffect (tokens, tokenWeapons, choice, greater) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Smite')\n const effectIcon = baseEffect.icon\n let changeValue = (choice === 'raise' ? '+4' : '+2')\n if (greater) {\n changeValue = (choice === 'raise' ? '+6' : '+4')\n }\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}}[system.damage]`\n if (!weaponId) {\n continue\n }\n const effectName = `${choice === 'raise' ? 'major' : 'minor'} Smite${greater ? '(greater)' : ''} (${weaponName})`\n const changes = [\n {\n key: changeKey,\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: changeValue,\n priority: 0\n }\n ]\n const mutate = swadeMBHelpers.createMutationWithEffect(\n effectIcon, effectName, 5, changes)\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.1GnCpp1vjEucgNGk"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677548889704,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"C1vGk7AKQDpcvKyP","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Deflection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/defensive/shield-barrier-deflect-teal.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/defensive/shield-barrier-deflect-teal.webp'\n let effectName = 'Deflection'\n if (choice === 'raise') {\n effectName = `${effectName} (all)`\n } else {\n effectName = `${effectName} (${choice})`\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677645552357,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"HYTiftQW0pwwOQGH","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Glow","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/light/explosion-star-blue-large.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Glow',\n content: `Apply Glow to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/light/explosion-star-blue-large.webp'\n const effectName = 'Glow'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.5,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'starlight'\n },\n bright: 0,\n color: '#0f3fff',\n coloration: 1,\n contrast: 0,\n dim: 0.5,\n luminosity: 0.5,\n saturation: 0,\n shadows: 0\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677704975699,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"JcZ9kxBZJpw8KLQ6","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Confusion","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/control/hypnosis-mesmerism-swirl.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Confusion',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Confusion' },\n { type: 'info', label: `Apply Confusion to ${tokenList}` },\n { type: 'checkbox', label: 'Greater (adds shaken)', options: false }\n ],\n buttons: [\n { label: 'Distracted', value: 'distracted' },\n { label: 'Vulnerable', value: 'vulnerable' },\n { label: 'Raise (both)', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n const greater = (inputs[2] === 'Greater (adds shaken)')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, buttons, greater)\n }\n}\n\nfunction getStatus (label, name) {\n const effect = JSON.parse(JSON.stringify(\n CONFIG.statusEffects.find(se => se.label === label)))\n effect.flags.core = { statusId: effect.id }\n effect.id = name\n return effect\n}\n\nasync function createEffect (tokens, choice, greater) {\n const effects = []\n if (choice === 'distracted' || choice === 'raise') {\n effects.push(getStatus('SWADE.Distr', 'Distracted'))\n }\n if (choice === 'vulnerable' || choice === 'raise') {\n effects.push(getStatus('SWADE.Vuln', 'Vulnerable'))\n }\n if (greater) {\n effects.push(getStatus('SWADE.Shaken', 'Shaken'))\n }\n for (const token of tokens) {\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Confusion')\n const mutate = {\n embedded: { ActiveEffect: {} }\n }\n for (const effect of effects) {\n mutate.embedded.ActiveEffect[effect.id] = effect\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678082334572,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"L2IstecV7ivcrgUI","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Shroud","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/perception/silhouette-stealth-shadow.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Shroud',\n content: `Apply Shroud to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/perception/silhouette-stealth-shadow.webp'\n const effectName = 'Shroud'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.1,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'roiling'\n },\n bright: 0,\n color: null,\n coloration: 0,\n contrast: 0,\n dim: 0.1,\n luminosity: -0.15,\n saturation: 0,\n shadows: 0.25\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677649631598,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"QpillIBvZmuHeuTV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Summon","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/symbols/runes-star-orange.webp","scope":"global","command":"const ACTORFOLDER = 'Summonables'\nconst SUMMONICON = 'icons/magic/symbols/runes-star-orange.webp'\n\nswadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const token = tokens[0]\n const tokenList = token.name\n const folder = swadeMBHelpers.getActorFolderByPath(ACTORFOLDER)\n const actors = swadeMBHelpers.getActorsInFolder(folder)\n const menuOptions = {\n title: 'Summon Creature',\n defaultButton: 'cancel',\n options: {}\n }\n const menuData = {\n inputs: [\n { type: 'header', label: 'Summon Creature' },\n { type: 'info', label: `${tokenList} is summoning` },\n {\n type: 'select',\n label: 'Ally to summon',\n options: Object.keys(actors).sort().map(k => { return { value: actors[k].id, html: k } })\n },\n { type: 'number', label: 'Number to spawn (+half base cost per)', options: 1 }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const summonData = {\n raise: (buttons === 'raise'),\n actorId: inputs[2],\n number: inputs[3]\n }\n summonData.actor = game.actors.get(summonData.actorId)\n summonData.actorName = summonData.actor.name\n summonData.icon = summonData.actor.prototypeToken.texture.src\n summonData.token = summonData.actor.prototypeToken\n\n doWork(summonData, token)\n }\n}\n\nasync function doWork (summonData, token) {\n console.log('Summon ', token, summonData)\n const effectName = `Summoned ${summonData.actorName} (${summonData.number})`\n const tokenEffectMutation = swadeMBHelpers.createMutationWithEffect(SUMMONICON, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, tokenEffectMutation, {}, mutateOptions)\n\n const spawnOptions = {\n controllingActor: token.actor,\n duplicates: summonData.number,\n comparisonKeys: { ActiveEffect: 'label' },\n crosshairs: {\n size: 1,\n icon: summonData.icon,\n label: `Summon ${summonData.actorName}`,\n drawOutline: false,\n rememberControlled: true\n }\n }\n const spawnMutation = {\n token: {\n actorLink: false,\n name: `${token.name}'s ${summonData.token.name}`\n }\n }\n await warpgate.spawn(summonData.actorName, spawnMutation, {}, spawnOptions)\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677996503821,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"RV09eJi9iG5bfupo","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Protection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_protection.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Protection')\n const changes = [\n {\n key: 'system.stats.toughness.armor',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE,\n value: 2,\n priority: 0\n }\n ]\n let effectName = 'minor Protection'\n if (choice === 'raise') {\n changes[0].key = 'system.stats.toughness.value'\n effectName = 'major Protection'\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(\n baseEffect.icon, effectName, 5, changes)\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677630174987,"modifiedTime":1678162795693,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"YETsNWOWfIxyLPdC","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Lingering Damage","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/acid/dissolve-arm-flesh.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Lingering Damage',\n content: `Apply Lingering Damage to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'Ok', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok') {\n await createEffect(tokens)\n }\n}\n\nasync function createEffect (tokens) {\n const icon = 'icons/magic/acid/dissolve-arm-flesh.webp'\n const effectName = 'Lingering Damage'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 1, [])\n mutate.embedded.ActiveEffect['Lingering Damage'].flags.swade.expiration =\n CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnPrompt\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677800587229,"modifiedTime":1678162795694,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"txJBrqgVNO3jpvFG","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Hinder","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/movement/abstract-ribbons-red-orange.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hinder',\n content: `Apply Hinder to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/movement/abstract-ribbons-red-orange.webp'\n const effectName = 'Hinder'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: -2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678162795694,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"uvHTdYUn5l3Z1rAV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Hurry","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/skills/movement/feet-winged-boots-blue.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hurry',\n content: `Apply Hurry to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/skills/movement/feet-winged-boots-blue.webp'\n const effectName = 'Hurry'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: 2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678162795694,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"yG1ZQO30ZlntYJp7","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Entangle","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/nature/root-vine-barrier-wall-brown.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Entangle',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Entangle' },\n { type: 'info', label: `Apply Entangle to ${tokenList}` },\n { type: 'radio', label: 'Not Damaging', options: ['dmg', true] },\n { type: 'radio', label: 'Damaging', options: ['dmg', false] },\n { type: 'radio', label: 'Deadly', options: ['dmg', false] },\n { type: 'checkbox', label: 'Tough', options: false }\n ],\n buttons: [\n { label: 'Entangled', value: 'apply' },\n { label: 'Bound (raise)', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n apply: (buttons === 'raise' ? 'bound' : 'entangled'),\n damage: (inputs[3] ? '2d4' : (inputs[4] ? '2d6' : null)),\n tough: (!!inputs[5])\n }\n await createEffect(tokens, options)\n }\n}\n\nfunction getStatus (label, name) {\n const effect = JSON.parse(JSON.stringify(\n CONFIG.statusEffects.find(se => se.label === label)))\n effect.label = name\n if (!effect.flags) {\n effect.flags = {}\n }\n effect.flags.core = { statusId: effect.id }\n effect.id = name\n return effect\n}\n\nasync function createEffect (tokens, options) {\n const effectSearch = (options.apply === 'bound' ? 'SWADE.Bound' : 'SWADE.Entangled')\n const effectName = (options.apply === 'bound' ? 'Bound' : 'Entangled')\n const effect = getStatus(effectSearch, effectName)\n const extraIcon = 'icons/magic/nature/root-vine-barrier-wall-brown.webp'\n const extraEffect = swadeMBHelpers.createEffectDocument(extraIcon, 'Entangle Modifier', 1, [])\n\n if (options.damage) {\n extraEffect.id = `${extraEffect.id} - ${options.damage} dmg`\n extraEffect.label = `${extraEffect.label} - ${options.damage} dmg`\n }\n if (options.tough) {\n extraEffect.id = `Tough ${extraEffect.id}`\n extraEffect.label = `Tough ${extraEffect.label}`\n }\n for (const token of tokens) {\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Entangle')\n const mutate = { embedded: { ActiveEffect: {} } }\n mutate.embedded.ActiveEffect[effect.id] = effect\n if (options.damage || options.tough) {\n mutate.embedded.ActiveEffect[extraEffect.id] = extraEffect\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.2TOeRNCJT3T2px8D"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678164427219,"modifiedTime":1678165566624,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"2TOeRNCJT3T2px8D","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Boost/Lower Trait","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/life/cross-embers-glow-yellow-purple.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n let traitOptions = [\n 'Agility', 'Smarts', 'Spirit', 'Strength', 'Vigor'\n ]\n const allSkills = []\n const traits = {}\n for (const traitName of traitOptions) {\n const lower = traitName.toLowerCase()\n traits[traitName] = {\n name: traitName,\n type: 'attribute',\n modkey: `system.attributes.${lower}.die.modifier`,\n diekey: `system.attributes.${lower}.die.sides`\n }\n }\n\n const tokenList = tokens.map(t => t.name).join(', ')\n for (const token of tokens) {\n const skills = token.actor.items.filter(item => item.type === 'skill')\n for (const skill of skills) {\n const name = skill.name\n traits[name] = {\n type: 'skill',\n name,\n modkey: `@Skill{${name}}[system.die.modifier]`,\n diekey: `@Skill{${name}}[system.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\n const menuOptions = {\n title: 'Boost/Lower Trait',\n defaultButton: 'Cancel',\n options: {}\n }\n const 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: ['isBoost', true] },\n { type: 'radio', label: 'Lower', options: ['isBoost', false] },\n { type: 'checkbox', label: 'Greater', options: false },\n { type: 'checkbox', label: 'Strong (lower only)', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n action: buttons,\n name: inputs[2],\n trait: traits[inputs[2]],\n direction: inputs[4] || inputs[5],\n greater: inputs[6],\n strong: inputs[7]\n }\n createEffect(tokens, options)\n }\n}\n\nconst UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp'\nconst DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp'\n\nasync function createEffect (tokens, options) {\n const raise = (options.action === 'raise')\n const icon = (options.direction === 'Boost' ? UPICON : DOWNICON)\n let namePart = `${options.direction} ${options.trait.name}`\n const mode = CONST.ACTIVE_EFFECT_MODES.ADD\n const mods = []\n if (options.strong && options.direction === 'Lower') {\n mods.push('strong')\n }\n if (options.greater) {\n mods.push('greater')\n }\n if (mods.length > 0) {\n namePart = `${namePart} (${mods.join(', ')})`\n }\n const minorEffect = swadeMBHelpers.createEffectDocument(\n icon, `minor ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n const majorEffect = swadeMBHelpers.createEffectDocument(\n icon, `major ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n if (options.direction === 'Lower' && options.greater === 'Greater') {\n minorEffect.changes.push({\n key: options.trait.modkey,\n mode,\n value: '-2',\n priority: 0\n })\n }\n const mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n }\n mutate.embedded.ActiveEffect[minorEffect.id] = minorEffect\n if (raise) {\n mutate.embedded.ActiveEffect[majorEffect.id] = majorEffect\n }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(namePart)\n for (const token of tokens) {\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677458254287,"modifiedTime":1678165566682,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"1AqIFHAcX5TRdE8X","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Smite","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_smite.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Smite',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Smite' },\n { type: 'info', label: `Apply Smite to ${tokenList}` },\n { type: 'checkbox', label: 'Greater', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with Raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const tokenWeapons = {}\n let index = 2\n for (const token of tokens) {\n index += 2\n tokenWeapons[token.id] = index\n menuData.inputs.push({ type: 'info', label: `

${token.name}

` })\n const weapons = token.actor.items.filter(i => i.type === 'weapon').map(\n i => { return { value: i.name, html: i.name } })\n weapons.unshift({ value: '', html: 'None' })\n menuData.inputs.push({ type: 'select', label: token.name, options: weapons })\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n for (const tokenId in tokenWeapons) {\n tokenWeapons[tokenId] = inputs[tokenWeapons[tokenId]]\n }\n const greater = (inputs[2] === 'Greater')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, tokenWeapons, buttons, greater)\n }\n}\n\nasync function createEffect (tokens, tokenWeapons, choice, greater) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Smite')\n const effectIcon = baseEffect.icon\n let changeValue = (choice === 'raise' ? '+4' : '+2')\n if (greater) {\n changeValue = (choice === 'raise' ? '+6' : '+4')\n }\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}}[system.damage]`\n if (!weaponId) {\n continue\n }\n const effectName = `${choice === 'raise' ? 'major' : 'minor'} Smite${greater ? '(greater)' : ''} (${weaponName})`\n const changes = [\n {\n key: changeKey,\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: changeValue,\n priority: 0\n }\n ]\n const mutate = swadeMBHelpers.createMutationWithEffect(\n effectIcon, effectName, 5, changes)\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.1GnCpp1vjEucgNGk"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677548889704,"modifiedTime":1678165566682,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"C1vGk7AKQDpcvKyP","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Deflection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/defensive/shield-barrier-deflect-teal.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/defensive/shield-barrier-deflect-teal.webp'\n let effectName = 'Deflection'\n if (choice === 'raise') {\n effectName = `${effectName} (all)`\n } else {\n effectName = `${effectName} (${choice})`\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677645552357,"modifiedTime":1678165566682,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"HYTiftQW0pwwOQGH","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Glow","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/light/explosion-star-blue-large.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Glow',\n content: `Apply Glow to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/light/explosion-star-blue-large.webp'\n const effectName = 'Glow'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.5,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'starlight'\n },\n bright: 0,\n color: '#0f3fff',\n coloration: 1,\n contrast: 0,\n dim: 0.5,\n luminosity: 0.5,\n saturation: 0,\n shadows: 0\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677704975699,"modifiedTime":1678165566683,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"JcZ9kxBZJpw8KLQ6","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Confusion","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/control/hypnosis-mesmerism-swirl.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Confusion',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Confusion' },\n { type: 'info', label: `Apply Confusion to ${tokenList}` },\n { type: 'checkbox', label: 'Greater (adds shaken)', options: false }\n ],\n buttons: [\n { label: 'Distracted', value: 'distracted' },\n { label: 'Vulnerable', value: 'vulnerable' },\n { label: 'Raise (both)', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n const greater = (inputs[2] === 'Greater (adds shaken)')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, buttons, greater)\n }\n}\n\nfunction getStatus (label, name) {\n const effect = JSON.parse(JSON.stringify(\n CONFIG.statusEffects.find(se => se.label === label)))\n effect.flags.core = { statusId: effect.id }\n effect.id = name\n return effect\n}\n\nasync function createEffect (tokens, choice, greater) {\n const effects = []\n if (choice === 'distracted' || choice === 'raise') {\n effects.push(getStatus('SWADE.Distr', 'Distracted'))\n }\n if (choice === 'vulnerable' || choice === 'raise') {\n effects.push(getStatus('SWADE.Vuln', 'Vulnerable'))\n }\n if (greater) {\n effects.push(getStatus('SWADE.Shaken', 'Shaken'))\n }\n for (const token of tokens) {\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Confusion')\n const mutate = {\n embedded: { ActiveEffect: {} }\n }\n for (const effect of effects) {\n mutate.embedded.ActiveEffect[effect.id] = effect\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678082334572,"modifiedTime":1678165566683,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"L2IstecV7ivcrgUI","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Shroud","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/perception/silhouette-stealth-shadow.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Shroud',\n content: `Apply Shroud to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/perception/silhouette-stealth-shadow.webp'\n const effectName = 'Shroud'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.1,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'roiling'\n },\n bright: 0,\n color: null,\n coloration: 0,\n contrast: 0,\n dim: 0.1,\n luminosity: -0.15,\n saturation: 0,\n shadows: 0.25\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677649631598,"modifiedTime":1678165566683,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"QpillIBvZmuHeuTV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Summon","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/symbols/runes-star-orange.webp","scope":"global","command":"const ACTORFOLDER = 'Summonables'\nconst SUMMONICON = 'icons/magic/symbols/runes-star-orange.webp'\n\nswadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const token = tokens[0]\n const tokenList = token.name\n const folder = swadeMBHelpers.getActorFolderByPath(ACTORFOLDER)\n const actors = swadeMBHelpers.getActorsInFolder(folder)\n const menuOptions = {\n title: 'Summon Creature',\n defaultButton: 'cancel',\n options: {}\n }\n const menuData = {\n inputs: [\n { type: 'header', label: 'Summon Creature' },\n { type: 'info', label: `${tokenList} is summoning` },\n {\n type: 'select',\n label: 'Ally to summon',\n options: Object.keys(actors).sort().map(k => { return { value: actors[k].id, html: k } })\n },\n { type: 'number', label: 'Number to spawn (+half base cost per)', options: 1 }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const summonData = {\n raise: (buttons === 'raise'),\n actorId: inputs[2],\n number: inputs[3]\n }\n summonData.actor = game.actors.get(summonData.actorId)\n summonData.actorName = summonData.actor.name\n summonData.icon = summonData.actor.prototypeToken.texture.src\n summonData.token = summonData.actor.prototypeToken\n\n doWork(summonData, token)\n }\n}\n\nasync function doWork (summonData, token) {\n console.log('Summon ', token, summonData)\n const effectName = `Summoned ${summonData.actorName} (${summonData.number})`\n const tokenEffectMutation = swadeMBHelpers.createMutationWithEffect(SUMMONICON, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, tokenEffectMutation, {}, mutateOptions)\n\n const spawnOptions = {\n controllingActor: token.actor,\n duplicates: summonData.number,\n comparisonKeys: { ActiveEffect: 'label' },\n crosshairs: {\n size: 1,\n icon: summonData.icon,\n label: `Summon ${summonData.actorName}`,\n drawOutline: false,\n rememberControlled: true\n }\n }\n const spawnMutation = {\n token: {\n actorLink: false,\n name: `${token.name}'s ${summonData.token.name}`\n }\n }\n await warpgate.spawn(summonData.actorName, spawnMutation, {}, spawnOptions)\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677996503821,"modifiedTime":1678165566683,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"RV09eJi9iG5bfupo","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Protection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_protection.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Protection')\n const changes = [\n {\n key: 'system.stats.toughness.armor',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE,\n value: 2,\n priority: 0\n }\n ]\n let effectName = 'minor Protection'\n if (choice === 'raise') {\n changes[0].key = 'system.stats.toughness.value'\n effectName = 'major Protection'\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(\n baseEffect.icon, effectName, 5, changes)\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677630174987,"modifiedTime":1678165566683,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"YETsNWOWfIxyLPdC","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Lingering Damage","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/acid/dissolve-arm-flesh.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Lingering Damage',\n content: `Apply Lingering Damage to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'Ok', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok') {\n await createEffect(tokens)\n }\n}\n\nasync function createEffect (tokens) {\n const icon = 'icons/magic/acid/dissolve-arm-flesh.webp'\n const effectName = 'Lingering Damage'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 1, [])\n mutate.embedded.ActiveEffect['Lingering Damage'].flags.swade.expiration =\n CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnPrompt\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677800587229,"modifiedTime":1678165566683,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"txJBrqgVNO3jpvFG","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Hinder","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/movement/abstract-ribbons-red-orange.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hinder',\n content: `Apply Hinder to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/movement/abstract-ribbons-red-orange.webp'\n const effectName = 'Hinder'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: -2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678165566684,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"uvHTdYUn5l3Z1rAV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Hurry","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/skills/movement/feet-winged-boots-blue.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hurry',\n content: `Apply Hurry to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/skills/movement/feet-winged-boots-blue.webp'\n const effectName = 'Hurry'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: 2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678165566684,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"yG1ZQO30ZlntYJp7","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Boost/Lower Trait","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/life/cross-embers-glow-yellow-purple.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n let traitOptions = [\n 'Agility', 'Smarts', 'Spirit', 'Strength', 'Vigor'\n ]\n const allSkills = []\n const traits = {}\n for (const traitName of traitOptions) {\n const lower = traitName.toLowerCase()\n traits[traitName] = {\n name: traitName,\n type: 'attribute',\n modkey: `system.attributes.${lower}.die.modifier`,\n diekey: `system.attributes.${lower}.die.sides`\n }\n }\n\n const tokenList = tokens.map(t => t.name).join(', ')\n for (const token of tokens) {\n const skills = token.actor.items.filter(item => item.type === 'skill')\n for (const skill of skills) {\n const name = skill.name\n traits[name] = {\n type: 'skill',\n name,\n modkey: `@Skill{${name}}[system.die.modifier]`,\n diekey: `@Skill{${name}}[system.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\n const menuOptions = {\n title: 'Boost/Lower Trait',\n defaultButton: 'Cancel',\n options: {}\n }\n const 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: ['isBoost', true] },\n { type: 'radio', label: 'Lower', options: ['isBoost', false] },\n { type: 'checkbox', label: 'Greater', options: false },\n { type: 'checkbox', label: 'Strong (lower only)', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n action: buttons,\n name: inputs[2],\n trait: traits[inputs[2]],\n direction: inputs[4] || inputs[5],\n greater: inputs[6],\n strong: inputs[7]\n }\n createEffect(tokens, options)\n }\n}\n\nconst UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp'\nconst DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp'\n\nasync function createEffect (tokens, options) {\n const raise = (options.action === 'raise')\n const icon = (options.direction === 'Boost' ? UPICON : DOWNICON)\n let namePart = `${options.direction} ${options.trait.name}`\n const mode = CONST.ACTIVE_EFFECT_MODES.ADD\n const mods = []\n if (options.strong && options.direction === 'Lower') {\n mods.push('strong')\n }\n if (options.greater) {\n mods.push('greater')\n }\n if (mods.length > 0) {\n namePart = `${namePart} (${mods.join(', ')})`\n }\n const minorEffect = swadeMBHelpers.createEffectDocument(\n icon, `minor ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n const majorEffect = swadeMBHelpers.createEffectDocument(\n icon, `major ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n if (options.direction === 'Lower' && options.greater === 'Greater') {\n minorEffect.changes.push({\n key: options.trait.modkey,\n mode,\n value: '-2',\n priority: 0\n })\n }\n const mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n }\n mutate.embedded.ActiveEffect[minorEffect.id] = minorEffect\n if (raise) {\n mutate.embedded.ActiveEffect[majorEffect.id] = majorEffect\n }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(namePart)\n for (const token of tokens) {\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677458254287,"modifiedTime":1678167540882,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"1AqIFHAcX5TRdE8X","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Entangle","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/nature/root-vine-barrier-wall-brown.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Entangle',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Entangle' },\n { type: 'info', label: `Apply Entangle to ${tokenList}` },\n { type: 'radio', label: 'Not Damaging', options: ['dmg', true] },\n { type: 'radio', label: 'Damaging', options: ['dmg', false] },\n { type: 'radio', label: 'Deadly', options: ['dmg', false] },\n { type: 'checkbox', label: 'Tough', options: false }\n ],\n buttons: [\n { label: 'Entangled', value: 'apply' },\n { label: 'Bound (raise)', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n apply: (buttons === 'raise' ? 'bound' : 'entangled'),\n damage: (inputs[3] ? '2d4' : (inputs[4] ? '2d6' : null)),\n tough: (!!inputs[5])\n }\n await createEffect(tokens, options)\n }\n}\n\nfunction getStatus (label, name) {\n const effect = JSON.parse(JSON.stringify(\n CONFIG.statusEffects.find(se => se.label === label)))\n effect.label = name\n if (!effect.flags) {\n effect.flags = {}\n }\n effect.flags.core = { statusId: effect.id }\n effect.id = name\n return effect\n}\n\nasync function createEffect (tokens, options) {\n const effectSearch = (options.apply === 'bound' ? 'SWADE.Bound' : 'SWADE.Entangled')\n const effectName = (options.apply === 'bound' ? 'Bound' : 'Entangled')\n const effect = getStatus(effectSearch, effectName)\n const extraIcon = 'icons/magic/nature/root-vine-barrier-wall-brown.webp'\n const extraEffect = swadeMBHelpers.createEffectDocument(extraIcon, 'Entangle Modifier', 1, [])\n\n if (options.damage) {\n extraEffect.id = `${extraEffect.id} - ${options.damage} dmg`\n extraEffect.label = `${extraEffect.label} - ${options.damage} dmg`\n }\n if (options.tough) {\n extraEffect.id = `Tough ${extraEffect.id}`\n extraEffect.label = `Tough ${extraEffect.label}`\n }\n for (const token of tokens) {\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Entangle')\n const mutate = { embedded: { ActiveEffect: {} } }\n mutate.embedded.ActiveEffect[effect.id] = effect\n if (options.damage || options.tough) {\n mutate.embedded.ActiveEffect[extraEffect.id] = extraEffect\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678164427219,"modifiedTime":1678167540882,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"2TOeRNCJT3T2px8D","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Smite","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_smite.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Smite',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Smite' },\n { type: 'info', label: `Apply Smite to ${tokenList}` },\n { type: 'checkbox', label: 'Greater', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with Raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const tokenWeapons = {}\n let index = 2\n for (const token of tokens) {\n index += 2\n tokenWeapons[token.id] = index\n menuData.inputs.push({ type: 'info', label: `

${token.name}

` })\n const weapons = token.actor.items.filter(i => i.type === 'weapon').map(\n i => { return { value: i.name, html: i.name } })\n weapons.unshift({ value: '', html: 'None' })\n menuData.inputs.push({ type: 'select', label: token.name, options: weapons })\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n for (const tokenId in tokenWeapons) {\n tokenWeapons[tokenId] = inputs[tokenWeapons[tokenId]]\n }\n const greater = (inputs[2] === 'Greater')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, tokenWeapons, buttons, greater)\n }\n}\n\nasync function createEffect (tokens, tokenWeapons, choice, greater) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Smite')\n const effectIcon = baseEffect.icon\n let changeValue = (choice === 'raise' ? '+4' : '+2')\n if (greater) {\n changeValue = (choice === 'raise' ? '+6' : '+4')\n }\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}}[system.damage]`\n if (!weaponId) {\n continue\n }\n const effectName = `${choice === 'raise' ? 'major' : 'minor'} Smite${greater ? '(greater)' : ''} (${weaponName})`\n const changes = [\n {\n key: changeKey,\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: changeValue,\n priority: 0\n }\n ]\n const mutate = swadeMBHelpers.createMutationWithEffect(\n effectIcon, effectName, 5, changes)\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.1GnCpp1vjEucgNGk"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677548889704,"modifiedTime":1678167540882,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"C1vGk7AKQDpcvKyP","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Deflection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/defensive/shield-barrier-deflect-teal.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/defensive/shield-barrier-deflect-teal.webp'\n let effectName = 'Deflection'\n if (choice === 'raise') {\n effectName = `${effectName} (all)`\n } else {\n effectName = `${effectName} (${choice})`\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677645552357,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"HYTiftQW0pwwOQGH","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Glow","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/light/explosion-star-blue-large.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Glow',\n content: `Apply Glow to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/light/explosion-star-blue-large.webp'\n const effectName = 'Glow'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.5,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'starlight'\n },\n bright: 0,\n color: '#0f3fff',\n coloration: 1,\n contrast: 0,\n dim: 0.5,\n luminosity: 0.5,\n saturation: 0,\n shadows: 0\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677704975699,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"JcZ9kxBZJpw8KLQ6","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Confusion","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/control/hypnosis-mesmerism-swirl.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Confusion',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Confusion' },\n { type: 'info', label: `Apply Confusion to ${tokenList}` },\n { type: 'checkbox', label: 'Greater (adds shaken)', options: false }\n ],\n buttons: [\n { label: 'Distracted', value: 'distracted' },\n { label: 'Vulnerable', value: 'vulnerable' },\n { label: 'Raise (both)', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n const greater = (inputs[2] === 'Greater (adds shaken)')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, buttons, greater)\n }\n}\n\nfunction getStatus (label, name) {\n const effect = JSON.parse(JSON.stringify(\n CONFIG.statusEffects.find(se => se.label === label)))\n effect.flags.core = { statusId: effect.id }\n effect.id = name\n return effect\n}\n\nasync function createEffect (tokens, choice, greater) {\n const effects = []\n if (choice === 'distracted' || choice === 'raise') {\n effects.push(getStatus('SWADE.Distr', 'Distracted'))\n }\n if (choice === 'vulnerable' || choice === 'raise') {\n effects.push(getStatus('SWADE.Vuln', 'Vulnerable'))\n }\n if (greater) {\n effects.push(getStatus('SWADE.Shaken', 'Shaken'))\n }\n for (const token of tokens) {\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Confusion')\n const mutate = {\n embedded: { ActiveEffect: {} }\n }\n for (const effect of effects) {\n mutate.embedded.ActiveEffect[effect.id] = effect\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678082334572,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"L2IstecV7ivcrgUI","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Shroud","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/perception/silhouette-stealth-shadow.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Shroud',\n content: `Apply Shroud to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/perception/silhouette-stealth-shadow.webp'\n const effectName = 'Shroud'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.1,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'roiling'\n },\n bright: 0,\n color: null,\n coloration: 0,\n contrast: 0,\n dim: 0.1,\n luminosity: -0.15,\n saturation: 0,\n shadows: 0.25\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677649631598,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"QpillIBvZmuHeuTV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Summon","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/symbols/runes-star-orange.webp","scope":"global","command":"const ACTORFOLDER = 'Summonables'\nconst SUMMONICON = 'icons/magic/symbols/runes-star-orange.webp'\n\nswadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const token = tokens[0]\n const tokenList = token.name\n const folder = swadeMBHelpers.getActorFolderByPath(ACTORFOLDER)\n const actors = swadeMBHelpers.getActorsInFolder(folder)\n const menuOptions = {\n title: 'Summon Creature',\n defaultButton: 'cancel',\n options: {}\n }\n const menuData = {\n inputs: [\n { type: 'header', label: 'Summon Creature' },\n { type: 'info', label: `${tokenList} is summoning` },\n {\n type: 'select',\n label: 'Ally to summon',\n options: Object.keys(actors).sort().map(k => { return { value: actors[k].id, html: k } })\n },\n { type: 'number', label: 'Number to spawn (+half base cost per)', options: 1 }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const summonData = {\n raise: (buttons === 'raise'),\n actorId: inputs[2],\n number: inputs[3]\n }\n summonData.actor = game.actors.get(summonData.actorId)\n summonData.actorName = summonData.actor.name\n summonData.icon = summonData.actor.prototypeToken.texture.src\n summonData.token = summonData.actor.prototypeToken\n\n doWork(summonData, token)\n }\n}\n\nasync function doWork (summonData, token) {\n console.log('Summon ', token, summonData)\n const effectName = `Summoned ${summonData.actorName} (${summonData.number})`\n const tokenEffectMutation = swadeMBHelpers.createMutationWithEffect(SUMMONICON, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, tokenEffectMutation, {}, mutateOptions)\n\n const spawnOptions = {\n controllingActor: token.actor,\n duplicates: summonData.number,\n comparisonKeys: { ActiveEffect: 'label' },\n crosshairs: {\n size: 1,\n icon: summonData.icon,\n label: `Summon ${summonData.actorName}`,\n drawOutline: false,\n rememberControlled: true\n }\n }\n const spawnMutation = {\n token: {\n actorLink: false,\n name: `${token.name}'s ${summonData.token.name}`\n }\n }\n await warpgate.spawn(summonData.actorName, spawnMutation, {}, spawnOptions)\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677996503821,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"RV09eJi9iG5bfupo","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Protection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_protection.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Protection')\n const changes = [\n {\n key: 'system.stats.toughness.armor',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE,\n value: 2,\n priority: 0\n }\n ]\n let effectName = 'minor Protection'\n if (choice === 'raise') {\n changes[0].key = 'system.stats.toughness.value'\n effectName = 'major Protection'\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(\n baseEffect.icon, effectName, 5, changes)\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677630174987,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"YETsNWOWfIxyLPdC","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Blind","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/svg/blind.svg","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Blind',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Blind' },\n { type: 'info', label: `Apply Blind to ${tokenList}` },\n { type: 'checkbox', label: 'Strong', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n raise: (buttons === 'raise'),\n strong: (!!inputs[2])\n }\n await createEffect(tokens, options)\n }\n}\n\nasync function createEffect (tokens, options) {\n const effectDetails = (options.raise ? '-4' : '-2')\n const effectEnd = (options.strong ? 'Vigor -2' : 'Vigor')\n const effectName = `Blind (${effectDetails}) ${effectEnd} ends`\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'EFFECT.StatusBlind')\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(baseEffect.icon, effectName, 1, [])\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Blind')\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.e9HvLMtaDw2qpcE8"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678165762773,"modifiedTime":1678167540828,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"e9HvLMtaDw2qpcE8","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Lingering Damage","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/acid/dissolve-arm-flesh.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Lingering Damage',\n content: `Apply Lingering Damage to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'Ok', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok') {\n await createEffect(tokens)\n }\n}\n\nasync function createEffect (tokens) {\n const icon = 'icons/magic/acid/dissolve-arm-flesh.webp'\n const effectName = 'Lingering Damage'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 1, [])\n mutate.embedded.ActiveEffect['Lingering Damage'].flags.swade.expiration =\n CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnPrompt\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677800587229,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"txJBrqgVNO3jpvFG","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Hinder","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/movement/abstract-ribbons-red-orange.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hinder',\n content: `Apply Hinder to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/movement/abstract-ribbons-red-orange.webp'\n const effectName = 'Hinder'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: -2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"uvHTdYUn5l3Z1rAV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Hurry","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/skills/movement/feet-winged-boots-blue.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hurry',\n content: `Apply Hurry to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/skills/movement/feet-winged-boots-blue.webp'\n const effectName = 'Hurry'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: 2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"yG1ZQO30ZlntYJp7","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -- 2.30.2 From 37f76c252140696cf608e1db8df62032225bab7b Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Tue, 7 Mar 2023 00:01:19 -0600 Subject: [PATCH 6/7] add invisibility and intangibility macro closes #29 closes #18 --- CHANGELOG.md | 2 ++ macros/intangibility.js | 41 ++++++++++++++++++++++++++++++++++++++ macros/invisibility.js | 44 +++++++++++++++++++++++++++++++++++++++++ packs/effect-macros.db | 28 ++++++++++++++------------ 4 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 macros/intangibility.js create mode 100644 macros/invisibility.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 223155e..7b965ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Confusion effect macro - Entangle effect macro - Blind effect macro +- Invisiblity macro +- Intangibility macro ### Changed diff --git a/macros/intangibility.js b/macros/intangibility.js new file mode 100644 index 0000000..8407b13 --- /dev/null +++ b/macros/intangibility.js @@ -0,0 +1,41 @@ +swadeMBHelpers.runOnTargetOrSelectedTokens(main) + +async function main (tokens) { + const tokenList = tokens.map(t => t.name).join(', ') + const menuOptions = { + title: 'Intangibility', + defaultButton: 'Cancel', + options: {} + } + + const menuData = { + inputs: [ + { type: 'header', label: 'Intangibility' }, + { type: 'info', label: `Apply Intangibility to ${tokenList}` }, + { type: 'checkbox', label: 'Duration', options: false } + ], + buttons: [ + { label: 'Apply', value: 'apply' }, + { label: 'Cancel', value: 'cancel' } + ] + } + + const { buttons, inputs } = await warpgate.menu(menuData, menuOptions) + if (buttons && buttons !== 'cancel') { + const options = { + duration: (!!inputs[2]) + } + await createEffect(tokens, options) + } +} + +async function createEffect (tokens, options) { + const effectName = 'Intangibility' + const duration = (options.duration ? 5 * 6 * 60 : 5) + const icon = 'icons/magic/control/debuff-energy-hold-levitate-blue-yellow.webp' + for (const token of tokens) { + const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, duration, []) + const mutateOptions = swadeMBHelpers.defaultMutationOptions('Intangibility') + await warpgate.mutate(token.document, mutate, {}, mutateOptions) + } +} diff --git a/macros/invisibility.js b/macros/invisibility.js new file mode 100644 index 0000000..9e007fb --- /dev/null +++ b/macros/invisibility.js @@ -0,0 +1,44 @@ +swadeMBHelpers.runOnTargetOrSelectedTokens(main) + +async function main (tokens) { + const tokenList = tokens.map(t => t.name).join(', ') + const menuOptions = { + title: 'Invisibility', + defaultButton: 'Cancel', + options: {} + } + + const menuData = { + inputs: [ + { type: 'header', label: 'Invisibility' }, + { type: 'info', label: `Apply Invisibility to ${tokenList}` }, + { type: 'checkbox', label: 'Duration', options: false } + ], + buttons: [ + { label: 'Apply', value: 'apply' }, + { label: 'Raise', value: 'raise' }, + { label: 'Cancel', value: 'cancel' } + ] + } + + const { buttons, inputs } = await warpgate.menu(menuData, menuOptions) + if (buttons && buttons !== 'cancel') { + const options = { + raise: (buttons === 'raise'), + duration: (!!inputs[2]) + } + await createEffect(tokens, options) + } +} + +async function createEffect (tokens, options) { + const effectName = `${options.raise ? 'major' : 'minor'} Invisibility` + const baseEffect = CONFIG.statusEffects.find(se => se.label === 'EFFECT.StatusInvisible') + const duration = (options.duration ? 5 * 6 * 60 : 5) + for (const token of tokens) { + const mutate = swadeMBHelpers.createMutationWithEffect(baseEffect.icon, effectName, duration, []) + mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id } + const mutateOptions = swadeMBHelpers.defaultMutationOptions('Invisibility') + await warpgate.mutate(token.document, mutate, {}, mutateOptions) + } +} diff --git a/packs/effect-macros.db b/packs/effect-macros.db index 1627e08..3d53698 100644 --- a/packs/effect-macros.db +++ b/packs/effect-macros.db @@ -1,13 +1,15 @@ -{"name":"Boost/Lower Trait","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/life/cross-embers-glow-yellow-purple.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n let traitOptions = [\n 'Agility', 'Smarts', 'Spirit', 'Strength', 'Vigor'\n ]\n const allSkills = []\n const traits = {}\n for (const traitName of traitOptions) {\n const lower = traitName.toLowerCase()\n traits[traitName] = {\n name: traitName,\n type: 'attribute',\n modkey: `system.attributes.${lower}.die.modifier`,\n diekey: `system.attributes.${lower}.die.sides`\n }\n }\n\n const tokenList = tokens.map(t => t.name).join(', ')\n for (const token of tokens) {\n const skills = token.actor.items.filter(item => item.type === 'skill')\n for (const skill of skills) {\n const name = skill.name\n traits[name] = {\n type: 'skill',\n name,\n modkey: `@Skill{${name}}[system.die.modifier]`,\n diekey: `@Skill{${name}}[system.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\n const menuOptions = {\n title: 'Boost/Lower Trait',\n defaultButton: 'Cancel',\n options: {}\n }\n const 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: ['isBoost', true] },\n { type: 'radio', label: 'Lower', options: ['isBoost', false] },\n { type: 'checkbox', label: 'Greater', options: false },\n { type: 'checkbox', label: 'Strong (lower only)', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n action: buttons,\n name: inputs[2],\n trait: traits[inputs[2]],\n direction: inputs[4] || inputs[5],\n greater: inputs[6],\n strong: inputs[7]\n }\n createEffect(tokens, options)\n }\n}\n\nconst UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp'\nconst DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp'\n\nasync function createEffect (tokens, options) {\n const raise = (options.action === 'raise')\n const icon = (options.direction === 'Boost' ? UPICON : DOWNICON)\n let namePart = `${options.direction} ${options.trait.name}`\n const mode = CONST.ACTIVE_EFFECT_MODES.ADD\n const mods = []\n if (options.strong && options.direction === 'Lower') {\n mods.push('strong')\n }\n if (options.greater) {\n mods.push('greater')\n }\n if (mods.length > 0) {\n namePart = `${namePart} (${mods.join(', ')})`\n }\n const minorEffect = swadeMBHelpers.createEffectDocument(\n icon, `minor ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n const majorEffect = swadeMBHelpers.createEffectDocument(\n icon, `major ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n if (options.direction === 'Lower' && options.greater === 'Greater') {\n minorEffect.changes.push({\n key: options.trait.modkey,\n mode,\n value: '-2',\n priority: 0\n })\n }\n const mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n }\n mutate.embedded.ActiveEffect[minorEffect.id] = minorEffect\n if (raise) {\n mutate.embedded.ActiveEffect[majorEffect.id] = majorEffect\n }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(namePart)\n for (const token of tokens) {\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677458254287,"modifiedTime":1678167540882,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"1AqIFHAcX5TRdE8X","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Entangle","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/nature/root-vine-barrier-wall-brown.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Entangle',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Entangle' },\n { type: 'info', label: `Apply Entangle to ${tokenList}` },\n { type: 'radio', label: 'Not Damaging', options: ['dmg', true] },\n { type: 'radio', label: 'Damaging', options: ['dmg', false] },\n { type: 'radio', label: 'Deadly', options: ['dmg', false] },\n { type: 'checkbox', label: 'Tough', options: false }\n ],\n buttons: [\n { label: 'Entangled', value: 'apply' },\n { label: 'Bound (raise)', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n apply: (buttons === 'raise' ? 'bound' : 'entangled'),\n damage: (inputs[3] ? '2d4' : (inputs[4] ? '2d6' : null)),\n tough: (!!inputs[5])\n }\n await createEffect(tokens, options)\n }\n}\n\nfunction getStatus (label, name) {\n const effect = JSON.parse(JSON.stringify(\n CONFIG.statusEffects.find(se => se.label === label)))\n effect.label = name\n if (!effect.flags) {\n effect.flags = {}\n }\n effect.flags.core = { statusId: effect.id }\n effect.id = name\n return effect\n}\n\nasync function createEffect (tokens, options) {\n const effectSearch = (options.apply === 'bound' ? 'SWADE.Bound' : 'SWADE.Entangled')\n const effectName = (options.apply === 'bound' ? 'Bound' : 'Entangled')\n const effect = getStatus(effectSearch, effectName)\n const extraIcon = 'icons/magic/nature/root-vine-barrier-wall-brown.webp'\n const extraEffect = swadeMBHelpers.createEffectDocument(extraIcon, 'Entangle Modifier', 1, [])\n\n if (options.damage) {\n extraEffect.id = `${extraEffect.id} - ${options.damage} dmg`\n extraEffect.label = `${extraEffect.label} - ${options.damage} dmg`\n }\n if (options.tough) {\n extraEffect.id = `Tough ${extraEffect.id}`\n extraEffect.label = `Tough ${extraEffect.label}`\n }\n for (const token of tokens) {\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Entangle')\n const mutate = { embedded: { ActiveEffect: {} } }\n mutate.embedded.ActiveEffect[effect.id] = effect\n if (options.damage || options.tough) {\n mutate.embedded.ActiveEffect[extraEffect.id] = extraEffect\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678164427219,"modifiedTime":1678167540882,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"2TOeRNCJT3T2px8D","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Smite","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_smite.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Smite',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Smite' },\n { type: 'info', label: `Apply Smite to ${tokenList}` },\n { type: 'checkbox', label: 'Greater', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with Raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const tokenWeapons = {}\n let index = 2\n for (const token of tokens) {\n index += 2\n tokenWeapons[token.id] = index\n menuData.inputs.push({ type: 'info', label: `

${token.name}

` })\n const weapons = token.actor.items.filter(i => i.type === 'weapon').map(\n i => { return { value: i.name, html: i.name } })\n weapons.unshift({ value: '', html: 'None' })\n menuData.inputs.push({ type: 'select', label: token.name, options: weapons })\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n for (const tokenId in tokenWeapons) {\n tokenWeapons[tokenId] = inputs[tokenWeapons[tokenId]]\n }\n const greater = (inputs[2] === 'Greater')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, tokenWeapons, buttons, greater)\n }\n}\n\nasync function createEffect (tokens, tokenWeapons, choice, greater) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Smite')\n const effectIcon = baseEffect.icon\n let changeValue = (choice === 'raise' ? '+4' : '+2')\n if (greater) {\n changeValue = (choice === 'raise' ? '+6' : '+4')\n }\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}}[system.damage]`\n if (!weaponId) {\n continue\n }\n const effectName = `${choice === 'raise' ? 'major' : 'minor'} Smite${greater ? '(greater)' : ''} (${weaponName})`\n const changes = [\n {\n key: changeKey,\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: changeValue,\n priority: 0\n }\n ]\n const mutate = swadeMBHelpers.createMutationWithEffect(\n effectIcon, effectName, 5, changes)\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.1GnCpp1vjEucgNGk"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677548889704,"modifiedTime":1678167540882,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"C1vGk7AKQDpcvKyP","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Deflection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/defensive/shield-barrier-deflect-teal.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/defensive/shield-barrier-deflect-teal.webp'\n let effectName = 'Deflection'\n if (choice === 'raise') {\n effectName = `${effectName} (all)`\n } else {\n effectName = `${effectName} (${choice})`\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677645552357,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"HYTiftQW0pwwOQGH","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Glow","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/light/explosion-star-blue-large.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Glow',\n content: `Apply Glow to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/light/explosion-star-blue-large.webp'\n const effectName = 'Glow'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.5,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'starlight'\n },\n bright: 0,\n color: '#0f3fff',\n coloration: 1,\n contrast: 0,\n dim: 0.5,\n luminosity: 0.5,\n saturation: 0,\n shadows: 0\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677704975699,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"JcZ9kxBZJpw8KLQ6","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Confusion","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/control/hypnosis-mesmerism-swirl.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Confusion',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Confusion' },\n { type: 'info', label: `Apply Confusion to ${tokenList}` },\n { type: 'checkbox', label: 'Greater (adds shaken)', options: false }\n ],\n buttons: [\n { label: 'Distracted', value: 'distracted' },\n { label: 'Vulnerable', value: 'vulnerable' },\n { label: 'Raise (both)', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n const greater = (inputs[2] === 'Greater (adds shaken)')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, buttons, greater)\n }\n}\n\nfunction getStatus (label, name) {\n const effect = JSON.parse(JSON.stringify(\n CONFIG.statusEffects.find(se => se.label === label)))\n effect.flags.core = { statusId: effect.id }\n effect.id = name\n return effect\n}\n\nasync function createEffect (tokens, choice, greater) {\n const effects = []\n if (choice === 'distracted' || choice === 'raise') {\n effects.push(getStatus('SWADE.Distr', 'Distracted'))\n }\n if (choice === 'vulnerable' || choice === 'raise') {\n effects.push(getStatus('SWADE.Vuln', 'Vulnerable'))\n }\n if (greater) {\n effects.push(getStatus('SWADE.Shaken', 'Shaken'))\n }\n for (const token of tokens) {\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Confusion')\n const mutate = {\n embedded: { ActiveEffect: {} }\n }\n for (const effect of effects) {\n mutate.embedded.ActiveEffect[effect.id] = effect\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678082334572,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"L2IstecV7ivcrgUI","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Shroud","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/perception/silhouette-stealth-shadow.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Shroud',\n content: `Apply Shroud to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/perception/silhouette-stealth-shadow.webp'\n const effectName = 'Shroud'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.1,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'roiling'\n },\n bright: 0,\n color: null,\n coloration: 0,\n contrast: 0,\n dim: 0.1,\n luminosity: -0.15,\n saturation: 0,\n shadows: 0.25\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677649631598,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"QpillIBvZmuHeuTV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Summon","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/symbols/runes-star-orange.webp","scope":"global","command":"const ACTORFOLDER = 'Summonables'\nconst SUMMONICON = 'icons/magic/symbols/runes-star-orange.webp'\n\nswadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const token = tokens[0]\n const tokenList = token.name\n const folder = swadeMBHelpers.getActorFolderByPath(ACTORFOLDER)\n const actors = swadeMBHelpers.getActorsInFolder(folder)\n const menuOptions = {\n title: 'Summon Creature',\n defaultButton: 'cancel',\n options: {}\n }\n const menuData = {\n inputs: [\n { type: 'header', label: 'Summon Creature' },\n { type: 'info', label: `${tokenList} is summoning` },\n {\n type: 'select',\n label: 'Ally to summon',\n options: Object.keys(actors).sort().map(k => { return { value: actors[k].id, html: k } })\n },\n { type: 'number', label: 'Number to spawn (+half base cost per)', options: 1 }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const summonData = {\n raise: (buttons === 'raise'),\n actorId: inputs[2],\n number: inputs[3]\n }\n summonData.actor = game.actors.get(summonData.actorId)\n summonData.actorName = summonData.actor.name\n summonData.icon = summonData.actor.prototypeToken.texture.src\n summonData.token = summonData.actor.prototypeToken\n\n doWork(summonData, token)\n }\n}\n\nasync function doWork (summonData, token) {\n console.log('Summon ', token, summonData)\n const effectName = `Summoned ${summonData.actorName} (${summonData.number})`\n const tokenEffectMutation = swadeMBHelpers.createMutationWithEffect(SUMMONICON, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, tokenEffectMutation, {}, mutateOptions)\n\n const spawnOptions = {\n controllingActor: token.actor,\n duplicates: summonData.number,\n comparisonKeys: { ActiveEffect: 'label' },\n crosshairs: {\n size: 1,\n icon: summonData.icon,\n label: `Summon ${summonData.actorName}`,\n drawOutline: false,\n rememberControlled: true\n }\n }\n const spawnMutation = {\n token: {\n actorLink: false,\n name: `${token.name}'s ${summonData.token.name}`\n }\n }\n await warpgate.spawn(summonData.actorName, spawnMutation, {}, spawnOptions)\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677996503821,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"RV09eJi9iG5bfupo","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Protection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_protection.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Protection')\n const changes = [\n {\n key: 'system.stats.toughness.armor',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE,\n value: 2,\n priority: 0\n }\n ]\n let effectName = 'minor Protection'\n if (choice === 'raise') {\n changes[0].key = 'system.stats.toughness.value'\n effectName = 'major Protection'\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(\n baseEffect.icon, effectName, 5, changes)\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677630174987,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"YETsNWOWfIxyLPdC","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Blind","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/svg/blind.svg","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Blind',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Blind' },\n { type: 'info', label: `Apply Blind to ${tokenList}` },\n { type: 'checkbox', label: 'Strong', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n raise: (buttons === 'raise'),\n strong: (!!inputs[2])\n }\n await createEffect(tokens, options)\n }\n}\n\nasync function createEffect (tokens, options) {\n const effectDetails = (options.raise ? '-4' : '-2')\n const effectEnd = (options.strong ? 'Vigor -2' : 'Vigor')\n const effectName = `Blind (${effectDetails}) ${effectEnd} ends`\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'EFFECT.StatusBlind')\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(baseEffect.icon, effectName, 1, [])\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Blind')\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.e9HvLMtaDw2qpcE8"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678165762773,"modifiedTime":1678167540828,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"e9HvLMtaDw2qpcE8","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Lingering Damage","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/acid/dissolve-arm-flesh.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Lingering Damage',\n content: `Apply Lingering Damage to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'Ok', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok') {\n await createEffect(tokens)\n }\n}\n\nasync function createEffect (tokens) {\n const icon = 'icons/magic/acid/dissolve-arm-flesh.webp'\n const effectName = 'Lingering Damage'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 1, [])\n mutate.embedded.ActiveEffect['Lingering Damage'].flags.swade.expiration =\n CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnPrompt\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677800587229,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"txJBrqgVNO3jpvFG","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Hinder","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/movement/abstract-ribbons-red-orange.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hinder',\n content: `Apply Hinder to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/movement/abstract-ribbons-red-orange.webp'\n const effectName = 'Hinder'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: -2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"uvHTdYUn5l3Z1rAV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -{"name":"Hurry","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/skills/movement/feet-winged-boots-blue.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hurry',\n content: `Apply Hurry to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/skills/movement/feet-winged-boots-blue.webp'\n const effectName = 'Hurry'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: 2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678167540883,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"yG1ZQO30ZlntYJp7","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Invisibility","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/svg/invisible.svg","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Invisibility',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Invisibility' },\n { type: 'info', label: `Apply Invisibility to ${tokenList}` },\n { type: 'checkbox', label: 'Duration', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n raise: (buttons === 'raise'),\n duration: (!!inputs[2])\n }\n await createEffect(tokens, options)\n }\n}\n\nasync function createEffect (tokens, options) {\n const effectName = `${options.raise ? 'major' : 'minor'} Invisibility`\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'EFFECT.StatusInvisible')\n const duration = (options.duration ? 5 * 6 * 60 : 5)\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(baseEffect.icon, effectName, duration, [])\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Blind')\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.11GOryzx2Q8MXbT6"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678168163811,"modifiedTime":1678168841533,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"11GOryzx2Q8MXbT6","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Boost/Lower Trait","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/life/cross-embers-glow-yellow-purple.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n let traitOptions = [\n 'Agility', 'Smarts', 'Spirit', 'Strength', 'Vigor'\n ]\n const allSkills = []\n const traits = {}\n for (const traitName of traitOptions) {\n const lower = traitName.toLowerCase()\n traits[traitName] = {\n name: traitName,\n type: 'attribute',\n modkey: `system.attributes.${lower}.die.modifier`,\n diekey: `system.attributes.${lower}.die.sides`\n }\n }\n\n const tokenList = tokens.map(t => t.name).join(', ')\n for (const token of tokens) {\n const skills = token.actor.items.filter(item => item.type === 'skill')\n for (const skill of skills) {\n const name = skill.name\n traits[name] = {\n type: 'skill',\n name,\n modkey: `@Skill{${name}}[system.die.modifier]`,\n diekey: `@Skill{${name}}[system.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\n const menuOptions = {\n title: 'Boost/Lower Trait',\n defaultButton: 'Cancel',\n options: {}\n }\n const 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: ['isBoost', true] },\n { type: 'radio', label: 'Lower', options: ['isBoost', false] },\n { type: 'checkbox', label: 'Greater', options: false },\n { type: 'checkbox', label: 'Strong (lower only)', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n action: buttons,\n name: inputs[2],\n trait: traits[inputs[2]],\n direction: inputs[4] || inputs[5],\n greater: inputs[6],\n strong: inputs[7]\n }\n createEffect(tokens, options)\n }\n}\n\nconst UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp'\nconst DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp'\n\nasync function createEffect (tokens, options) {\n const raise = (options.action === 'raise')\n const icon = (options.direction === 'Boost' ? UPICON : DOWNICON)\n let namePart = `${options.direction} ${options.trait.name}`\n const mode = CONST.ACTIVE_EFFECT_MODES.ADD\n const mods = []\n if (options.strong && options.direction === 'Lower') {\n mods.push('strong')\n }\n if (options.greater) {\n mods.push('greater')\n }\n if (mods.length > 0) {\n namePart = `${namePart} (${mods.join(', ')})`\n }\n const minorEffect = swadeMBHelpers.createEffectDocument(\n icon, `minor ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n const majorEffect = swadeMBHelpers.createEffectDocument(\n icon, `major ${namePart}`, 5, [\n {\n key: options.trait.diekey,\n mode,\n value: (options.direction === 'Boost' ? '+2' : '-2'),\n priority: 0\n }\n ]\n )\n if (options.direction === 'Lower' && options.greater === 'Greater') {\n minorEffect.changes.push({\n key: options.trait.modkey,\n mode,\n value: '-2',\n priority: 0\n })\n }\n const mutate = {\n embedded: {\n ActiveEffect: {\n }\n }\n }\n mutate.embedded.ActiveEffect[minorEffect.id] = minorEffect\n if (raise) {\n mutate.embedded.ActiveEffect[majorEffect.id] = majorEffect\n }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(namePart)\n for (const token of tokens) {\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677458254287,"modifiedTime":1678168841593,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"1AqIFHAcX5TRdE8X","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Entangle","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/nature/root-vine-barrier-wall-brown.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Entangle',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Entangle' },\n { type: 'info', label: `Apply Entangle to ${tokenList}` },\n { type: 'radio', label: 'Not Damaging', options: ['dmg', true] },\n { type: 'radio', label: 'Damaging', options: ['dmg', false] },\n { type: 'radio', label: 'Deadly', options: ['dmg', false] },\n { type: 'checkbox', label: 'Tough', options: false }\n ],\n buttons: [\n { label: 'Entangled', value: 'apply' },\n { label: 'Bound (raise)', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n apply: (buttons === 'raise' ? 'bound' : 'entangled'),\n damage: (inputs[3] ? '2d4' : (inputs[4] ? '2d6' : null)),\n tough: (!!inputs[5])\n }\n await createEffect(tokens, options)\n }\n}\n\nfunction getStatus (label, name) {\n const effect = JSON.parse(JSON.stringify(\n CONFIG.statusEffects.find(se => se.label === label)))\n effect.label = name\n if (!effect.flags) {\n effect.flags = {}\n }\n effect.flags.core = { statusId: effect.id }\n effect.id = name\n return effect\n}\n\nasync function createEffect (tokens, options) {\n const effectSearch = (options.apply === 'bound' ? 'SWADE.Bound' : 'SWADE.Entangled')\n const effectName = (options.apply === 'bound' ? 'Bound' : 'Entangled')\n const effect = getStatus(effectSearch, effectName)\n const extraIcon = 'icons/magic/nature/root-vine-barrier-wall-brown.webp'\n const extraEffect = swadeMBHelpers.createEffectDocument(extraIcon, 'Entangle Modifier', 1, [])\n\n if (options.damage) {\n extraEffect.id = `${extraEffect.id} - ${options.damage} dmg`\n extraEffect.label = `${extraEffect.label} - ${options.damage} dmg`\n }\n if (options.tough) {\n extraEffect.id = `Tough ${extraEffect.id}`\n extraEffect.label = `Tough ${extraEffect.label}`\n }\n for (const token of tokens) {\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Entangle')\n const mutate = { embedded: { ActiveEffect: {} } }\n mutate.embedded.ActiveEffect[effect.id] = effect\n if (options.damage || options.tough) {\n mutate.embedded.ActiveEffect[extraEffect.id] = extraEffect\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678164427219,"modifiedTime":1678168841593,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"2TOeRNCJT3T2px8D","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Smite","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_smite.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Smite',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Smite' },\n { type: 'info', label: `Apply Smite to ${tokenList}` },\n { type: 'checkbox', label: 'Greater', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with Raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const tokenWeapons = {}\n let index = 2\n for (const token of tokens) {\n index += 2\n tokenWeapons[token.id] = index\n menuData.inputs.push({ type: 'info', label: `

${token.name}

` })\n const weapons = token.actor.items.filter(i => i.type === 'weapon').map(\n i => { return { value: i.name, html: i.name } })\n weapons.unshift({ value: '', html: 'None' })\n menuData.inputs.push({ type: 'select', label: token.name, options: weapons })\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n for (const tokenId in tokenWeapons) {\n tokenWeapons[tokenId] = inputs[tokenWeapons[tokenId]]\n }\n const greater = (inputs[2] === 'Greater')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, tokenWeapons, buttons, greater)\n }\n}\n\nasync function createEffect (tokens, tokenWeapons, choice, greater) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Smite')\n const effectIcon = baseEffect.icon\n let changeValue = (choice === 'raise' ? '+4' : '+2')\n if (greater) {\n changeValue = (choice === 'raise' ? '+6' : '+4')\n }\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}}[system.damage]`\n if (!weaponId) {\n continue\n }\n const effectName = `${choice === 'raise' ? 'major' : 'minor'} Smite${greater ? '(greater)' : ''} (${weaponName})`\n const changes = [\n {\n key: changeKey,\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: changeValue,\n priority: 0\n }\n ]\n const mutate = swadeMBHelpers.createMutationWithEffect(\n effectIcon, effectName, 5, changes)\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.1GnCpp1vjEucgNGk"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677548889704,"modifiedTime":1678168841593,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"C1vGk7AKQDpcvKyP","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Deflection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/defensive/shield-barrier-deflect-teal.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/defensive/shield-barrier-deflect-teal.webp'\n let effectName = 'Deflection'\n if (choice === 'raise') {\n effectName = `${effectName} (all)`\n } else {\n effectName = `${effectName} (${choice})`\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677645552357,"modifiedTime":1678168841593,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"HYTiftQW0pwwOQGH","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Glow","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/light/explosion-star-blue-large.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Glow',\n content: `Apply Glow to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/light/explosion-star-blue-large.webp'\n const effectName = 'Glow'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.5,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'starlight'\n },\n bright: 0,\n color: '#0f3fff',\n coloration: 1,\n contrast: 0,\n dim: 0.5,\n luminosity: 0.5,\n saturation: 0,\n shadows: 0\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677704975699,"modifiedTime":1678168841593,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"JcZ9kxBZJpw8KLQ6","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Confusion","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/control/hypnosis-mesmerism-swirl.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Confusion',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Confusion' },\n { type: 'info', label: `Apply Confusion to ${tokenList}` },\n { type: 'checkbox', label: 'Greater (adds shaken)', options: false }\n ],\n buttons: [\n { label: 'Distracted', value: 'distracted' },\n { label: 'Vulnerable', value: 'vulnerable' },\n { label: 'Raise (both)', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n const greater = (inputs[2] === 'Greater (adds shaken)')\n if (buttons && buttons !== 'cancel') {\n await createEffect(tokens, buttons, greater)\n }\n}\n\nfunction getStatus (label, name) {\n const effect = JSON.parse(JSON.stringify(\n CONFIG.statusEffects.find(se => se.label === label)))\n effect.flags.core = { statusId: effect.id }\n effect.id = name\n return effect\n}\n\nasync function createEffect (tokens, choice, greater) {\n const effects = []\n if (choice === 'distracted' || choice === 'raise') {\n effects.push(getStatus('SWADE.Distr', 'Distracted'))\n }\n if (choice === 'vulnerable' || choice === 'raise') {\n effects.push(getStatus('SWADE.Vuln', 'Vulnerable'))\n }\n if (greater) {\n effects.push(getStatus('SWADE.Shaken', 'Shaken'))\n }\n for (const token of tokens) {\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Confusion')\n const mutate = {\n embedded: { ActiveEffect: {} }\n }\n for (const effect of effects) {\n mutate.embedded.ActiveEffect[effect.id] = effect\n }\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678082334572,"modifiedTime":1678168841593,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"L2IstecV7ivcrgUI","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Intangibility","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/control/debuff-energy-hold-levitate-blue-yellow.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Intangibility',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Intangibility' },\n { type: 'info', label: `Apply Intangibility to ${tokenList}` },\n { type: 'checkbox', label: 'Duration', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n duration: (!!inputs[2])\n }\n await createEffect(tokens, options)\n }\n}\n\nasync function createEffect (tokens, options) {\n const effectName = 'Intangibility'\n const duration = (options.duration ? 5 * 6 * 60 : 5)\n const icon = 'icons/magic/control/debuff-energy-hold-levitate-blue-yellow.webp'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, duration, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Intangibility')\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{"core":{"sourceId":"Macro.OMDjgWLJyE9BJAwT"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678168528898,"modifiedTime":1678168841533,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"OMDjgWLJyE9BJAwT","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Shroud","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/perception/silhouette-stealth-shadow.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Shroud',\n content: `Apply Shroud to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Mutate token lighting', value: 'mutate' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok' || choice === 'mutate') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/perception/silhouette-stealth-shadow.webp'\n const effectName = 'Shroud'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n if (choice === 'mutate') {\n const mutate2 = {\n token: {\n light: {\n alpha: 0.5,\n angle: 360,\n attenuation: 0.1,\n animation: {\n intensity: 5,\n reverse: false,\n speed: 5,\n type: 'roiling'\n },\n bright: 0,\n color: null,\n coloration: 0,\n contrast: 0,\n dim: 0.1,\n luminosity: -0.15,\n saturation: 0,\n shadows: 0.25\n }\n }\n }\n mutateOptions.permanent = false\n await warpgate.mutate(token.document, mutate2, {}, mutateOptions)\n }\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677649631598,"modifiedTime":1678168841593,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"QpillIBvZmuHeuTV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Summon","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/symbols/runes-star-orange.webp","scope":"global","command":"const ACTORFOLDER = 'Summonables'\nconst SUMMONICON = 'icons/magic/symbols/runes-star-orange.webp'\n\nswadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const token = tokens[0]\n const tokenList = token.name\n const folder = swadeMBHelpers.getActorFolderByPath(ACTORFOLDER)\n const actors = swadeMBHelpers.getActorsInFolder(folder)\n const menuOptions = {\n title: 'Summon Creature',\n defaultButton: 'cancel',\n options: {}\n }\n const menuData = {\n inputs: [\n { type: 'header', label: 'Summon Creature' },\n { type: 'info', label: `${tokenList} is summoning` },\n {\n type: 'select',\n label: 'Ally to summon',\n options: Object.keys(actors).sort().map(k => { return { value: actors[k].id, html: k } })\n },\n { type: 'number', label: 'Number to spawn (+half base cost per)', options: 1 }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Apply with raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const summonData = {\n raise: (buttons === 'raise'),\n actorId: inputs[2],\n number: inputs[3]\n }\n summonData.actor = game.actors.get(summonData.actorId)\n summonData.actorName = summonData.actor.name\n summonData.icon = summonData.actor.prototypeToken.texture.src\n summonData.token = summonData.actor.prototypeToken\n\n doWork(summonData, token)\n }\n}\n\nasync function doWork (summonData, token) {\n console.log('Summon ', token, summonData)\n const effectName = `Summoned ${summonData.actorName} (${summonData.number})`\n const tokenEffectMutation = swadeMBHelpers.createMutationWithEffect(SUMMONICON, effectName, 5, [])\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, tokenEffectMutation, {}, mutateOptions)\n\n const spawnOptions = {\n controllingActor: token.actor,\n duplicates: summonData.number,\n comparisonKeys: { ActiveEffect: 'label' },\n crosshairs: {\n size: 1,\n icon: summonData.icon,\n label: `Summon ${summonData.actorName}`,\n drawOutline: false,\n rememberControlled: true\n }\n }\n const spawnMutation = {\n token: {\n actorLink: false,\n name: `${token.name}'s ${summonData.token.name}`\n }\n }\n await warpgate.spawn(summonData.actorName, spawnMutation, {}, spawnOptions)\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677996503821,"modifiedTime":1678168841593,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"RV09eJi9iG5bfupo","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Protection","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"systems/swade/assets/icons/status/status_protection.svg","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const 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\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice && choice !== 'cancel') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'SWADE.Protection')\n const changes = [\n {\n key: 'system.stats.toughness.armor',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.UPGRADE,\n value: 2,\n priority: 0\n }\n ]\n let effectName = 'minor Protection'\n if (choice === 'raise') {\n changes[0].key = 'system.stats.toughness.value'\n effectName = 'major Protection'\n }\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(\n baseEffect.icon, effectName, 5, changes)\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677630174987,"modifiedTime":1678168841593,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"YETsNWOWfIxyLPdC","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Blind","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/svg/blind.svg","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const menuOptions = {\n title: 'Blind',\n defaultButton: 'Cancel',\n options: {}\n }\n\n const menuData = {\n inputs: [\n { type: 'header', label: 'Blind' },\n { type: 'info', label: `Apply Blind to ${tokenList}` },\n { type: 'checkbox', label: 'Strong', options: false }\n ],\n buttons: [\n { label: 'Apply', value: 'apply' },\n { label: 'Raise', value: 'raise' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const { buttons, inputs } = await warpgate.menu(menuData, menuOptions)\n if (buttons && buttons !== 'cancel') {\n const options = {\n raise: (buttons === 'raise'),\n strong: (!!inputs[2])\n }\n await createEffect(tokens, options)\n }\n}\n\nasync function createEffect (tokens, options) {\n const effectDetails = (options.raise ? '-4' : '-2')\n const effectEnd = (options.strong ? 'Vigor -2' : 'Vigor')\n const effectName = `Blind (${effectDetails}) ${effectEnd} ends`\n const baseEffect = CONFIG.statusEffects.find(se => se.label === 'EFFECT.StatusBlind')\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(baseEffect.icon, effectName, 1, [])\n mutate.embedded.ActiveEffect[effectName].flags.core = { statusId: baseEffect.id }\n const mutateOptions = swadeMBHelpers.defaultMutationOptions('Blind')\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678165762773,"modifiedTime":1678168841593,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"e9HvLMtaDw2qpcE8","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Lingering Damage","type":"script","scope":"global","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/acid/dissolve-arm-flesh.webp","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Lingering Damage',\n content: `Apply Lingering Damage to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'Ok', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions)\n\n if (choice === 'ok') {\n await createEffect(tokens)\n }\n}\n\nasync function createEffect (tokens) {\n const icon = 'icons/magic/acid/dissolve-arm-flesh.webp'\n const effectName = 'Lingering Damage'\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 1, [])\n mutate.embedded.ActiveEffect['Lingering Damage'].flags.swade.expiration =\n CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnPrompt\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677800587229,"modifiedTime":1678168841594,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"txJBrqgVNO3jpvFG","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Hinder","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/magic/movement/abstract-ribbons-red-orange.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hinder',\n content: `Apply Hinder to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/magic/movement/abstract-ribbons-red-orange.webp'\n const effectName = 'Hinder'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: -2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678168841594,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"uvHTdYUn5l3Z1rAV","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} +{"name":"Hurry","type":"script","author":"ueJGUfSYuRRL3Ypr","img":"icons/skills/movement/feet-winged-boots-blue.webp","scope":"global","command":"swadeMBHelpers.runOnTargetOrSelectedTokens(main)\n\nasync function main (tokens) {\n const tokenList = tokens.map(t => t.name).join(', ')\n const dialogOptions = {\n title: 'Hurry',\n content: `Apply Hurry to ${tokenList}`,\n default: 'cancel',\n buttons: [\n { label: 'OK', value: 'ok' },\n { label: 'Cancel', value: 'cancel' }\n ]\n }\n\n const choice = await warpgate.buttonDialog(dialogOptions, 'column')\n\n if (choice === 'ok') {\n await createEffect(tokens, choice)\n }\n}\n\nasync function createEffect (tokens, choice) {\n const icon = 'icons/skills/movement/feet-winged-boots-blue.webp'\n const effectName = 'Hurry'\n const changes = [\n {\n key: 'system.stats.speed.value',\n mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,\n value: 2,\n priority: 0\n }\n ]\n for (const token of tokens) {\n const mutate = swadeMBHelpers.createMutationWithEffect(icon, effectName, 5, changes)\n const mutateOptions = swadeMBHelpers.defaultMutationOptions(effectName)\n await warpgate.mutate(token.document, mutate, {}, mutateOptions)\n }\n}","flags":{},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1677802063142,"modifiedTime":1678168841594,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"yG1ZQO30ZlntYJp7","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -- 2.30.2 From 2453a595944d36c60441a7803730ecacecac4c48 Mon Sep 17 00:00:00 2001 From: Mike Bloy Date: Tue, 7 Mar 2023 00:16:47 -0600 Subject: [PATCH 7/7] prep for 1.0 release, add docs --- CHANGELOG.md | 3 +++ README.md | 5 ++++- module.json | 2 +- packs/module-docs.db | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b965ca..acc3471 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## 1.0.0 + ### Added +- Added Documentation and README - Confusion effect macro - Entangle effect macro - Blind effect macro diff --git a/README.md b/README.md index 0e1fa64..6aabb51 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ -# swade-mb-helpers +# SWADE Helpers (MB) +This is a series of helper macros and other helpers to help run SWADE and +Savage Pathfinder games with some minimal help remembering token state, without +going overboard on the automation. diff --git a/module.json b/module.json index b4dfa3f..3a3db67 100644 --- a/module.json +++ b/module.json @@ -3,7 +3,7 @@ "name": "SWADE Helpers (MB)", "title": "SWADE Helpers (MB)", "description": "Mike's collection of swade helpers", - "version": "0.9.0", + "version": "1.0.0", "authors": [ { "name": "Mike" diff --git a/packs/module-docs.db b/packs/module-docs.db index e69de29..05c7f2f 100644 --- a/packs/module-docs.db +++ b/packs/module-docs.db @@ -0,0 +1 @@ +{"name":"Macros","pages":[{"sort":100000,"name":"Effect Macros","type":"text","_id":"i31qmsZnIGhjvA2K","title":{"show":true,"level":1},"image":{},"text":{"format":1,"content":"

The effect macros found in the SWADE MB Effect Macros compendium are all set up to handle applying effects to multiple tokens at once, with one exception, the Summon macro.

Summon Macro

The Summon macro expects to have one and only one target, and depends on the existence of an Actor folder called \"Summonables\" on the Actor sidebar. If this folder has subfolders, they'll be used by the macro to sort the list of available summonables. In the Summonables folder and subfolders, place the Actors that are available for summoning.

","markdown":""},"video":{"controls":true,"volume":0.5},"src":null,"system":{},"ownership":{"default":-1},"flags":{}}],"flags":{"core":{"sourceId":"JournalEntry.Mw1g2Fx5dp4SoqVP"}},"_stats":{"systemId":"swade","systemVersion":"2.2.5","coreVersion":"10.291","createdTime":1678169291843,"modifiedTime":1678169602285,"lastModifiedBy":"ueJGUfSYuRRL3Ypr"},"_id":"Mw1g2Fx5dp4SoqVP","folder":null,"sort":0,"ownership":{"default":0,"ueJGUfSYuRRL3Ypr":3}} -- 2.30.2