import { moduleName } from './globals.js' import { PowerEffect } from './basePowers.js' class ArcaneProtectionEffect extends PowerEffect { get name () { return 'Arcane Protection' } get duration () { return 5 } get icon () { return 'icons/magic/defensive/shield-barrier-flaming-pentagon-blue.webp' } get hasAdditionalRecipients () { return true } get additionalRecipientCost () { return 1 } get isTargeted () { return true } get modifiers () { const mods = super.modifiers mods.push({ name: 'Greater Arcane Protection', id: 'greater', value: 2, epic: true, effect: false }) return mods } get effectName () { const greater = this.data.mods.has('greater') const raise = this.data.raise const amount = (raise ? -4 : -2) + (greater ? -2 : 0) return `${greater ? 'Greater ' : ''}Arcane Protection (${raise ? 'major, ' : ''}${amount})` } } class BanishEffect extends PowerEffect { get name () { return 'Banish' } get duration () { return 0 } get basePowerPoints () { return 3 } get usePrimaryEffect () { return false } get isTargeted () { return true } get menuInputs () { const inputs = super.menuInputs inputs.push inputs.push({ type: 'select', label: '⭐ Area of Effect', options: [ {html: 'None', value: 0, selected: true}, {html: 'Small Blast Template (+1)', value: 1, selected: false}, {html: 'Medium Blast Template (+2)', value: 1, selected: false}, {html: 'Large Blast Template (+3)', value: 1, selected: false}, ]}) return inputs } get powerPoints () { let total = super.powerPoints total += this.data.aoe return total } get chatMessageEffects () { const list = [] switch (this.data.aoe) { case 0: break case 1: list.push('SBT') break case 2: list.push('MBT') break case 3: list.push('LBT') break } list.push("Opposed Roll: caster's arcane skill vs target's Spirit.") list.push("Success: Shaken, Each Raise: 1 Wound") list.push("If target incapacitated by this, banishment to home plane") return list } async parseValues () { await super.parseValues() this.data.aoe = this.data.values.shift() } } class BarrierEffect extends PowerEffect { get name () { return 'Barrier' } get duration () { return 5 } get icon () { return 'icons/environment/settlement/fence-stone-brick.webp' } get isTargeted () { return false } get basePowerPoints () { return 2 } get usePrimaryEffect () { return false } get modifiers () { const mods = super.modifiers mods.push({ name: 'Damage', id: 'damage', value: 1, epic: false, effect: false }) mods.push({ name: 'Damage (immaterial trapping)', id: 'damage', value: 0, epic: false, effect: false }) mods.push({ name: 'Deadly', id: 'deadly', value: 2, epic: true, effect: false }) mods.push({ name: 'Hardened', id: 'hardened', value: 1, epic: false, effect: false }) mods.push({ name: 'Shaped', id: 'shaped', value: 1, epic: false, effect: false }) mods.push({ name: 'Size', id: 'size', value: 1, epic: false, effect: false }) return mods } get chatMessageEffects () { const list = [] const hardness = (this.data.raise ? 12 : 10) + (this.data.mods.has('hardened') ? 2 : 0) list.push(`The Barrier is hardness ${hardness}`) if (this.data.mods.has('damage')) { list.push('Damage: 2d4 to anyone who contacts') } if (this.data.mods.has('deadly')) { list.push('Deadly: 2d6 to anyone who contacts') } if (this.data.mods.has('shaped')) { list.push('Shaped (circle, square, or rectangle)') } if (this.data.mods.has('size')) { list.push('Size - length and height doubled') } return list } async createMaintainEffect (maintId) { const doc = await super.createMaintainEffect(maintId) doc.icon = this.icon return doc } } class BurrowEffect extends PowerEffect { get name () { return 'Burrow' } get duration () { return 5 } get icon () { return 'icons/magic/earth/projectile-stone-landslide.webp' } get hasAdditionalRecipients () { return true } get additionalRecipientCost () { return 1 } get basePowerPoints () { return 1 } get isTargeted () { return true } get modifiers () { const mods = super.modifiers mods.push( { name: 'Power', id: 'power', value: 1, epic: false, effect: false, }) return mods } get effectName () { return `${this.name} ${this.data.mods.has('power') ? '[Power] ' : ''}` + `(${this.data.raise ? 'full' : 'half'} pace)` } } const PowerClasses = { "arcane-protection": ArcaneProtectionEffect, banish: BanishEffect, barrier: BarrierEffect, burrow: BurrowEffect } /* ---------------------------------------------------------------- */ export async function powerEffectManagementHook(effect, data, userId) { if (game.user.id !== userId) { return } const maintId = effect.getFlag(moduleName, 'maintainingId') 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 effect of effects) { mutation.embedded.ActiveEffect[effect.id] = warpgate.CONST.DELETE } mutateOptions.description = `${effect.parent.name} is no longer ${effect.name} on ${target.name}` await warpgate.mutate(target.document, mutation, {}, mutateOptions) } } export async function powers (options = {}) { const token = 'token' in options ? options.token : null if (token === undefined || token === null) { ui.notifications.error('Please select one token to be the caster') return } const targets = 'targets' in options ? Array.from(options.targets) : [] const item = 'item' in options ? options.item : null const swid = options?.name || item?.system.swid || null if (swid in PowerClasses) { const runner = new PowerClasses[swid](token, targets) runner.powerEffect() return } ui.notifications.error(`No power effect found for ${name}`) }