swade-mb-helpers/scripts/allPowers.js
2024-04-29 23:59:38 -05:00

247 lines
6.9 KiB
JavaScript

import { moduleName, log } from './globals.js'
class PowerEffect {
constructor (token, targets) {
this.source = token
this.targets = targets
this.data = {}
}
static async getStatus (label, name, favorite = true) {
const effect = deepClone(
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
}
createEffectDocument (icon, name, changes = null) {
if (changes === null) {
changes = []
}
return {
icon,
name,
changes,
description: `<p>From <strong>${this.source.name}</strong> casting <em>${this.name}</em></p>`,
duration: { rounds: 99 },
flags: {
[moduleName]: {
powerEffect: true
},
swade: {
loseTurnOnHold: false,
expiration: CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnAuto
}
}
}
}
get name () { return 'Unknown Power' }
get icon () { return 'icons/magic/symbols/question-stone-yellow.webp' }
get duration () { return 5 }
get basePowerPoints () { return 0 }
get powerPoints () { return this.basePowerPoints }
get usePrimaryEffect () { return true }
get modifiers () {
return [
{ name: 'Glow',
id: 'glow',
value: 1,
advanced: false,
effect: true,
icon: 'icons/magic/light/orb-shadow-blue.webp',
changes: [ { key: '@Skill{Stealth}[system.die.modifier]', value: -2,
priority: 0, mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD } ]
},
{ name: 'Shroud',
id: 'shroud',
value: 1,
advanced: false,
effect: true,
icon: 'icons/magic/perception/shadow-stealth-eyes-purple.webp',
changes: [ { key: '@Skill{Stealth}[system.die.modifier]', value: 1,
priority: 0, mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD } ]
},
{ name: 'Hinder',
id: 'hinder',
value: 1,
advanced: false,
effect: true,
icon: 'icons/magic/control/debuff-chains-shackle-movement-red.webp',
changes: [ { key: 'system.stats.speed.value', value: -2,
priority: 0, mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD } ]
},
{ name: 'Hurry',
id: 'hurry',
value: 1,
advanced: false,
effect: true,
icon: 'icons/skills/movement/feet-winged-sandals-tan.webp',
changes: [ { key: 'system.stats.speed.value', value: 2,
priority: 0, mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD } ]
},
]
}
get menuData () {
return {
inputs: this.menuInputs,
buttons: this.menuButtons,
}
}
get menuInputs () {
const data = [
{ type: 'header', label: `${this.name} Effect` },
{ type: 'info', label: `Apply ${this.name} Effect` },
]
if (this.targets.length > 0) {
data.push({
type: 'info',
label: `<strong>Targets:</strong> ${this.targets.map(t => t.name).join(',')}`
})
}
for (const mod of this.modifiers) {
data.push({
type: 'checkbox',
label: (
`${mod.advanced ? '⭐ ' : ''}${mod.name} ` +
`(${mod.value >= 0 ? '+' : ''}${mod.value})`
),
})
}
return data
}
get menuButtons () {
const data = [
{ label: 'Apply', value: 'apply' },
{ label: 'Apply with Raise', value: 'raise' },
{ label: 'Cancel', value: 'cancel' }
]
return data
}
get menuOptions () {
return {
title: `${this.name} Effect`,
defaultButton: 'Cancel',
options: {}
}
}
async powerEffect () {
const { buttons, inputs } = await warpgate.menu(
this.menuData, this.menuOptions
)
if (buttons && buttons !== 'cancel') {
this.data.button = buttons
this.data.values = inputs
await this.parseValues()
await this.apply()
await this.sideEffects()
}
}
async parseValues () {
this.data.rawValues = deepClone(this.data.values)
this.data.raise = this.data.button === 'raise'
for (let i = 0; i < 3; i++) {
this.data.values.shift()
}
this.data.mods = new Set()
for (const mod of this.modifiers) {
const modEnabled = this.data.values.shift()
if (modEnabled) {
this.data.mods.add(mod.id)
}
}
}
async createSecondaryEffects () {
const docs = []
for (const mod of this.modifiers) {
if (this.data.mods.has(mod.id) && mod.effect) {
const doc = this.createEffectDocument(mod.icon, mod.name, mod.changes)
if (this.duration === 0 && !this.usePrimaryEffect) {
// set secondary effects of instant spells to expire on victim's next
// turn
doc.duration.rounds = 1
doc.flags.swade.expiration = CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnAuto
}
docs.push(doc)
}
}
return docs
}
async createPrimaryEffect () {
const doc = this.createEffectDocument(this.icon, this.name, [])
return doc
}
async createMaintainEffect () {
const doc = this.createEffectDocument(
this.icon, `Maintaining ${this.name}`, [])
doc.duration.rounds = this.duration
doc.flags.swade.expiration = CONFIG.SWADE.CONST.STATUS_EFFECT_EXPIRATION.StartOfTurnPrompt
doc.flags.swade.loseTurnOnHold = true
return doc
}
async secondaryDocsForTarget(docs, target) {
return deepClone(docs)
}
async primaryDocForTarget(doc, ids, target) {
const newDoc = deepClone(doc)
newDoc.flags[moduleName].secondaryDocIds = deepClone(ids)
return newDoc
}
async apply () {
const secondaryDocs = await this.createSecondaryEffects()
const primaryDoc = await this.createPrimaryEffect()
const maintainDoc = await this.createMaintainEffect()
const primaryIds = []
for (const target of this.targets) {
const created = await target.actor.createEmbeddedDocuments(
'ActiveEffect', await this.secondaryDocsForTarget(secondaryDocs, target))
const createdIds = created.map(c => c.uuid)
if (this.duration > 0 || this.usePrimaryEffect) {
const pCreated = await target.actor.createEmbeddedDocuments(
'ActiveEffect', [await this.primaryDocForTarget(primaryDoc, createdIds, target)])
primaryIds.push(pCreated[0].uuid)
}
}
if (this.duration > 0) {
maintainDoc.flags[moduleName].secondaryDocIds = deepClone(primaryIds)
await this.source.actor.createEmbeddedDocuments('ActiveEffect', [maintainDoc])
}
}
async sideEffects () {
}
}
class BurrowEffect extends PowerEffect {
get name () { return 'Burrow' }
get duration () { return 5 }
get icon () { return 'icons/magic/earth/projectile-stone-landslide.webp' }
}
export const PowerClasses = {
burrow: BurrowEffect
}