summon part 2
This commit is contained in:
parent
4bdd6176e8
commit
6fe743130d
@ -117,7 +117,7 @@ export class PowerFormApplication extends FormApplication {
|
|||||||
formData.submit = ev?.submitter?.value ?? 'cancel';
|
formData.submit = ev?.submitter?.value ?? 'cancel';
|
||||||
if (formData.submit !== 'cancel') {
|
if (formData.submit !== 'cancel') {
|
||||||
this.powerEffect.formData = formData;
|
this.powerEffect.formData = formData;
|
||||||
await this.powerEffect.applyEffect();
|
this.powerEffect.applyEffect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -447,6 +447,29 @@ export class PowerEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enhanceSecondaryEffect(maintId, doc) {
|
||||||
|
doc.statuses = doc.statuses ?? [];
|
||||||
|
doc.statuses.push('powerEffect');
|
||||||
|
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.EndOfTurnAuto;
|
||||||
|
} else {
|
||||||
|
doc.flags[moduleName].maintId = maintId;
|
||||||
|
if (moduleHelpers.useVAE) {
|
||||||
|
doc.flags['visual-active-effects'] = {
|
||||||
|
data: {
|
||||||
|
inclusion: 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
doc.duration.seconds = 594;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
async createSecondaryEffects(maintId) {
|
async createSecondaryEffects(maintId) {
|
||||||
const docs = [];
|
const docs = [];
|
||||||
for (const mod of this.modifiers) {
|
for (const mod of this.modifiers) {
|
||||||
@ -455,26 +478,7 @@ export class PowerEffect {
|
|||||||
const icon = 'effects' in mod ? mod.effects[modValue].icon : mod.icon;
|
const icon = 'effects' in mod ? mod.effects[modValue].icon : mod.icon;
|
||||||
const name = 'effects' in mod ? mod.effects[modValue].name : mod.name;
|
const name = 'effects' in mod ? mod.effects[modValue].name : mod.name;
|
||||||
const changes = 'effects' in mod ? mod.effects[modValue].changes : mod.changes;
|
const changes = 'effects' in mod ? mod.effects[modValue].changes : mod.changes;
|
||||||
const doc = this.createEffectDocument(icon, name, changes);
|
const doc = this.enhanceSecondaryEffect(maintId, this.createEffectDocument(icon, name, changes));
|
||||||
doc.statuses = doc.statuses ?? [];
|
|
||||||
doc.statuses.push('powerEffect');
|
|
||||||
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.EndOfTurnAuto;
|
|
||||||
} else {
|
|
||||||
doc.flags[moduleName].maintId = maintId;
|
|
||||||
if (moduleHelpers.useVAE) {
|
|
||||||
doc.flags['visual-active-effects'] = {
|
|
||||||
data: {
|
|
||||||
inclusion: 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
doc.duration.seconds = 594;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
docs.push(doc);
|
docs.push(doc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,7 +69,7 @@ export class BlindEffect extends PowerEffect {
|
|||||||
const docs = await super.createSecondaryEffects(maintId);
|
const docs = await super.createSecondaryEffects(maintId);
|
||||||
if (this.data.raise) {
|
if (this.data.raise) {
|
||||||
const strong = this.data.strong;
|
const strong = this.data.strong;
|
||||||
const doc = this.createEffectDocument(this.icon, `Blinded (${strong ? 'Strong, ' : ''}Raise)`, [
|
let doc = this.createEffectDocument(this.icon, `Blinded (${strong ? 'Strong, ' : ''}Raise)`, [
|
||||||
{
|
{
|
||||||
key: 'system.stats.globalMods.trait',
|
key: 'system.stats.globalMods.trait',
|
||||||
value: -2,
|
value: -2,
|
||||||
@ -77,9 +77,8 @@ export class BlindEffect extends PowerEffect {
|
|||||||
mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,
|
mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
doc.duration.seconds = 594;
|
doc = this.enhanceSecondaryEffect(maintId, doc);
|
||||||
doc.description = this.description + '<p>This is the raise effect which can be shaken off separately.</p>';
|
doc.description = this.description + '<p>This is the raise effect which can be shaken off separately.</p>';
|
||||||
doc.flags[moduleName].maintId = maintId;
|
|
||||||
docs.push(doc);
|
docs.push(doc);
|
||||||
}
|
}
|
||||||
return docs;
|
return docs;
|
||||||
|
|||||||
@ -70,10 +70,8 @@ export class BoostLowerTraitEffect extends PowerEffect {
|
|||||||
mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,
|
mode: foundry.CONST.ACTIVE_EFFECT_MODES.ADD,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const doc = this.createEffectDocument(this.icon, name, changes);
|
const doc = this.enhanceSecondaryEffect(maintId, this.createEffectDocument(this.icon, name, changes));
|
||||||
doc.duration.seconds = 594;
|
|
||||||
doc.description = this.description + '<p>This is the raise effect which can be shaken off separately.</p>';
|
doc.description = this.description + '<p>This is the raise effect which can be shaken off separately.</p>';
|
||||||
doc.flags[moduleName].maintId = maintId;
|
|
||||||
docs.push(doc);
|
docs.push(doc);
|
||||||
}
|
}
|
||||||
return docs;
|
return docs;
|
||||||
|
|||||||
@ -56,6 +56,7 @@ import { SmiteEffect } from './smite.js';
|
|||||||
import { SoundSilenceEffect } from './soundSilence.js';
|
import { SoundSilenceEffect } from './soundSilence.js';
|
||||||
import { SpeakLanguageEffect } from './speakLanguage.js';
|
import { SpeakLanguageEffect } from './speakLanguage.js';
|
||||||
import { StunEffect } from './stun.js';
|
import { StunEffect } from './stun.js';
|
||||||
|
import { SummonAllyEffect } from './summon.js';
|
||||||
|
|
||||||
const PowerClasses = {
|
const PowerClasses = {
|
||||||
'arcane-protection': ArcaneProtectionEffect,
|
'arcane-protection': ArcaneProtectionEffect,
|
||||||
@ -132,6 +133,7 @@ const PowerClasses = {
|
|||||||
sound: SoundSilenceEffect,
|
sound: SoundSilenceEffect,
|
||||||
'speak-language': SpeakLanguageEffect,
|
'speak-language': SpeakLanguageEffect,
|
||||||
stun: StunEffect,
|
stun: StunEffect,
|
||||||
|
'summon-ally': SummonAllyEffect,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ---------------------------------------------------------------- */
|
/* ---------------------------------------------------------------- */
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
/* globals Portal */
|
/* globals Portal */
|
||||||
|
import { moduleName } from '../globals.js';
|
||||||
import { ActorFolderEffect } from './basePowers.js';
|
import { ActorFolderEffect } from './basePowers.js';
|
||||||
|
|
||||||
class BaseSummonEffect extends ActorFolderEffect {
|
class BaseSummonEffect extends ActorFolderEffect {
|
||||||
@ -80,16 +81,79 @@ class BaseSummonEffect extends ActorFolderEffect {
|
|||||||
if (!(this.hasIncreasedTrait && this?.data?.increasedTrait)) {
|
if (!(this.hasIncreasedTrait && this?.data?.increasedTrait)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const skillSet = new Set();
|
||||||
|
for (const skill of this.targetActor.items.filter((i) => i.type === 'skill')) {
|
||||||
|
skillSet.add(skill.name);
|
||||||
|
}
|
||||||
|
for (const item of Object.values(this.data.embeddedUpdates.Item).filter((i) => i.type === 'skill')) {
|
||||||
|
skillSet.add(item.name);
|
||||||
|
}
|
||||||
|
const skillList = Array.from(skillSet);
|
||||||
|
skillList.sort();
|
||||||
|
const attrList = ['Agility', 'Smarts', 'Spirit', 'Strength', 'Vigor'];
|
||||||
|
let html = `<form><h2>Increase Attributes</h2><p>(+1 pp each)</p>`;
|
||||||
|
html += attrList
|
||||||
|
.map(
|
||||||
|
(name) => `<div class="form-group">
|
||||||
|
<label><input type="checkbox" name="${name}">${name}</label>
|
||||||
|
</div>`,
|
||||||
|
)
|
||||||
|
.join('');
|
||||||
|
html += `<h2>Increase Skills</h2><p>(+1 pp each)</p>`;
|
||||||
|
html += skillList
|
||||||
|
.map(
|
||||||
|
(name) => `<div class="form-group">
|
||||||
|
<label><input type="checkbox" name="${name}">${name}</label>
|
||||||
|
</div>`,
|
||||||
|
)
|
||||||
|
.join('');
|
||||||
|
const formData = await Dialog.wait({
|
||||||
|
title: 'Select Trait increases',
|
||||||
|
content: html,
|
||||||
|
buttons: {
|
||||||
|
submit: {
|
||||||
|
label: 'Submit',
|
||||||
|
callback: (html) => {
|
||||||
|
const formElement = html[0].querySelector('form');
|
||||||
|
const formData = new FormDataExtended(formElement);
|
||||||
|
return formData.object;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cancel: { label: 'Cancel' },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const mode = CONST.ACTIVE_EFFECT_MODES.ADD;
|
||||||
|
const value = 2;
|
||||||
|
const priority = 0;
|
||||||
|
this.data.increasedTraitChanges = [];
|
||||||
|
for (const attr of attrList) {
|
||||||
|
if (formData[attr]) {
|
||||||
|
this.data.increasedTraitChanges.push({
|
||||||
|
key: `system.attributes.${attr.toLowerCase()}.die.sides`,
|
||||||
|
value,
|
||||||
|
mode,
|
||||||
|
priority,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const skill of skillList) {
|
||||||
|
if (formData[skill]) {
|
||||||
|
this.data.increasedTraitChanges.push({
|
||||||
|
key: `@Skill{${skill}}[system.die.sides]`,
|
||||||
|
value,
|
||||||
|
mode,
|
||||||
|
priority,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async prePrep() {}
|
||||||
|
|
||||||
async parseValues() {
|
async parseValues() {
|
||||||
await super.parseValues();
|
await super.parseValues();
|
||||||
this.data.actorUpdates = {
|
this.data.actorUpdates = {
|
||||||
name: `${this.source.actor.name}'s summoned ${this.targetActor.name}`,
|
name: `${this.source.actor.name}'s summoned ${this.targetActor.name}`,
|
||||||
system: {
|
|
||||||
wildcard: this.source.actor.system.wildcard,
|
|
||||||
attributes: {},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
this.data.tokenUpdates = {
|
this.data.tokenUpdates = {
|
||||||
actorLink: false,
|
actorLink: false,
|
||||||
@ -103,9 +167,35 @@ class BaseSummonEffect extends ActorFolderEffect {
|
|||||||
ActiveEffect: {},
|
ActiveEffect: {},
|
||||||
Item: {},
|
Item: {},
|
||||||
};
|
};
|
||||||
|
this.data.primaryEffectChanges = [];
|
||||||
|
await this.prePrep();
|
||||||
await this.prepIncreasedTrait();
|
await this.prepIncreasedTrait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPrimaryEffectChanges() {
|
||||||
|
return [...super.getPrimaryEffectChanges(), ...this.data.primaryEffectChanges];
|
||||||
|
}
|
||||||
|
|
||||||
|
async createSecondaryEffects(maintId) {
|
||||||
|
const effects = await super.createSecondaryEffects(maintId);
|
||||||
|
if (this.data.mindRider) {
|
||||||
|
const doc = this.enhanceSecondaryEffect(
|
||||||
|
maintId,
|
||||||
|
this.createEffectDocument('icons/magic/control/hypnosis-mesmerism-eye.webp', 'Mind Rider', []),
|
||||||
|
);
|
||||||
|
doc.description = `The caster can communicate and sense through the ally`;
|
||||||
|
effects.push(doc);
|
||||||
|
}
|
||||||
|
if ((this.data?.increasedTraitChanges?.length ?? 0) > 0) {
|
||||||
|
const doc = this.enhanceSecondaryEffect(
|
||||||
|
maintId,
|
||||||
|
this.createEffectDocument(this.icon, 'Increased Trait', this.data.increasedTraitChanges),
|
||||||
|
);
|
||||||
|
effects.push(doc);
|
||||||
|
}
|
||||||
|
return effects;
|
||||||
|
}
|
||||||
|
|
||||||
get spawnUpdates() {
|
get spawnUpdates() {
|
||||||
const updates = super.spawnUpdates;
|
const updates = super.spawnUpdates;
|
||||||
mergeObject(updates.actor, this.data.actorUpdates);
|
mergeObject(updates.actor, this.data.actorUpdates);
|
||||||
@ -116,14 +206,23 @@ class BaseSummonEffect extends ActorFolderEffect {
|
|||||||
|
|
||||||
async spawn() {
|
async spawn() {
|
||||||
const spawned = await new Portal()
|
const spawned = await new Portal()
|
||||||
.addCreature(this.targetTokenDoc)
|
.addCreature(this.targetTokenDoc, { count: this.summonCount })
|
||||||
.texture(this.targetTokenDoc.texture.src)
|
.texture(this.targetTokenDoc.texture.src)
|
||||||
.spawn();
|
.spawn();
|
||||||
return spawned;
|
return spawned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async apply() {
|
||||||
|
await super.apply();
|
||||||
|
const maintainDoc = await this.createMaintainEffect(this.data.maintId);
|
||||||
|
maintainDoc.flags[moduleName].targetIds = this.data.spawned.map((t) => t.id);
|
||||||
|
if (this.duration > 0) {
|
||||||
|
await this.applyActiveEffects(this.source, [maintainDoc]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SummonAllyEffect extends BaseSummonEffect() {
|
export class SummonAllyEffect extends BaseSummonEffect {
|
||||||
get name() {
|
get name() {
|
||||||
return 'Summon Ally';
|
return 'Summon Ally';
|
||||||
}
|
}
|
||||||
@ -132,6 +231,18 @@ export class SummonAllyEffect extends BaseSummonEffect() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get duration() {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
get icon() {
|
||||||
|
return 'icons/magic/control/silhouette-hold-beam-blue.webp';
|
||||||
|
}
|
||||||
|
|
||||||
|
get isTargeted() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
get values() {
|
get values() {
|
||||||
return {
|
return {
|
||||||
attendant: 1,
|
attendant: 1,
|
||||||
@ -181,6 +292,86 @@ export class SummonAllyEffect extends BaseSummonEffect() {
|
|||||||
epic: false,
|
epic: false,
|
||||||
effect: false,
|
effect: false,
|
||||||
});
|
});
|
||||||
|
const { choices, effects, values } = this._edges;
|
||||||
return mods;
|
return mods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async prePrep() {
|
||||||
|
await super.prePrep();
|
||||||
|
if (this.data.raise && this.data.actors['raise_template']) {
|
||||||
|
const raiseTemplate = this.summonableActors.raise_template;
|
||||||
|
for (const item of raiseTemplate.items) {
|
||||||
|
const raiseItemDoc = await raiseTemplate.getEmbeddedDocument('Item', item.id);
|
||||||
|
this.data.embeddedUpdates.Item[item.name] = raiseItemDoc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.targetActor.name !== 'Mirror Self') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const mirrorActor = this.source.actor;
|
||||||
|
mergeObject(this.data.actorUpdates, {
|
||||||
|
system: mirrorActor.system
|
||||||
|
.clone({
|
||||||
|
'fatigue.value': 0,
|
||||||
|
'wounds.value': 0,
|
||||||
|
'wounds.max': 0,
|
||||||
|
'bennies.max': 0,
|
||||||
|
'bennies.value': 0,
|
||||||
|
})
|
||||||
|
.toObject(),
|
||||||
|
name: `Mirror ${mirrorActor.name}`,
|
||||||
|
img: mirrorActor.img,
|
||||||
|
});
|
||||||
|
this.data.actorUpdates.system.wildcard = false;
|
||||||
|
mergeObject(this.data.tokenUpdates, {
|
||||||
|
name: `Mirror ${this.source.name}`,
|
||||||
|
texture: {
|
||||||
|
src: this.source.document.texture.src,
|
||||||
|
scaleX: this.source.document.texture.scaleX * -1,
|
||||||
|
scaleY: this.source.document.texture.scaleY,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.data.mirrorChanges = [];
|
||||||
|
for (const mirrorItem of mirrorActor.items) {
|
||||||
|
if (
|
||||||
|
mirrorItem.type === 'power' &&
|
||||||
|
(mirrorItem.system?.swid === 'summon-ally' || mirrorItem.name === 'Summon Ally')
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (['weapon', 'armor', 'consumable', 'gear'].includes(mirrorItem.type)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.data.embeddedUpdates.Item[mirrorItem.name] = await mirrorActor.getEmbeddedDocument('Item', mirrorItem.id);
|
||||||
|
if (mirrorItem.type === 'skill') {
|
||||||
|
this.data.mirrorChanges.push({
|
||||||
|
key: `@Skill{${mirrorItem.name}}[system.die.sides]`,
|
||||||
|
mode: CONST.ACTIVE_EFFECT_MODES.ADD,
|
||||||
|
value: -2,
|
||||||
|
priority: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async parseValues() {
|
||||||
|
await super.parseValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
async createSecondaryEffects(maintId) {
|
||||||
|
const effects = await super.createSecondaryEffects(maintId);
|
||||||
|
if ((this.data?.mirrorChanges?.length ?? 0) > 0) {
|
||||||
|
const doc = this.enhanceSecondaryEffect(
|
||||||
|
maintId,
|
||||||
|
this.createEffectDocument(
|
||||||
|
'icons/magic/control/mouth-smile-deception-purple.webp',
|
||||||
|
'Mirror Self',
|
||||||
|
this.data.mirrorChanges,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
doc.description = 'A mirror self ally has skills 1 die type worse than the caster';
|
||||||
|
effects.push(doc);
|
||||||
|
}
|
||||||
|
return effects;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user