mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-11 19:25:21 +01:00
[Fix] Homebrew Item Features (#1365)
* Fixed adding and editing effects on a homebrew feature * . * Fixed effect removal
This commit is contained in:
parent
cb10b18e06
commit
9fa4627b19
11 changed files with 411 additions and 252 deletions
|
|
@ -2094,6 +2094,7 @@
|
|||
"missingDragDropThing": "Drop {thing} here",
|
||||
"multiclass": "Multiclass",
|
||||
"newCategory": "New Category",
|
||||
"newThing": "New {thing}",
|
||||
"none": "None",
|
||||
"noTarget": "No current target",
|
||||
"partner": "Partner",
|
||||
|
|
@ -2383,8 +2384,8 @@
|
|||
"newDowntimeMove": "Downtime Move",
|
||||
"downtimeMove": "Downtime Move",
|
||||
"armorFeature": "Armor Feature",
|
||||
"weaponFeature": "Weapon Feaure",
|
||||
"newFeature": "New ItemFeature",
|
||||
"weaponFeature": "Weapon Feature",
|
||||
"newFeature": "New Item Feature",
|
||||
"downtimeMoves": "Downtime Moves",
|
||||
"itemFeatures": "Item Features",
|
||||
"nrChoices": "# Moves Per Rest",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
export { default as ActionConfig } from './action-config.mjs';
|
||||
export { default as ActionSettingsConfig } from './action-settings-config.mjs';
|
||||
export { default as CharacterSettings } from './character-settings.mjs';
|
||||
export { default as AdversarySettings } from './adversary-settings.mjs';
|
||||
export { default as CompanionSettings } from './companion-settings.mjs';
|
||||
|
|
|
|||
236
module/applications/sheets-configs/action-base-config.mjs
Normal file
236
module/applications/sheets-configs/action-base-config.mjs
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
import DaggerheartSheet from '../sheets/daggerheart-sheet.mjs';
|
||||
|
||||
const { ApplicationV2 } = foundry.applications.api;
|
||||
export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) {
|
||||
constructor(action) {
|
||||
super({});
|
||||
|
||||
this.action = action;
|
||||
this.openSection = null;
|
||||
}
|
||||
|
||||
get title() {
|
||||
return `${game.i18n.localize('DAGGERHEART.GENERAL.Tabs.settings')}: ${this.action.name}`;
|
||||
}
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
classes: ['daggerheart', 'dh-style', 'dialog', 'max-800'],
|
||||
window: {
|
||||
icon: 'fa-solid fa-wrench',
|
||||
resizable: false
|
||||
},
|
||||
position: { width: 600, height: 'auto' },
|
||||
actions: {
|
||||
toggleSection: this.toggleSection,
|
||||
addEffect: this.addEffect,
|
||||
removeEffect: this.removeEffect,
|
||||
addElement: this.addElement,
|
||||
removeElement: this.removeElement,
|
||||
editEffect: this.editEffect,
|
||||
addDamage: this.addDamage,
|
||||
removeDamage: this.removeDamage
|
||||
},
|
||||
form: {
|
||||
handler: this.updateForm,
|
||||
submitOnChange: true,
|
||||
closeOnSubmit: false
|
||||
}
|
||||
};
|
||||
|
||||
static PARTS = {
|
||||
header: {
|
||||
id: 'header',
|
||||
template: 'systems/daggerheart/templates/sheets-settings/action-settings/header.hbs'
|
||||
},
|
||||
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
|
||||
base: {
|
||||
id: 'base',
|
||||
template: 'systems/daggerheart/templates/sheets-settings/action-settings/base.hbs'
|
||||
},
|
||||
configuration: {
|
||||
id: 'configuration',
|
||||
template: 'systems/daggerheart/templates/sheets-settings/action-settings/configuration.hbs'
|
||||
},
|
||||
effect: {
|
||||
id: 'effect',
|
||||
template: 'systems/daggerheart/templates/sheets-settings/action-settings/effect.hbs'
|
||||
}
|
||||
};
|
||||
|
||||
static TABS = {
|
||||
base: {
|
||||
active: true,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'base',
|
||||
icon: null,
|
||||
label: 'DAGGERHEART.GENERAL.Tabs.base'
|
||||
},
|
||||
config: {
|
||||
active: false,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'config',
|
||||
icon: null,
|
||||
label: 'DAGGERHEART.GENERAL.Tabs.configuration'
|
||||
},
|
||||
effect: {
|
||||
active: false,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'effect',
|
||||
icon: null,
|
||||
label: 'DAGGERHEART.GENERAL.Tabs.effects'
|
||||
}
|
||||
};
|
||||
|
||||
static CLEAN_ARRAYS = ['damage.parts', 'cost', 'effects'];
|
||||
|
||||
_getTabs(tabs) {
|
||||
for (const v of Object.values(tabs)) {
|
||||
v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active;
|
||||
v.cssClass = v.active ? 'active' : '';
|
||||
}
|
||||
|
||||
return tabs;
|
||||
}
|
||||
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options, 'action');
|
||||
context.source = this.action.toObject(false);
|
||||
context.openSection = this.openSection;
|
||||
context.tabs = this._getTabs(this.constructor.TABS);
|
||||
context.config = CONFIG.DH;
|
||||
if (this.action.damage?.hasOwnProperty('includeBase') && this.action.type === 'attack')
|
||||
context.hasBaseDamage = !!this.action.parent.attack;
|
||||
context.costOptions = this.getCostOptions();
|
||||
context.getRollTypeOptions = this.getRollTypeOptions();
|
||||
context.disableOption = this.disableOption.bind(this);
|
||||
context.isNPC = this.action.actor?.isNPC;
|
||||
context.baseSaveDifficulty = this.action.actor?.baseSaveDifficulty;
|
||||
context.baseAttackBonus = this.action.actor?.system.attack?.roll.bonus;
|
||||
context.hasRoll = this.action.hasRoll;
|
||||
|
||||
const settingsTiers = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers;
|
||||
context.tierOptions = [
|
||||
{ key: 1, label: game.i18n.localize('DAGGERHEART.GENERAL.Tiers.1') },
|
||||
...Object.values(settingsTiers).map(x => ({ key: x.tier, label: x.name }))
|
||||
];
|
||||
return context;
|
||||
}
|
||||
|
||||
static toggleSection(_, button) {
|
||||
this.openSection = button.dataset.section === this.openSection ? null : button.dataset.section;
|
||||
this.render(true);
|
||||
}
|
||||
|
||||
getCostOptions() {
|
||||
const options = foundry.utils.deepClone(CONFIG.DH.GENERAL.abilityCosts);
|
||||
const resource = this.action.parent.resource;
|
||||
if (resource) {
|
||||
options.resource = {
|
||||
label: 'DAGGERHEART.GENERAL.itemResource',
|
||||
group: 'Global'
|
||||
};
|
||||
}
|
||||
|
||||
if (this.action.parent.metadata?.isQuantifiable) {
|
||||
options.quantity = {
|
||||
label: 'DAGGERHEART.GENERAL.itemQuantity',
|
||||
group: 'Global'
|
||||
};
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
getRollTypeOptions() {
|
||||
const types = foundry.utils.deepClone(CONFIG.DH.GENERAL.rollTypes);
|
||||
if (!this.action.actor) return types;
|
||||
Object.values(types).forEach(t => {
|
||||
if (this.action.actor.type !== 'character' && t.playerOnly) delete types[t.id];
|
||||
});
|
||||
return types;
|
||||
}
|
||||
|
||||
disableOption(index, costOptions, choices) {
|
||||
const filtered = foundry.utils.deepClone(costOptions);
|
||||
Object.keys(filtered).forEach(o => {
|
||||
if (choices.find((c, idx) => c.type === o && index !== idx)) filtered[o].disabled = true;
|
||||
});
|
||||
return filtered;
|
||||
}
|
||||
|
||||
_prepareSubmitData(_event, formData) {
|
||||
const submitData = foundry.utils.expandObject(formData.object);
|
||||
|
||||
const itemAbilityCostKeys = Object.keys(CONFIG.DH.GENERAL.itemAbilityCosts);
|
||||
for (const keyPath of this.constructor.CLEAN_ARRAYS) {
|
||||
const data = foundry.utils.getProperty(submitData, keyPath);
|
||||
const dataValues = data ? Object.values(data) : [];
|
||||
if (keyPath === 'cost') {
|
||||
for (var value of dataValues) {
|
||||
value.itemId = itemAbilityCostKeys.includes(value.key) ? this.action.parent.parent.id : null;
|
||||
}
|
||||
}
|
||||
|
||||
if (data) foundry.utils.setProperty(submitData, keyPath, dataValues);
|
||||
}
|
||||
return submitData;
|
||||
}
|
||||
|
||||
static async updateForm(event, _, formData) {
|
||||
const submitData = this._prepareSubmitData(event, formData),
|
||||
data = foundry.utils.mergeObject(this.action.toObject(), submitData);
|
||||
this.action = await this.action.update(data);
|
||||
|
||||
this.sheetUpdate?.(this.action);
|
||||
this.render();
|
||||
}
|
||||
|
||||
static addElement(event) {
|
||||
const data = this.action.toObject(),
|
||||
key = event.target.closest('[data-key]').dataset.key;
|
||||
if (!this.action[key]) return;
|
||||
|
||||
data[key].push(this.action.defaultValues[key] ?? {});
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
static removeElement(event, button) {
|
||||
event.stopPropagation();
|
||||
const data = this.action.toObject(),
|
||||
key = event.target.closest('[data-key]').dataset.key,
|
||||
index = button.dataset.index;
|
||||
data[key].splice(index, 1);
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
static addDamage(_event) {
|
||||
if (!this.action.damage.parts) return;
|
||||
const data = this.action.toObject(),
|
||||
part = {};
|
||||
if (this.action.actor?.isNPC) part.value = { multiplier: 'flat' };
|
||||
data.damage.parts.push(part);
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
static removeDamage(_event, button) {
|
||||
if (!this.action.damage.parts) return;
|
||||
const data = this.action.toObject(),
|
||||
index = button.dataset.index;
|
||||
data.damage.parts.splice(index, 1);
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
/** Specific implementation in extending classes **/
|
||||
static async addEffect(_event) {}
|
||||
static removeEffect(_event, _button) {}
|
||||
static editEffect(_event) {}
|
||||
|
||||
async close(options) {
|
||||
this.tabGroups.primary = 'base';
|
||||
await super.close(options);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,241 +1,32 @@
|
|||
import DaggerheartSheet from '../sheets/daggerheart-sheet.mjs';
|
||||
|
||||
const { ApplicationV2 } = foundry.applications.api;
|
||||
export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
||||
constructor(action, sheetUpdate) {
|
||||
super({});
|
||||
|
||||
this.action = action;
|
||||
this.sheetUpdate = sheetUpdate;
|
||||
this.openSection = null;
|
||||
}
|
||||
|
||||
get title() {
|
||||
return `${game.i18n.localize('DAGGERHEART.GENERAL.Tabs.settings')}: ${this.action.name}`;
|
||||
}
|
||||
import DHActionBaseConfig from './action-base-config.mjs';
|
||||
|
||||
export default class DHActionConfig extends DHActionBaseConfig {
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
classes: ['daggerheart', 'dh-style', 'dialog', 'max-800'],
|
||||
window: {
|
||||
icon: 'fa-solid fa-wrench',
|
||||
resizable: false
|
||||
},
|
||||
position: { width: 600, height: 'auto' },
|
||||
...DHActionBaseConfig.DEFAULT_OPTIONS,
|
||||
actions: {
|
||||
toggleSection: this.toggleSection,
|
||||
...DHActionBaseConfig.DEFAULT_OPTIONS.actions,
|
||||
addEffect: this.addEffect,
|
||||
removeEffect: this.removeEffect,
|
||||
addElement: this.addElement,
|
||||
removeElement: this.removeElement,
|
||||
editEffect: this.editEffect,
|
||||
addDamage: this.addDamage,
|
||||
removeDamage: this.removeDamage
|
||||
},
|
||||
form: {
|
||||
handler: this.updateForm,
|
||||
submitOnChange: true,
|
||||
closeOnSubmit: false
|
||||
editEffect: this.editEffect
|
||||
}
|
||||
};
|
||||
|
||||
static PARTS = {
|
||||
header: {
|
||||
id: 'header',
|
||||
template: 'systems/daggerheart/templates/sheets-settings/action-settings/header.hbs'
|
||||
},
|
||||
tabs: { template: 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs' },
|
||||
base: {
|
||||
id: 'base',
|
||||
template: 'systems/daggerheart/templates/sheets-settings/action-settings/base.hbs'
|
||||
},
|
||||
configuration: {
|
||||
id: 'configuration',
|
||||
template: 'systems/daggerheart/templates/sheets-settings/action-settings/configuration.hbs'
|
||||
},
|
||||
effect: {
|
||||
id: 'effect',
|
||||
template: 'systems/daggerheart/templates/sheets-settings/action-settings/effect.hbs'
|
||||
}
|
||||
};
|
||||
|
||||
static TABS = {
|
||||
base: {
|
||||
active: true,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'base',
|
||||
icon: null,
|
||||
label: 'DAGGERHEART.GENERAL.Tabs.base'
|
||||
},
|
||||
config: {
|
||||
active: false,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'config',
|
||||
icon: null,
|
||||
label: 'DAGGERHEART.GENERAL.Tabs.configuration'
|
||||
},
|
||||
effect: {
|
||||
active: false,
|
||||
cssClass: '',
|
||||
group: 'primary',
|
||||
id: 'effect',
|
||||
icon: null,
|
||||
label: 'DAGGERHEART.GENERAL.Tabs.effects'
|
||||
}
|
||||
};
|
||||
|
||||
static CLEAN_ARRAYS = ['damage.parts', 'cost', 'effects'];
|
||||
|
||||
_getTabs(tabs) {
|
||||
for (const v of Object.values(tabs)) {
|
||||
v.active = this.tabGroups[v.group] ? this.tabGroups[v.group] === v.id : v.active;
|
||||
v.cssClass = v.active ? 'active' : '';
|
||||
}
|
||||
|
||||
return tabs;
|
||||
}
|
||||
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options, 'action');
|
||||
context.source = this.action.toObject(false);
|
||||
context.openSection = this.openSection;
|
||||
context.tabs = this._getTabs(this.constructor.TABS);
|
||||
context.config = CONFIG.DH;
|
||||
async _prepareContext(options) {
|
||||
const context = await super._prepareContext(options);
|
||||
if (!!this.action.effects) context.effects = this.action.effects.map(e => this.action.item.effects.get(e._id));
|
||||
if (this.action.damage?.hasOwnProperty('includeBase') && this.action.type === 'attack')
|
||||
context.hasBaseDamage = !!this.action.parent.attack;
|
||||
context.getEffectDetails = this.getEffectDetails.bind(this);
|
||||
context.costOptions = this.getCostOptions();
|
||||
context.getRollTypeOptions = this.getRollTypeOptions();
|
||||
context.disableOption = this.disableOption.bind(this);
|
||||
context.isNPC = this.action.actor?.isNPC;
|
||||
context.baseSaveDifficulty = this.action.actor?.baseSaveDifficulty;
|
||||
context.baseAttackBonus = this.action.actor?.system.attack?.roll.bonus;
|
||||
context.hasRoll = this.action.hasRoll;
|
||||
|
||||
const settingsTiers = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers;
|
||||
context.tierOptions = [
|
||||
{ key: 1, label: game.i18n.localize('DAGGERHEART.GENERAL.Tiers.1') },
|
||||
...Object.values(settingsTiers).map(x => ({ key: x.tier, label: x.name }))
|
||||
];
|
||||
return context;
|
||||
}
|
||||
|
||||
static toggleSection(_, button) {
|
||||
this.openSection = button.dataset.section === this.openSection ? null : button.dataset.section;
|
||||
this.render(true);
|
||||
}
|
||||
|
||||
getCostOptions() {
|
||||
const options = foundry.utils.deepClone(CONFIG.DH.GENERAL.abilityCosts);
|
||||
const resource = this.action.parent.resource;
|
||||
if (resource) {
|
||||
options.resource = {
|
||||
label: 'DAGGERHEART.GENERAL.itemResource',
|
||||
group: 'Global'
|
||||
};
|
||||
}
|
||||
|
||||
if (this.action.parent.metadata?.isQuantifiable) {
|
||||
options.quantity = {
|
||||
label: 'DAGGERHEART.GENERAL.itemQuantity',
|
||||
group: 'Global'
|
||||
};
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
getRollTypeOptions() {
|
||||
const types = foundry.utils.deepClone(CONFIG.DH.GENERAL.rollTypes);
|
||||
if (!this.action.actor) return types;
|
||||
Object.values(types).forEach(t => {
|
||||
if (this.action.actor.type !== 'character' && t.playerOnly) delete types[t.id];
|
||||
});
|
||||
return types;
|
||||
}
|
||||
|
||||
disableOption(index, costOptions, choices) {
|
||||
const filtered = foundry.utils.deepClone(costOptions);
|
||||
Object.keys(filtered).forEach(o => {
|
||||
if (choices.find((c, idx) => c.type === o && index !== idx)) filtered[o].disabled = true;
|
||||
});
|
||||
return filtered;
|
||||
}
|
||||
|
||||
getEffectDetails(id) {
|
||||
return this.action.item.effects.get(id);
|
||||
}
|
||||
|
||||
_prepareSubmitData(_event, formData) {
|
||||
const submitData = foundry.utils.expandObject(formData.object);
|
||||
|
||||
const itemAbilityCostKeys = Object.keys(CONFIG.DH.GENERAL.itemAbilityCosts);
|
||||
for (const keyPath of this.constructor.CLEAN_ARRAYS) {
|
||||
const data = foundry.utils.getProperty(submitData, keyPath);
|
||||
const dataValues = data ? Object.values(data) : [];
|
||||
if (keyPath === 'cost') {
|
||||
for (var value of dataValues) {
|
||||
value.itemId = itemAbilityCostKeys.includes(value.key) ? this.action.parent.parent.id : null;
|
||||
}
|
||||
}
|
||||
|
||||
if (data) foundry.utils.setProperty(submitData, keyPath, dataValues);
|
||||
}
|
||||
return submitData;
|
||||
}
|
||||
|
||||
static async updateForm(event, _, formData) {
|
||||
const submitData = this._prepareSubmitData(event, formData),
|
||||
data = foundry.utils.mergeObject(this.action.toObject(), submitData);
|
||||
this.action = await this.action.update(data);
|
||||
|
||||
this.sheetUpdate?.(this.action);
|
||||
this.render();
|
||||
}
|
||||
|
||||
static addElement(event) {
|
||||
const data = this.action.toObject(),
|
||||
key = event.target.closest('[data-key]').dataset.key;
|
||||
if (!this.action[key]) return;
|
||||
|
||||
data[key].push(this.action.defaultValues[key] ?? {});
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
static removeElement(event, button) {
|
||||
event.stopPropagation();
|
||||
const data = this.action.toObject(),
|
||||
key = event.target.closest('[data-key]').dataset.key,
|
||||
index = button.dataset.index;
|
||||
data[key].splice(index, 1);
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
static addDamage(event) {
|
||||
if (!this.action.damage.parts) return;
|
||||
const data = this.action.toObject(),
|
||||
part = {};
|
||||
if (this.action.actor?.isNPC) part.value = { multiplier: 'flat' };
|
||||
data.damage.parts.push(part);
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
static removeDamage(event, button) {
|
||||
if (!this.action.damage.parts) return;
|
||||
const data = this.action.toObject(),
|
||||
index = button.dataset.index;
|
||||
data.damage.parts.splice(index, 1);
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
static async addEffect(event) {
|
||||
static async addEffect(_event) {
|
||||
if (!this.action.effects) return;
|
||||
const effectData = this._addEffectData.bind(this)(),
|
||||
[created] = await this.action.item.createEmbeddedDocuments('ActiveEffect', [effectData], { render: false }),
|
||||
data = this.action.toObject();
|
||||
const effectData = this._addEffectData.bind(this)();
|
||||
const data = this.action.toObject();
|
||||
|
||||
const [created] = await this.action.item.createEmbeddedDocuments('ActiveEffect', [effectData], {
|
||||
render: false
|
||||
});
|
||||
data.effects.push({ _id: created._id });
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
this.action.item.effects.get(created._id).sheet.render(true);
|
||||
|
|
@ -255,6 +46,10 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
};
|
||||
}
|
||||
|
||||
getEffectDetails(id) {
|
||||
return this.action.item.effects.get(id);
|
||||
}
|
||||
|
||||
static removeEffect(event, button) {
|
||||
if (!this.action.effects) return;
|
||||
const index = button.dataset.index,
|
||||
|
|
@ -267,9 +62,4 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
const id = event.target.closest('[data-effect-id]')?.dataset?.effectId;
|
||||
this.action.item.effects.get(id).sheet.render(true);
|
||||
}
|
||||
|
||||
async close(options) {
|
||||
this.tabGroups.primary = 'base';
|
||||
await super.close(options);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
import DHActionBaseConfig from './action-base-config.mjs';
|
||||
|
||||
export default class DHActionSettingsConfig extends DHActionBaseConfig {
|
||||
constructor(action, effects, sheetUpdate) {
|
||||
super(action);
|
||||
|
||||
this.effects = effects;
|
||||
this.sheetUpdate = sheetUpdate;
|
||||
}
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
...DHActionBaseConfig.DEFAULT_OPTIONS,
|
||||
actions: {
|
||||
...DHActionBaseConfig.DEFAULT_OPTIONS.actions,
|
||||
addEffect: this.addEffect,
|
||||
removeEffect: this.removeEffect,
|
||||
editEffect: this.editEffect
|
||||
}
|
||||
};
|
||||
|
||||
async _prepareContext(options) {
|
||||
const context = await super._prepareContext(options);
|
||||
context.effects = this.effects;
|
||||
context.getEffectDetails = this.getEffectDetails.bind(this);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
getEffectDetails(id) {
|
||||
return this.effects.find(x => x.id === id);
|
||||
}
|
||||
|
||||
static async addEffect(_event) {
|
||||
if (!this.action.effects) return;
|
||||
const effectData = game.system.api.data.activeEffects.BaseEffect.getDefaultObject();
|
||||
const data = this.action.toObject();
|
||||
|
||||
this.sheetUpdate(data, effectData);
|
||||
this.effects = [...this.effects, effectData];
|
||||
data.effects.push({ _id: effectData.id });
|
||||
this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) });
|
||||
}
|
||||
|
||||
static removeEffect(event, button) {
|
||||
if (!this.action.effects) return;
|
||||
const index = button.dataset.index,
|
||||
effectId = this.action.effects[index]._id;
|
||||
this.constructor.removeElement.bind(this)(event, button);
|
||||
this.sheetUpdate(
|
||||
this.action.toObject(),
|
||||
this.effects.find(x => x.id === effectId),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
static async editEffect(event) {
|
||||
const id = event.target.closest('[data-effect-id]')?.dataset?.effectId;
|
||||
const updatedEffect = await game.system.api.applications.sheetConfigs.SettingActiveEffectConfig.configure(
|
||||
this.getEffectDetails(id)
|
||||
);
|
||||
if (!updatedEffect) return;
|
||||
|
||||
this.effects = await this.sheetUpdate(this.action.toObject(), { ...updatedEffect, id });
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ export default class SettingActiveEffectConfig extends HandlebarsApplicationMixi
|
|||
}
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ['daggerheart', 'sheet', 'dh-style', 'active-effect-config'],
|
||||
classes: ['daggerheart', 'sheet', 'dh-style', 'active-effect-config', 'standard-form'],
|
||||
tag: 'form',
|
||||
position: {
|
||||
width: 560
|
||||
|
|
@ -131,6 +131,7 @@ export default class SettingActiveEffectConfig extends HandlebarsApplicationMixi
|
|||
if (partId in context.tabs) context.tab = context.tabs[partId];
|
||||
switch (partId) {
|
||||
case 'details':
|
||||
context.statuses = CONFIG.statusEffects.map(s => ({ value: s.id, label: game.i18n.localize(s.name) }));
|
||||
context.isActorEffect = false;
|
||||
context.isItemEffect = true;
|
||||
const useGeneric = game.settings.get(
|
||||
|
|
@ -138,10 +139,13 @@ export default class SettingActiveEffectConfig extends HandlebarsApplicationMixi
|
|||
CONFIG.DH.SETTINGS.gameSettings.appearance
|
||||
).showGenericStatusEffects;
|
||||
if (!useGeneric) {
|
||||
context.statuses = Object.values(CONFIG.DH.GENERAL.conditions).map(status => ({
|
||||
value: status.id,
|
||||
label: game.i18n.localize(status.name)
|
||||
}));
|
||||
context.statuses = [
|
||||
...context.statuses,
|
||||
Object.values(CONFIG.DH.GENERAL.conditions).map(status => ({
|
||||
value: status.id,
|
||||
label: game.i18n.localize(status.name)
|
||||
}))
|
||||
];
|
||||
}
|
||||
break;
|
||||
case 'changes':
|
||||
|
|
@ -157,7 +161,7 @@ export default class SettingActiveEffectConfig extends HandlebarsApplicationMixi
|
|||
return context;
|
||||
}
|
||||
|
||||
static async #onSubmit(event, form, formData) {
|
||||
static async #onSubmit(_event, _form, formData) {
|
||||
this.data = foundry.utils.expandObject(formData.object);
|
||||
this.close();
|
||||
}
|
||||
|
|
@ -193,11 +197,11 @@ export default class SettingActiveEffectConfig extends HandlebarsApplicationMixi
|
|||
* @type {ApplicationClickAction}
|
||||
*/
|
||||
static async #addChange() {
|
||||
const submitData = foundry.utils.expandObject(new FormDataExtended(this.form).object);
|
||||
const changes = Object.values(submitData.changes ?? {});
|
||||
changes.push({});
|
||||
const { changes, ...rest } = foundry.utils.expandObject(new FormDataExtended(this.form).object);
|
||||
const updatedChanges = Object.values(changes ?? {});
|
||||
updatedChanges.push({});
|
||||
|
||||
this.effect.changes = changes;
|
||||
this.effect = { ...rest, changes: updatedChanges };
|
||||
this.render();
|
||||
}
|
||||
|
||||
|
|
@ -208,12 +212,12 @@ export default class SettingActiveEffectConfig extends HandlebarsApplicationMixi
|
|||
*/
|
||||
static async #deleteChange(event) {
|
||||
const submitData = foundry.utils.expandObject(new FormDataExtended(this.form).object);
|
||||
const changes = Object.values(submitData.changes);
|
||||
const updatedChanges = Object.values(submitData.changes);
|
||||
const row = event.target.closest('li');
|
||||
const index = Number(row.dataset.index) || 0;
|
||||
changes.splice(index, 1);
|
||||
updatedChanges.splice(index, 1);
|
||||
|
||||
this.effect.changes = changes;
|
||||
this.effect = { ...submitData, changes: updatedChanges };
|
||||
this.render();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { actionsTypes } from '../../data/action/_module.mjs';
|
||||
import DHActionConfig from './action-config.mjs';
|
||||
import ActionSettingsConfig from './action-settings-config.mjs';
|
||||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
||||
|
|
@ -102,6 +102,8 @@ export default class SettingFeatureConfig extends HandlebarsApplicationMixin(App
|
|||
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 }
|
||||
|
|
@ -158,16 +160,55 @@ export default class SettingFeatureConfig extends HandlebarsApplicationMixin(App
|
|||
this.render();
|
||||
} else {
|
||||
const action = this.move.actions.get(id);
|
||||
await new DHActionConfig(action, async updatedMove => {
|
||||
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) {
|
||||
await this.settings.updateSource({ [`${this.actionsPath}.-=${target.dataset.id}`]: null });
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -459,7 +459,16 @@ export const allArmorFeatures = () => {
|
|||
...armorFeatures,
|
||||
...Object.keys(homebrewFeatures).reduce((acc, key) => {
|
||||
const feature = homebrewFeatures[key];
|
||||
acc[key] = { ...feature, label: feature.name };
|
||||
const actions = feature.actions.map(action => ({
|
||||
...action,
|
||||
effects: action.effects.map(effect => feature.effects.find(x => x.id === effect._id)),
|
||||
type: action.type
|
||||
}));
|
||||
const actionEffects = actions.flatMap(a => a.effects);
|
||||
|
||||
const effects = feature.effects.filter(effect => !actionEffects.some(x => x.id === effect.id));
|
||||
|
||||
acc[key] = { ...feature, label: feature.name, effects, actions };
|
||||
return acc;
|
||||
}, {})
|
||||
};
|
||||
|
|
@ -1414,11 +1423,21 @@ export const weaponFeatures = {
|
|||
export const allWeaponFeatures = () => {
|
||||
const homebrewFeatures = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).itemFeatures
|
||||
.weaponFeatures;
|
||||
|
||||
return {
|
||||
...weaponFeatures,
|
||||
...Object.keys(homebrewFeatures).reduce((acc, key) => {
|
||||
const feature = homebrewFeatures[key];
|
||||
acc[key] = { ...feature, label: feature.name };
|
||||
|
||||
const actions = feature.actions.map(action => ({
|
||||
...action,
|
||||
effects: action.effects.map(effect => feature.effects.find(x => x.id === effect._id)),
|
||||
type: action.type
|
||||
}));
|
||||
const actionEffects = actions.flatMap(a => a.effects);
|
||||
const effects = feature.effects.filter(effect => !actionEffects.some(x => x.id === effect.id));
|
||||
|
||||
acc[key] = { ...feature, label: feature.name, effects, actions };
|
||||
return acc;
|
||||
}, {})
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import BaseDataActor from './base.mjs';
|
||||
import DhLevelData from '../levelData.mjs';
|
||||
import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs';
|
||||
import { ActionField, ActionsField } from '../fields/actionField.mjs';
|
||||
import { ActionField } from '../fields/actionField.mjs';
|
||||
import { adjustDice, adjustRange } from '../../helpers/utils.mjs';
|
||||
import DHCompanionSettings from '../../applications/sheets-configs/companion-settings.mjs';
|
||||
import { resourceField, bonusField } from '../fields/actorField.mjs';
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<div class="settings-items">
|
||||
{{#each move.effects}}
|
||||
{{> "systems/daggerheart/templates/settings/components/settings-item-line.hbs" id=this.id type="effect" }}
|
||||
{{> "systems/daggerheart/templates/settings/components/settings-item-line.hbs" actionId=../move.id id=this.id type="effect" }}
|
||||
{{/each}}
|
||||
</div>
|
||||
</fieldset>
|
||||
|
|
|
|||
|
|
@ -4,10 +4,11 @@
|
|||
{{formGroup fields.disabled value=source.disabled rootId=rootId}}
|
||||
|
||||
{{#if isActorEffect}}
|
||||
{{formGroup fields.origin value=source.origin rootId=rootId disabled=true}}
|
||||
{{formGroup fields.origin value=source.origin rootId=rootId disabled=true}}
|
||||
{{/if}}
|
||||
|
||||
{{#if isItemEffect}}
|
||||
{{formGroup fields.transfer value=source.transfer rootId=rootId label=legacyTransfer.label hint=(localize "DAGGERHEART.EFFECTS.Attachments.transferHint")}}
|
||||
{{formGroup fields.transfer value=source.transfer rootId=rootId label=legacyTransfer.label hint=(localize "DAGGERHEART.EFFECTS.Attachments.transferHint")}}
|
||||
{{/if}}
|
||||
|
||||
{{formGroup fields.statuses value=source.statuses options=statuses rootId=rootId classes="statuses"}}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue