251 lines
6.0 KiB
JavaScript
251 lines
6.0 KiB
JavaScript
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 += `<p>This version of <em>smite</em> 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.</p>`;
|
|
return text;
|
|
}
|
|
}
|
|
|
|
export class SmiteEffect extends PowerEffect {
|
|
get name() {
|
|
return 'Smite';
|
|
}
|
|
|
|
get duration() {
|
|
return 5;
|
|
}
|
|
|
|
get icon() {
|
|
return 'systems/swade/assets/icons/status/status_smite.svg';
|
|
}
|
|
|
|
get isDamaging() {
|
|
return true;
|
|
}
|
|
|
|
get basePowerPoints() {
|
|
return 2;
|
|
}
|
|
|
|
get isTargeted() {
|
|
return true;
|
|
}
|
|
|
|
get hasAdditionalRecipients() {
|
|
return true;
|
|
}
|
|
|
|
get additionalRecipientCost() {
|
|
return 1;
|
|
}
|
|
|
|
get modifiers() {
|
|
return [
|
|
...super.modifiers,
|
|
{
|
|
type: 'checkbox',
|
|
default: false,
|
|
name: 'Greater Smite',
|
|
id: 'greater',
|
|
value: 2,
|
|
epic: true,
|
|
effect: false,
|
|
},
|
|
{
|
|
type: 'checkbox',
|
|
default: false,
|
|
name: 'Spiritual Weapon',
|
|
id: 'spiritualWeapon',
|
|
value: 2,
|
|
epic: true,
|
|
effect: false,
|
|
},
|
|
];
|
|
}
|
|
|
|
async parseValues() {
|
|
await super.parseValues();
|
|
this.baseDoc = await PowerEffect.getStatus('SWADE.Smite', 'Smite', false);
|
|
this.baseDoc.flags = mergeObject(this.baseDoc.flags ?? {}, {
|
|
[moduleName]: { powerEffect: true },
|
|
});
|
|
this.data.bonus = (this.data.raise ? 4 : 2) + (this.data.greater ? 2 : 0);
|
|
this.baseDoc.changes = [...this.getPrimaryEffectChanges()];
|
|
}
|
|
|
|
get basePrimaryEffect() {
|
|
return this.baseDoc;
|
|
}
|
|
|
|
getPrimaryEffectChanges() {
|
|
return [
|
|
...super.getPrimaryEffectChanges(),
|
|
{
|
|
key: 'system.stats.globalMods.damage',
|
|
value: this.data.bonus,
|
|
priority: 0,
|
|
mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,
|
|
},
|
|
];
|
|
}
|
|
|
|
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 = `
|
|
<p>Increase damage by ${this.data.bonus} on one weapon or load of ammunition.
|
|
`;
|
|
if (this.data.greater) {
|
|
text += 'The weapon is considered a Heavy Weapon.';
|
|
}
|
|
text += '</p>';
|
|
return super.description + text;
|
|
}
|
|
}
|