diff --git a/src/module/powers/basePowers.js b/src/module/powers/basePowers.js index 9ddb5d0..537b63f 100644 --- a/src/module/powers/basePowers.js +++ b/src/module/powers/basePowers.js @@ -1,4 +1,4 @@ -import { moduleName, moduleHelpers } from '../globals.js'; +import { moduleName, moduleHelpers, log } from '../globals.js'; import { firstOwner, addActiveEffectsToToken } from '../helpers.js'; import { templates } from '../preloadTemplates.js'; @@ -236,6 +236,10 @@ export class PowerEffect { return false; } + get hasRange() { + return true; + } + get isRaisable() { return true; } @@ -386,24 +390,26 @@ export class PowerEffect { isGlobal: true, }); } - mods.push({ - type: 'select', - default: 0, - name: 'Range', - id: 'range', - choices: { - normal: 'Normal Range', - x2: 'Range ×2', - x3: 'Range ×3', - }, - values: { - normal: 0, - x2: 1, - x3: 2, - }, - isGlobal: true, - effects: { normal: null, x2: null, x3: null }, - }); + if (this.hasRange) { + mods.push({ + type: 'select', + default: 0, + name: 'Range', + id: 'range', + choices: { + normal: 'Normal Range', + x2: 'Range ×2', + x3: 'Range ×3', + }, + values: { + normal: 0, + x2: 1, + x3: 2, + }, + isGlobal: true, + effects: { normal: null, x2: null, x3: null }, + }); + } return mods; } @@ -682,3 +688,49 @@ export class PowerEffect { ); } } + +export class ActorFolderEffect extends PowerEffect { + get actorFolderBase() { + return 'PowerActors'; + } + + get actorFolder() { + return `${this.actorFolderBase}/${this.name}`; + } + + prepFolders() { + const folders = []; + const folderNames = [ + this.actorFolder, + `${this.actorFolder} - Default`, + `${this.actorFolder}/Default`, + `${this.actorFolder} - ${this.source.name}`, + `${this.actorFolder} - ${this.source.actor.name}`, + `${this.actorFolder}/${this.source.name}`, + `${this.actorFolder}/${this.source.actor.name}`, + ]; + for (const folderName of folderNames) { + const folder = moduleHelpers.getActorFolderByPath(folderName); + if (folder) { + log(`Found actor folder ${folderName}`); + folders.push(folder); + } + } + if (folders.length > 1) { + folders.shift(); + } + return folders; + } + + prepActors() { + const folders = this.prepFolders(); + const actors = {}; + for (const folder of folders) { + const folderActors = moduleHelpers.getActorsInFolder(folder); + for (const key in folderActors) { + actors[key] = folderActors[key]; + } + } + return actors; + } +} diff --git a/src/module/powers/powers.js b/src/module/powers/powers.js index 2a4dd02..1c25459 100644 --- a/src/module/powers/powers.js +++ b/src/module/powers/powers.js @@ -48,6 +48,7 @@ import { ReliefEffect } from './relief.js'; import { ResurrectionEffect } from './resurrection.js'; import { SanctuaryEffect } from './sanctuary.js'; import { ScryingEffect } from './scrying.js'; +import { ShapeChangeEffect } from './shapeChange.js'; const PowerClasses = { 'arcane-protection': ArcaneProtectionEffect, @@ -109,6 +110,7 @@ const PowerClasses = { resurrection: ResurrectionEffect, sanctuary: SanctuaryEffect, scrying: ScryingEffect, + 'shape-change': ShapeChangeEffect, shrink: GrowthShrinkEffect, }; diff --git a/src/module/powers/shapeChange.js b/src/module/powers/shapeChange.js new file mode 100644 index 0000000..67d40d8 --- /dev/null +++ b/src/module/powers/shapeChange.js @@ -0,0 +1,107 @@ +import { ActorFolderEffect } from './basePowers.js'; + +export class ShapeChangeEffect extends ActorFolderEffect { + get name() { + return 'Shape Change'; + } + + get icon() { + return 'icons/magic/control/silhouette-hold-change-blue.webp'; + } + + get duration() { + return this.data.duration ? 50 : 5; + } + + get isTargeted() { + return true; + } + + get isRaisable() { + return true; + } + + get basePowerPoints() { + return 0; + } + + get hasRange() { + return false; + } + + get actorFolderBase() { + return 'Morphables'; + } + + getShapeChangeActors() { + this.data.actors = this.prepActors(); + const choices = {}; + const effects = {}; + const values = {}; + Object.keys(this.data.actors) + .filter((k) => !k.includes('_template')) + .sort() + .forEach((key) => { + const id = this.data.actors[key].id; + const size = this.data.actors[key].system.stats.size; + let value = 3; + if (size >= 5) { + value = 15; + } else if (size >= 3) { + value = 11; + } else if (size >= 1) { + value = 8; + } else if (size >= 0) { + value = 5; + } + choices[id] = key; + effects[id] = null; + values[id] = value; + }); + return { choices, effects, values }; + } + + get modifiers() { + const { choices, effects, values } = this.getShapeChangeActors(); + return [ + ...super.modifiers, + { + name: 'Shape Change Into', + id: 'actorId', + type: 'select', + choices, + effects, + values, + epic: false, + effect: false, + }, + { + name: 'Duration', + type: 'checkbox', + value: 1, + id: 'duration', + epic: false, + effect: false, + }, + { + name: 'Transform', + type: 'select', + default: 'none', + id: 'transform', + epic: true, + choices: { + none: 'None', + touch: '⭐ Transform (touch)', + smarts: '⭐ Transform (smarts)', + }, + effects: { none: null, touch: null, smarts: null }, + values: { none: 0, touch: 2, smarts: 3 }, + }, + ]; + } + + get description() { + let desc = super.description; + return desc; + } +}