diff --git a/scripts/api.js b/scripts/api.js index 1a5fd51..1815d69 100644 --- a/scripts/api.js +++ b/scripts/api.js @@ -1,5 +1,5 @@ -import { helpers } from './helpers.js' -import { shim, log } from './shim.js' +import { log } from './shim.js' +import { requestRollFromTokens } from './helpers.js' import { powerEffects } from './powerEffects.js' export class api { @@ -12,7 +12,8 @@ export class api { const moduleName = 'swade-mb-helpers' game.modules.get(moduleName).api = { DEBUG: true, - powerEffects + powerEffects, + requestRollFromTokens } } } diff --git a/scripts/helpers.js b/scripts/helpers.js index 553e929..46f50a3 100644 --- a/scripts/helpers.js +++ b/scripts/helpers.js @@ -1,92 +1,58 @@ -import { CONST, shim } from './shim.js' +import { shim } from './shim.js' -export class helpers { - static runOnTargetOrSelectedTokens (runFunc) { - let tokens = [] - const targets = Array.from(shim.targets) - if (targets.length > 0) { - tokens = targets - } else if (shim.controlled.length > 0) { - tokens = shim.controlled - } - if (tokens.length > 0) { - runFunc(tokens) - } else { - shim.notifications.error('Please select or target a token') - } - } - - static createEffectDocument (icon, name, durationRounds, changes) { - const effectData = { - icon, - name, - duration: { rounds: durationRounds }, - flags: { - swade: { - expiration: CONST.SWADE.STATUS_EFFECT_EXPIRATION.EndOfTurnPrompt, - loseTurnOnHold: true - } - }, - changes - } - return effectData - } - - static createMutationWithEffect (icon, name, durationRounds, changes) { - const effect = helpers.createEffectDocument(icon, name, durationRounds, changes) - const mutate = { - embedded: { ActiveEffect: {} } - } - mutate.embedded.ActiveEffect[name] = effect - return mutate - } - - static defaultMutationOptions (name) { - const mutateOptions = { - name, - permanent: true, - description: name - } - return mutateOptions - } - - static getActorFolderByPath (path) { - const names = path.split('/') - if (names[0] === '') { - names.shift() - } - let name = names.shift() - let folder = shim.folders.find(f => f.name === name && !f.folder) - while (names.length > 0) { - name = names.shift() - folder = folder.children.find(c => c.folder.name === name) - folder = folder.folder - } - return folder - } - - static getActorsInFolder (inFolder) { - const prefixStack = [''] - const actors = {} - const folderStack = [inFolder] - - while (folderStack.length > 0) { - const prefix = prefixStack.shift() - const folder = folderStack.shift() - for (const actor of folder.contents) { - if ( - shim.user.isGM || actor.testUserPermission( - shim.user, CONST.FOUNDRY.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER) - ) { - actors[`${prefix}${actor.name}`] = actor - } - } - for (const child of folder.children) { - const newPrefix = `${prefix}${child.folder.name} | ` - prefixStack.push(newPrefix) - folderStack.push(child.folder) - } - } - return actors +export async function requestRollFromTokens (tokens, rollType, rollDesc, options = {}) { + // tokens: list of tokens to request a roll from + // rollType: 'attribute' or 'skill + // rollDesc: name of attribute or skill + // options: + // title: title for the roll dialog. Will have "- {{ token name }}" + // appended + // mods: list of modifiers {label: "", value: 0, ignore: false} + // modCallback: callback function that takes a token and returns a list of + // modifiers in the same format as modifiers, above + options.requestingUserId = shim.user.id + const promises = [] + for (const token in tokens) { + const owner = shim.warpgateUtil.firstOwner(token.document) + promises.append(shim.socket.executeAsUser(requestTokenRoll, owner.id, + token.scene.id, token.id, rollType, rollDesc, options)) } + results = await Promise.allSettled(promises) + return results +} + +export async function requestTokenRoll ( + sceneId, tokenId, rollType, rollDesc, options +) { + const requestingUser = shim.users.get(options.requestingUserId) + const scene = shim.scenes.get(sceneId) + const token = scene.tokens.get(tokenId) + const additionalMods = [] + if ('mods' in options) { + for (const mod of options.mods) { + additionalMods.push(mod) + } + } + if ('modCallback' in options) { + const tokenMods = await options.modCallback(token) + for (const tm of tokenMods) { + additionalMods.push(tm) + } + } + let rollFunc = token.actor.rollAttribute + let rollId = rollDesc.toLowerCase() + if (rollType === 'skill') { + rollFunc = token.actor.rollSkill + rollId = token.actor.items.find(i => ( + (i.system.swid === rollDesc.toLowerCase() || + i.name.toLowerCase() === rollDesc.toLowerCase()) && i.type === 'skill')) + } + const rollOpts = { + title: options?.title || `${requestingUser.name} requests a ${rollDesc} roll` + } + if (additionalMods.length > 0) { + rollOpts.additionalMods = additionalMods + } + const result = await rollFunc(rollId, rollOpts) + return { sceneId, tokenId, result } } diff --git a/scripts/module.js b/scripts/module.js index 06a19a7..0498760 100644 --- a/scripts/module.js +++ b/scripts/module.js @@ -1,4 +1,5 @@ import { api } from './api.js' +import { requestTokenRoll } from './helpers.js' import { havocResult, shapeChangeOnDismiss } from './powerEffects.js' import { log, shim } from './shim.js' @@ -25,5 +26,6 @@ Hooks.on('ready', () => { Hooks.on('socketlib.ready', () => { const socket = socketlib.registerModule('swade-mb-helpers') socket.register('havocResult', havocResult) + socket.register('requestTokenRoll', requestTokenRoll) shim._socket = socket }) diff --git a/scripts/shim.js b/scripts/shim.js index cb7d026..f5b2aee 100644 --- a/scripts/shim.js +++ b/scripts/shim.js @@ -41,6 +41,10 @@ export class shim { return game.user } + static get users () { + return game.users + } + static get notifications () { return ui.notifications }