209 lines
6.4 KiB
JavaScript
209 lines
6.4 KiB
JavaScript
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("<strong>Success:</strong> Shaken, <strong>Each Raise:</strong> 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}`)
|
|
}
|
|
|