diff --git a/CHANGELOG.md b/CHANGELOG.md index 178ec33..71a7d74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,21 @@ 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). +## [3.0.0] UNRELEASED + +### Changed + +- Refactor and redo of powers handling + - maintained powers + - powerpoint calculation + - more powers +- Refactor of distribution + - Code is minified into one file for faster loading + +### Removed + +- Began work to remove Warpgate dependency + ## [2.4.3] 2024-04-21 ### Added diff --git a/src/module/globals.js b/src/module/globals.js index d2746a8..434734c 100644 --- a/src/module/globals.js +++ b/src/module/globals.js @@ -1,126 +1,77 @@ /* globals coreFearDialog */ /* globals swpfFearDialog */ -/* globals warpgate */ -export const moduleName = 'swade-mb-helpers' +export const moduleName = 'swade-mb-helpers'; -export function log (...args) { - console.log('SWADE MB HELPERS |', ...args) +export function log(...args) { + console.log('SWADE MB HELPERS |', ...args); } export class moduleHelpers { - static _socket = null + static _socket = null; - static get socket () { - return moduleHelpers._socket + static get socket() { + return moduleHelpers._socket; } - static get rulesVersion () { + static get rulesVersion() { if (game.modules.get('swpf-core-rules')?.active) { - return 'swpf' + return 'swpf'; } if (game.modules.get('swade-core-rules')?.active) { - return 'swade' + return 'swade'; } - return 'system' + return 'system'; } - static async applyActiveEffects (token, effectDocuments) { - const mutation = { - embedded: { ActiveEffect: {} } - } - const mutateOptions = { - permanent: true, - description: effectDocuments[effectDocuments.length - 1]?.name - } - for (const effectDocument of effectDocuments) { - mutation.embedded.ActiveEffect[effectDocument.name] = effectDocument - } - await warpgate.mutate(token.document, mutation, {}, mutateOptions) - } - - static getStatus (label, name, favorite = true) { - const effect = JSON.parse(JSON.stringify( - CONFIG.statusEffects.find(se => se.label === label))) - effect.name = ('name' in effect ? effect.name : effect.label) - if (!('flags' in effect)) { - effect.flags = {} - } - if (favorite) { - if (!('swade' in effect.flags)) { - effect.flags.swade = {} - } - effect.flags.swade.favorite = true - } - effect.flags.core = { statusId: effect.id } - return effect - } - - static createEffectDocument (icon, name, durationRounds, changes = null) { - if (changes === null) { - changes = [] - } - return { - icon, - name, - duration: { rounds: durationRounds }, - changes, - flags: { - swade: { - favorite: true, - expiration: CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.EndOfTurnPrompt - } - } - } - } - - static getActorFolderByPath (path) { - const names = path.split('/') + static getActorFolderByPath(path) { + const names = path.split('/'); if (names[0] === '') { - names.shift() + names.shift(); + } + let name = names.shift(); + let folder = game.folders.filter((f) => f.type === 'Actor' && !f.folder).find((f) => f.name === name); + if (!folder) { + return undefined; } - let name = names.shift() - let folder = game.folders.filter( - f => f.type === 'Actor' && !f.folder - ).find(f => f.name === name) - if (!folder) { return undefined } while (names.length > 0) { - name = names.shift() - folder = folder.children.find(c => c.folder.name === name) - if (!folder) { return undefined } - folder = folder.folder + name = names.shift(); + folder = folder.children.find((c) => c.folder.name === name); + if (!folder) { + return undefined; + } + folder = folder.folder; } - return folder + return folder; } - static getActorsInFolder (inFolder) { - const prefixStack = [''] - const actors = {} - const folderStack = [inFolder] + static getActorsInFolder(inFolder) { + const prefixStack = ['']; + const actors = {}; + const folderStack = [inFolder]; while (folderStack.length > 0) { - const prefix = prefixStack.shift() - const folder = folderStack.shift() + const prefix = prefixStack.shift(); + const folder = folderStack.shift(); for (const actor of folder.contents) { - if (game.user.isGM || - actor.testUserPermission( - game.user, foundry.CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER) - ) { - actors[`${prefix}${actor.name}`] = actor + if (game.user.isGM || actor.testUserPermission(game.user, foundry.CONST.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) + const newPrefix = `${prefix}${child.folder.name} | `; + prefixStack.push(newPrefix); + folderStack.push(child.folder); } } - return actors + return actors; } - static get fearTableHelper () { + static get fearTableHelper() { switch (moduleHelpers.rulesVersion) { - case 'swade': return coreFearDialog // defined as global by the swade module - case 'swpf': return swpfFearDialog // defined as global by the swpf module + case 'swade': + return coreFearDialog; // defined as global by the swade module + case 'swpf': + return swpfFearDialog; // defined as global by the swpf module } - throw new ReferenceError('No premium module active. No fear table found') + throw new ReferenceError('No premium module active. No fear table found'); } } diff --git a/src/module/helpers.js b/src/module/helpers.js index 6b861f2..0b5fbc0 100644 --- a/src/module/helpers.js +++ b/src/module/helpers.js @@ -1,4 +1,3 @@ -/* global warpgate */ import { moduleHelpers } from './globals.js'; export async function requestFearRollFromTokens(tokens, options = {}) { @@ -19,6 +18,27 @@ export async function requestFearRollFromTokens(tokens, options = {}) { return requestRollFromTokens(tokens, 'attribute', 'spirit', rollOpts); } +export function firstOwner(doc) { + // lifted from warpgate + // https://github.com/trioderegion/warpgate/blob/master/src/scripts/module.js + if (!doc) return undefined; + const corrected = doc instanceof TokenDocument ? doc.actor : doc instanceof Token ? doc.document.actor : doc; + const permissionObject = getProperty(corrected ?? {}, 'ownership'); + const playerOwners = Object.entries(permissionObject) + .filter(([id, level]) => !game.users.get(id)?.isGM && game.users.get(id)?.active && level === 3) + .map(([id]) => id); + if (playerOwners.length > 0) { + return game.users.get(playerOwners[0]); + } + return firstGM(); +} + +export function firstGM() { + // lifted from warpgate + // https://github.com/trioderegion/warpgate/blob/master/src/scripts/module.js + return game.users?.find((u) => u.isGM && u.active); +} + export async function requestRollFromTokens(tokens, rollType, rollDesc, options = {}) { // tokens: list of tokens to request a roll from // rollType: 'attribute' or 'skill @@ -37,7 +57,7 @@ export async function requestRollFromTokens(tokens, rollType, rollDesc, options const targetNumber = options?.targetNumber || 4; const promises = []; for (const token of tokens) { - const owner = warpgate.util.firstOwner(token.document); + const owner = firstOwner(token.document); const rollOpts = { title: `${title} - ${token.name}`, targetNumber, diff --git a/src/module/powers/basePowers.js b/src/module/powers/basePowers.js index c12b6fa..0bccc72 100644 --- a/src/module/powers/basePowers.js +++ b/src/module/powers/basePowers.js @@ -132,17 +132,6 @@ export class PowerEffect { async applyActiveEffects(token, effectDocuments) { await token.actor.createEmbeddedDocuments('ActiveEffect', effectDocuments); - // const mutation = { - // embedded: { ActiveEffect: {} }, - // }; - // const mutateOptions = { - // permanent: true, - // description: `${this.source.name} applying ${effectDocuments[effectDocuments.length - 1]?.name} to ${token.name}`, - // }; - // for (const effectDocument of effectDocuments) { - // mutation.embedded.ActiveEffect[effectDocument.name] = effectDocument; - // } - // await warpgate.mutate(token.document, mutation, {}, mutateOptions); } get name() { diff --git a/src/module/powers/powers.js b/src/module/powers/powers.js index 82ab067..d1c6b7c 100644 --- a/src/module/powers/powers.js +++ b/src/module/powers/powers.js @@ -1,4 +1,3 @@ -/* globals warpgate */ import { moduleName } from '../globals.js'; import { ArcaneProtectionEffect } from './arcaneProtection.js'; import { BanishEffect } from './banish.js'; @@ -54,27 +53,17 @@ export async function powerEffectManagementHook(effect, data, userId) { if (!maintId) { return; } - const mutateOptions = { - permanent: true, - comparisonKeys: { - ActiveEffect: 'id', - }, - }; const targetIds = effect.getFlag(moduleName, 'targetIds') || []; for (const targetId of targetIds) { - const mutation = { - embedded: { ActiveEffect: {} }, - }; const target = canvas.tokens.get(targetId); if (!target) { continue; } - const effects = target.actor.effects.filter((e) => e.getFlag(moduleName, 'maintId') === maintId); - for (const efct of effects) { - mutation.embedded.ActiveEffect[efct.id] = warpgate.CONST.DELETE; + const effectIds = target.actor.effects.filter((e) => e.getFlag(moduleName, 'maintId') === maintId).map((e) => e.id); + if (effectIds.length === 0) { + continue; } - mutateOptions.description = `${effect.parent.name} is no longer ${effect.name} on ${target.name}`; - await warpgate.mutate(target.document, mutation, {}, mutateOptions); + await target.actor.deleteEmbeddedDocuments('ActiveEffects', effectIds); } }