swadeMBHelpers.runOnTargetOrSelectedTokens(main) async function main (tokens) { let traitOptions = [ 'Agility', 'Smarts', 'Spirit', 'Strength', 'Vigor' ] const allSkills = [] const traits = {} for (const traitName of traitOptions) { const lower = traitName.toLowerCase() traits[traitName] = { name: traitName, type: 'attribute', modkey: `system.attributes.${lower}.die.modifier`, diekey: `system.attributes.${lower}.die.sides` } } const tokenList = tokens.map(t => t.name).join(', ') for (const token of tokens) { const skills = token.actor.items.filter(item => item.type === 'skill') for (const skill of skills) { const name = skill.name traits[name] = { type: 'skill', name, modkey: `@Skill{${name}}[system.die.modifier]`, diekey: `@Skill{${name}}[system.die.sides]` } if (name !== 'Unskilled' && !allSkills.find(v => v === name)) { allSkills.push(name) } } } traitOptions = traitOptions.concat(allSkills.sort()) const menuOptions = { title: 'Boost/Lower Trait', defaultButton: 'Cancel', options: {} } const menuData = { inputs: [ { type: 'header', label: 'Boost/Lower Trait' }, { type: 'info', label: `Affected Tokens ${tokenList}` }, { type: 'select', label: 'Trait', options: traitOptions }, { type: 'info', label: 'Boost or Lower?' }, { type: 'radio', label: 'Boost', options: ['isBoost', true] }, { type: 'radio', label: 'Lower', options: ['isBoost', false] }, { type: 'checkbox', label: 'Greater', options: false }, { type: 'checkbox', label: 'Strong (lower only)', options: false } ], buttons: [ { label: 'Apply', value: 'apply' }, { label: 'Apply with raise', value: 'raise' }, { label: 'Cancel', value: 'cancel' } ] } const { buttons, inputs } = await warpgate.menu(menuData, menuOptions) if (buttons !== 'cancel') { const options = { action: buttons, name: inputs[2], trait: traits[inputs[2]], direction: inputs[4] || inputs[5], greater: inputs[6], strong: inputs[7] } createEffect(tokens, options) } } const UPICON = 'icons/magic/life/cross-embers-glow-yellow-purple.webp' const DOWNICON = 'icons/magic/movement/chevrons-down-yellow.webp' async function createEffect (tokens, options) { const raise = (options.action === 'raise') const icon = (options.direction === 'Boost' ? UPICON : DOWNICON) let namePart = `${options.direction} ${options.trait.name}` const mode = CONST.ACTIVE_EFFECT_MODES.ADD const mods = [] if (options.strong && options.direction === 'Lower') { mods.push('strong') } if (options.greater) { mods.push('greater') } if (mods.length > 0) { namePart = `${namePart} (${mods.join(', ')})` } const minorEffect = { icon, id: `minor ${namePart}`, label: `minor ${namePart}`, duration: { rounds: 5 }, flags: { swade: { expiration: CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.EndOfTurnPrompt, loseTurnOnHold: true } }, changes: [ { key: options.trait.diekey, mode, value: (options.direction === 'Boost' ? '+2' : '-2'), priority: 0 } ] } const majorEffect = { icon, id: `major ${namePart}`, label: `major ${namePart}`, duration: { rounds: 5 }, flags: { swade: { expiration: CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.EndOfTurnPrompt, loseTurnOnHold: true } }, changes: [ { key: options.trait.diekey, mode, value: (options.direction === 'Boost' ? '+2' : '-2'), priority: 0 } ] } if (options.direction === 'Lower' && options.greater === 'Greater') { minorEffect.changes.push({ key: options.trait.modkey, mode, value: '-2', priority: 0 }) } const mutate = { embedded: { ActiveEffect: { } } } mutate.embedded.ActiveEffect[minorEffect.id] = minorEffect if (raise) { mutate.embedded.ActiveEffect[majorEffect.id] = majorEffect } const mutateOptions = { comparisonKeys: { ActiveEffect: 'label' }, name: namePart, permanent: true, description: namePart } for (const token of tokens) { await warpgate.mutate(token.document, mutate, {}, mutateOptions) } }