diff --git a/src/module/powers/basePowers.js b/src/module/powers/basePowers.js index bafc7d3..dddc585 100644 --- a/src/module/powers/basePowers.js +++ b/src/module/powers/basePowers.js @@ -33,6 +33,8 @@ function _hashCode(str) { export class PowerFormApplication extends FormApplication { constructor(powerEffect) { super(); + const name = powerEffect.name.replaceAll(/[^a-zA-Z]/g, ''); + this.options.id = `${this.options.id}${name}`; this.powerEffect = powerEffect; } @@ -843,7 +845,9 @@ export class ActorFolderEffect extends PowerEffect { const collection = actor.getEmbeddedCollection(documentType); adds[documentType] = []; updates[documentType] = []; + log('docType', documentType); for (const newDocKey in newDocs[documentType]) { + log('newDocKey', newDocKey); const newDoc = newDocs[documentType][newDocKey].toObject(); const oldDoc = collection.find((doc) => this.#documentFinder(documentType, doc, newDoc)); if (newDoc.type === 'power' && newDoc?.system?.choiceSets?.length > 0) { diff --git a/src/module/powers/smite.js b/src/module/powers/smite.js index 4c3e8bc..be12054 100644 --- a/src/module/powers/smite.js +++ b/src/module/powers/smite.js @@ -1,5 +1,131 @@ import { moduleName } from '../globals.js'; import { PowerEffect } from './basePowers.js'; +import { BaseSummonEffect } from './summonSupport.js'; + +class SpiritualWeaponEffect extends BaseSummonEffect { + get name() { + return 'Spiritual Weapon'; + } + + get icon() { + return 'icons/weapons/hammers/hammer-double-glowing-yellow.webp'; + } + + get duration() { + return 5; + } + + get basePowerPoints() { + return 4; + } + + get modifiers() { + const arcaneSkillSwids = ['faith', 'spellcasting', 'performance', 'alchemy']; + const choices = {}; + const values = {}; + const effects = {}; + const skillList = this.source.actor.items.filter( + (i) => i.type === 'skill' && arcaneSkillSwids.includes(i.system.swid), + ); + for (const skill of skillList.map((s) => s.name)) { + choices[skill] = skill; + values[skill] = 0; + effects[skill] = null; + } + return [ + ...super.modifiers, + { + type: 'select', + name: 'Arcane Skill', + id: 'arcaneSkill', + choices, + values, + effects, + epic: false, + }, + ]; + } + + // eslint-disable-next-line no-unused-vars + actorValue(actor) { + return 0; + } + + async parseValuesPre() { + await super.parseValuesPre(); + this.data.primaryEffectChanges = []; + this.data.actorUpdates = { + name: `${this.source.actor.name}'s ${this.targetActor.name}`, + system: { + wildcard: this.source.actor.system.wildcard, + attributes: { + spirit: { + die: { + sides: this.source.actor.system.attributes.spirit.die.sides, + modifier: this.source.actor.system.attributes.spirit.die.modifier, + }, + 'wild-die': { + sides: this.source.actor.system.attributes.spirit['wild-die'].sides, + }, + }, + }, + }, + }; + this.data.tokenUpdates = { + disposition: this.source.document.disposition, + sight: { enabled: false }, + actorLink: false, + name: `${this.source.name}'s ${this.targetActor.name}`, + }; + const weaponId = this.targetActor.items.find((i) => i.type === 'weapon' && i.system.swid === 'spiritual-weapon').id; + const weaponDoc = await this.targetActor.getEmbeddedDocument('Item', weaponId).clone(); + const arcaneSkillId = this.source.actor.items.find( + (i) => i.type === 'skill' && i.name === this.data.arcaneSkill, + ).id; + const arcaneDoc = await this.source.actor.getEmbeddedDocument('Item', arcaneSkillId).clone(); + weaponDoc.updateSource({ + system: { + damage: this.data.raise ? '@spi+d6' : '@spi+d4', + actions: { + trait: arcaneDoc.name, + }, + }, + }); + this.data.embeddedUpdates = { + ActiveEffect: {}, + Item: { + [weaponDoc.name]: weaponDoc, + [arcaneDoc.name]: arcaneDoc, + }, + }; + } + + get summonCount() { + return 1; + } + + getPrimaryEffectChanges() { + return [...super.getPrimaryEffectChanges(), ...this.data.primaryEffectChanges]; + } + + get spawnUpdates() { + const updates = super.spawnUpdates; + mergeObject(updates.actor, this.data.actorUpdates); + mergeObject(updates.token, this.data.tokenUpdates); + mergeObject(updates.embedded, this.data.embeddedUpdates); + return updates; + } + + get description() { + let text = super.description; + text += `
This version of smite summons an enchanted weapon made + of energy within Smarts. The caster can move the spiritual weapon up to 5" + and attack with it as a free action, using their ${this.data.arcaneSkill} + in place of fighting. The weapon does ${this.data.raise ? 'Spr+d6' : 'Spr+d4'} + damage.
`; + return text; + } +} export class SmiteEffect extends PowerEffect { get name() { @@ -46,6 +172,15 @@ export class SmiteEffect extends PowerEffect { epic: true, effect: false, }, + { + type: 'checkbox', + default: false, + name: 'Spiritual Weapon', + id: 'spiritualWeapon', + value: 2, + epic: true, + effect: false, + }, ]; } @@ -75,6 +210,33 @@ export class SmiteEffect extends PowerEffect { ]; } + async applySpiritualWeapon() { + const runner = new SpiritualWeaponEffect(this.source, []); + runner.render(); + } + + async apply() { + if (this.data.spiritualWeapon) { + await this.applySpiritualWeapon(); + } else { + super.apply(); + } + } + + async chatMessage() { + if (this.data.spiritualWeapon) { + return; + } + await super.chatMessage(); + } + + async sideEffects() { + if (this.data.spiritualWeapon) { + return; + } + await super.sideEffects(); + } + get description() { let text = `Increase damage by ${this.data.bonus} on one weapon or load of ammunition.