212 lines
5.8 KiB
JavaScript
212 lines
5.8 KiB
JavaScript
/* globals Sequencer */
|
|
import { log, moduleName } from '../globals.js';
|
|
import { templates } from '../preloadTemplates.js';
|
|
import { ActorFolderEffect } from './basePowers.js';
|
|
|
|
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
|
|
|
|
export class BaseSummonEffect extends ActorFolderEffect {
|
|
get name() {
|
|
return 'Base Summon';
|
|
}
|
|
|
|
get actorFolderBase() {
|
|
return 'Summonables';
|
|
}
|
|
|
|
get summonCount() {
|
|
return 0;
|
|
}
|
|
|
|
get spawnUpdates() {
|
|
const updates = super.spawnUpdates;
|
|
const actorUpdates = {
|
|
system: {
|
|
initiative: {
|
|
follow: this.source.name,
|
|
},
|
|
},
|
|
};
|
|
foundry.utils.mergeObject(updates.actor, actorUpdates);
|
|
return updates;
|
|
}
|
|
|
|
async parseValuesPre() {}
|
|
|
|
async parseValuesMid() {}
|
|
|
|
async parseValuesPost() {}
|
|
|
|
async parseValues() {
|
|
await super.parseValues();
|
|
await this.parseValuesPre();
|
|
await this.parseValuesMid();
|
|
await this.parseValuesPost();
|
|
}
|
|
|
|
async spawn() {
|
|
const location = await Sequencer.Crosshair.show({
|
|
distance: this.targetTokenDoc.height / 2,
|
|
texture: this.targetTokenDoc.texture.src,
|
|
snap: {
|
|
position: CONST.GRID_SNAPPING_MODES.VERTEX | CONST.GRID_SNAPPING_MODES.CENTER,
|
|
},
|
|
label: { text: this.targetTokenDoc.name },
|
|
});
|
|
const tokenDocs = [];
|
|
for (let i = 0; i < this.summonCount; i++) {
|
|
tokenDocs[i] = this.targetTokenDoc.clone({
|
|
x: location.token.x + i * 5,
|
|
y: location.token.y + i * 5,
|
|
elevation: this.source.elevation,
|
|
});
|
|
}
|
|
log('token docs', tokenDocs);
|
|
const spawned = await this.source.scene.createEmbeddedDocuments('Token', tokenDocs);
|
|
log('Spawned', 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 SummonCostApplication extends HandlebarsApplicationMixin(ApplicationV2) {
|
|
constructor(actors, powers) {
|
|
super();
|
|
this.actors = actors;
|
|
this.powers = powers;
|
|
this.object = {};
|
|
}
|
|
|
|
static DEFAULT_OPTIONS = {
|
|
id: 'mbSwadeSummonCostApplication',
|
|
form: {
|
|
handler: SummonCostApplication.#onSubmit,
|
|
closeOnSubmit: true,
|
|
},
|
|
tag: 'form',
|
|
position: {
|
|
width: 800,
|
|
height: 'auto',
|
|
},
|
|
classes: ['mbSwade', 'mbSwadeForm', 'mbSwadeSummonCostForm'],
|
|
window: {
|
|
title: 'Set Summoning Costs',
|
|
},
|
|
};
|
|
|
|
static PARTS = {
|
|
header: {
|
|
template: templates['dialogHeader.html'],
|
|
classes: ['mbSwade', 'mbSwadeDialogHeader', 'mbSwadeSummonCostsHeader'],
|
|
},
|
|
body: {
|
|
template: templates['summonCosts.html'],
|
|
classes: ['mbSwade', 'mbSwadePowerEffectsBody', 'scrollable'],
|
|
},
|
|
footer: {
|
|
template: 'templates/generic/form-footer.hbs',
|
|
},
|
|
};
|
|
|
|
async _prepareContext() {
|
|
const actorNames = Object.keys(this.actors).map((k) => {
|
|
let splitName = k.split(' | ');
|
|
splitName.pop();
|
|
let folder = splitName.length ? splitName.join(' | ') : '';
|
|
return { name: this.actors[k].name, folder, fullName: k };
|
|
});
|
|
actorNames.sort((a, b) => {
|
|
if (a.name < b.name) {
|
|
return -1;
|
|
} else if (a.name > b.name) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
});
|
|
const data = {
|
|
name: 'Set Summon Costs',
|
|
formId: foundry.utils.randomID(),
|
|
headerTitle: 'Set Summon Costs',
|
|
powers: this.powers,
|
|
actors: [],
|
|
buttons: [
|
|
{ type: 'submit', icon: 'fa-solid fa-save', label: 'SETTINGS.Save' },
|
|
{ type: 'cancel', icon: 'fa-solid fa-ban', label: 'SETTINGS.Cancel' },
|
|
],
|
|
};
|
|
for (const actor of actorNames) {
|
|
const summon = this.actors[actor.fullName].getFlag(moduleName, 'summonData') ?? {
|
|
cost: 0,
|
|
powers: {},
|
|
};
|
|
const hbSummon = {
|
|
cost: summon.cost,
|
|
powers: [],
|
|
};
|
|
for (const power of this.powers) {
|
|
hbSummon.powers.push({ power, value: summon.powers?.[power] ?? false });
|
|
}
|
|
data.actors.push({ actor, summon: hbSummon });
|
|
}
|
|
log('summon data');
|
|
log(data);
|
|
return data;
|
|
}
|
|
|
|
static async #onSubmit(event, form, formData) {
|
|
const submit = event?.submitter?.value ?? 'cancel';
|
|
if (submit === 'cancel') {
|
|
return;
|
|
}
|
|
log('FORMDATA |', formData);
|
|
formData = formData.object;
|
|
const updates = {};
|
|
for (const key of Object.keys(formData)) {
|
|
const value = formData[key];
|
|
const [name, subKey] = key.split(':;:');
|
|
if (!(name in updates)) {
|
|
updates[name] = { powers: {} };
|
|
}
|
|
if (subKey === 'cost') {
|
|
updates[name].cost = value;
|
|
} else {
|
|
updates[name].powers[subKey] = value;
|
|
}
|
|
}
|
|
log('FORMUPDATES |', updates);
|
|
for (const key of Object.keys(updates)) {
|
|
const update = updates[key];
|
|
const flagValue = this.actors[key].getFlag(moduleName, 'summonData') ?? {};
|
|
foundry.utils.mergeObject(flagValue, update);
|
|
const result = this.actors[key].setFlag(moduleName, 'summonData', flagValue);
|
|
console.log('update', key, result);
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function setSummonCosts(powers = [], folderName = null) {
|
|
if (!folderName) {
|
|
folderName = 'Summonables/Creatures';
|
|
}
|
|
const folder = ActorFolderEffect.getPackFolderByPath(folderName);
|
|
if (!folder) {
|
|
log(`ERROR: Could not find folder ${folderName}`);
|
|
}
|
|
const indexActors = ActorFolderEffect.getPackActorsInFolder(folder);
|
|
const actors = {};
|
|
const promises = [];
|
|
for (const actorName in indexActors) {
|
|
promises.push(foundry.utils.fromUuid(indexActors[actorName].uuid).then((result) => (actors[actorName] = result)));
|
|
}
|
|
await Promise.all(promises);
|
|
new SummonCostApplication(actors, powers).render(true);
|
|
}
|