mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-11 19:25:21 +01:00
252 lines
9.4 KiB
JavaScript
252 lines
9.4 KiB
JavaScript
import { actionsTypes } from '../../data/action/_module.mjs';
|
|
import ActionSettingsConfig from './action-settings-config.mjs';
|
|
|
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
|
|
|
export default class SettingFeatureConfig extends HandlebarsApplicationMixin(ApplicationV2) {
|
|
constructor(configTitle, move, movePath, settings, optionalParts, options) {
|
|
super(options);
|
|
|
|
this.configTitle = configTitle;
|
|
this.move = move;
|
|
|
|
this.movePath = movePath;
|
|
this.actionsPath = `${movePath}.actions`;
|
|
this.settings = settings;
|
|
|
|
const { hasIcon, hasEffects } = optionalParts;
|
|
this.hasIcon = hasIcon;
|
|
this.hasEffects = hasEffects;
|
|
}
|
|
|
|
get title() {
|
|
return this.configTitle;
|
|
}
|
|
|
|
static DEFAULT_OPTIONS = {
|
|
tag: 'form',
|
|
classes: ['daggerheart', 'setting', 'dh-style'],
|
|
position: { width: 440, height: 'auto' },
|
|
window: {
|
|
icon: 'fa-solid fa-gears'
|
|
},
|
|
actions: {
|
|
editImage: this.onEditImage,
|
|
addItem: this.addItem,
|
|
editItem: this.editItem,
|
|
removeItem: this.removeItem,
|
|
addEffect: this.addEffect,
|
|
resetMoves: this.resetMoves,
|
|
saveForm: this.saveForm
|
|
},
|
|
form: { handler: this.updateData, submitOnChange: true, closeOnSubmit: false }
|
|
};
|
|
|
|
static PARTS = {
|
|
header: { template: 'systems/daggerheart/templates/settings/downtime-config/header.hbs' },
|
|
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
|
|
main: { template: 'systems/daggerheart/templates/settings/downtime-config/main.hbs' },
|
|
actions: { template: 'systems/daggerheart/templates/settings/downtime-config/actions.hbs' },
|
|
effects: { template: 'systems/daggerheart/templates/settings/downtime-config/effects.hbs' },
|
|
footer: { template: 'systems/daggerheart/templates/settings/downtime-config/footer.hbs' }
|
|
};
|
|
|
|
/** @inheritdoc */
|
|
static TABS = {
|
|
primary: {
|
|
tabs: [{ id: 'main' }, { id: 'actions' }, { id: 'effects' }],
|
|
initial: 'main',
|
|
labelPrefix: 'DAGGERHEART.GENERAL.Tabs'
|
|
}
|
|
};
|
|
|
|
async _prepareContext(_options) {
|
|
const context = await super._prepareContext(_options);
|
|
context.tabs = this._filterTabs(context.tabs);
|
|
context.hasIcon = this.hasIcon;
|
|
context.hasEffects = this.hasEffects;
|
|
context.move = this.move;
|
|
context.move.enrichedDescription = await foundry.applications.ux.TextEditor.enrichHTML(
|
|
context.move.description
|
|
);
|
|
|
|
return context;
|
|
}
|
|
|
|
static async updateData(event, element, formData) {
|
|
const data = foundry.utils.expandObject(formData.object);
|
|
foundry.utils.mergeObject(this.move, data);
|
|
|
|
this.render();
|
|
}
|
|
|
|
static async saveForm() {
|
|
this.close({ submitted: true });
|
|
}
|
|
|
|
static onEditImage() {
|
|
const fp = new foundry.applications.apps.FilePicker.implementation({
|
|
current: this.img,
|
|
type: 'image',
|
|
callback: async path => {
|
|
this.move.img = path;
|
|
this.render();
|
|
},
|
|
top: this.position.top + 40,
|
|
left: this.position.left + 10
|
|
});
|
|
return fp.browse();
|
|
}
|
|
|
|
async selectActionType() {
|
|
return (
|
|
(await foundry.applications.api.DialogV2.input({
|
|
window: { title: game.i18n.localize('DAGGERHEART.CONFIG.SelectAction.selectType') },
|
|
position: { width: 300 },
|
|
classes: ['daggerheart', 'dh-style'],
|
|
content: await foundry.applications.handlebars.renderTemplate(
|
|
'systems/daggerheart/templates/actionTypes/actionType.hbs',
|
|
{ types: CONFIG.DH.ACTIONS.actionTypes }
|
|
),
|
|
ok: {
|
|
label: game.i18n.format('DOCUMENT.Create', {
|
|
type: game.i18n.localize('DAGGERHEART.GENERAL.Action.single')
|
|
})
|
|
}
|
|
})) ?? {}
|
|
);
|
|
}
|
|
|
|
static async addItem() {
|
|
const { type: actionType } = await this.selectActionType();
|
|
if (!actionType) return;
|
|
|
|
const cls = actionsTypes[actionType] ?? actionsTypes.attack,
|
|
action = new cls(
|
|
{
|
|
type: actionType,
|
|
name: game.i18n.localize(CONFIG.DH.ACTIONS.actionTypes[actionType].name),
|
|
img: 'icons/magic/life/cross-worn-green.webp',
|
|
actionType: 'action',
|
|
systemPath: this.actionsPath
|
|
},
|
|
{
|
|
parent: this.settings
|
|
}
|
|
);
|
|
|
|
await this.settings.updateSource({ [`${this.actionsPath}.${action.id}`]: action });
|
|
this.move = foundry.utils.getProperty(this.settings, this.movePath);
|
|
|
|
this.render();
|
|
}
|
|
|
|
static async editItem(_, target) {
|
|
const { type, id } = target.dataset;
|
|
if (type === 'effect') {
|
|
const effectIndex = this.move.effects.findIndex(x => x.id === id);
|
|
const effect = this.move.effects[effectIndex];
|
|
const updatedEffect =
|
|
await game.system.api.applications.sheetConfigs.SettingActiveEffectConfig.configure(effect);
|
|
if (!updatedEffect) return;
|
|
|
|
await this.settings.updateSource({
|
|
[`${this.movePath}.effects`]: this.move.effects.reduce((acc, effect, index) => {
|
|
acc.push(index === effectIndex ? { ...updatedEffect, id: effect.id } : effect);
|
|
return acc;
|
|
}, [])
|
|
});
|
|
this.move = foundry.utils.getProperty(this.settings, this.movePath);
|
|
this.render();
|
|
} else {
|
|
const action = this.move.actions.get(id);
|
|
await new ActionSettingsConfig(action, this.move.effects, async (updatedMove, effectData, deleteEffect) => {
|
|
let updatedEffects = null;
|
|
if (effectData) {
|
|
const currentEffects = foundry.utils.getProperty(this.settings, `${this.movePath}.effects`);
|
|
const existingEffectIndex = currentEffects.findIndex(x => x.id === effectData.id);
|
|
|
|
updatedEffects = deleteEffect
|
|
? currentEffects.filter(x => x.id !== effectData.id)
|
|
: existingEffectIndex === -1
|
|
? [...currentEffects, effectData]
|
|
: currentEffects.with(existingEffectIndex, effectData);
|
|
await this.settings.updateSource({
|
|
[`${this.movePath}.effects`]: updatedEffects
|
|
});
|
|
}
|
|
|
|
await this.settings.updateSource({ [`${this.actionsPath}.${id}`]: updatedMove });
|
|
this.move = foundry.utils.getProperty(this.settings, this.movePath);
|
|
this.render();
|
|
return updatedEffects;
|
|
}).render(true);
|
|
}
|
|
}
|
|
|
|
static async removeItem(_, target) {
|
|
const { type, id } = target.dataset;
|
|
if (type === 'effect') {
|
|
const move = foundry.utils.getProperty(this.settings, this.movePath);
|
|
for (const action of move.actions) {
|
|
const remainingEffects = action.effects.filter(x => x._id !== id);
|
|
if (action.effects.length !== remainingEffects.length) {
|
|
await action.update({
|
|
effects: remainingEffects.map(x => {
|
|
const { _id, ...rest } = x;
|
|
return { ...rest, _id: _id };
|
|
})
|
|
});
|
|
}
|
|
}
|
|
await this.settings.updateSource({
|
|
[this.movePath]: {
|
|
effects: move.effects.filter(x => x.id !== id),
|
|
actions: move.actions
|
|
}
|
|
});
|
|
} else {
|
|
await this.settings.updateSource({ [`${this.actionsPath}.-=${target.dataset.id}`]: null });
|
|
}
|
|
|
|
this.move = foundry.utils.getProperty(this.settings, this.movePath);
|
|
this.render();
|
|
}
|
|
|
|
static async addEffect(_, target) {
|
|
const currentEffects = foundry.utils.getProperty(this.settings, `${this.movePath}.effects`);
|
|
await this.settings.updateSource({
|
|
[`${this.movePath}.effects`]: [
|
|
...currentEffects,
|
|
game.system.api.data.activeEffects.BaseEffect.getDefaultObject()
|
|
]
|
|
});
|
|
|
|
this.move = foundry.utils.getProperty(this.settings, this.movePath);
|
|
this.render();
|
|
}
|
|
|
|
static resetMoves() {}
|
|
|
|
_filterTabs(tabs) {
|
|
return this.hasEffects
|
|
? tabs
|
|
: Object.keys(tabs).reduce((acc, key) => {
|
|
if (key !== 'effects') acc[key] = tabs[key];
|
|
return acc;
|
|
}, {});
|
|
}
|
|
|
|
/** @override */
|
|
_onClose(options = {}) {
|
|
if (!options.submitted) this.move = null;
|
|
}
|
|
|
|
static async configure(configTitle, move, movePath, settings, optionalParts, options = {}) {
|
|
return new Promise(resolve => {
|
|
const app = new this(configTitle, move, movePath, settings, optionalParts, options);
|
|
app.addEventListener('close', () => resolve(app.move), { once: true });
|
|
app.render({ force: true });
|
|
});
|
|
}
|
|
}
|