mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-12 19:51:08 +01:00
Refactor/actions v2 (#402)
* Action Refactor Part #1 * Fixed Weapon/Armor features. Fixed Feature actions * f * Action Refactor Part #2 * Fixes * Remove ActionsField from Companion * Fixes * Localization fix * BaseDataItem hasActions false --------- Co-authored-by: WBHarry <williambjrklund@gmail.com>
This commit is contained in:
parent
80744381f5
commit
0632a8c6bb
52 changed files with 988 additions and 743 deletions
|
|
@ -13,7 +13,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
this.action =
|
||||
config.data.attack?._id == config.source.action
|
||||
? config.data.attack
|
||||
: this.item.system.actions.find(a => a._id === config.source.action);
|
||||
: this.item.system.actions.get(config.source.action);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -68,19 +68,19 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
}));
|
||||
|
||||
if (this.config.costs?.length) {
|
||||
const updatedCosts = this.action.calcCosts(this.config.costs);
|
||||
const updatedCosts = game.system.api.fields.ActionFields.CostField.calcCosts.call(this.action, this.config.costs);
|
||||
context.costs = updatedCosts.map(x => ({
|
||||
...x,
|
||||
label: x.keyIsID
|
||||
? this.action.parent.parent.name
|
||||
: game.i18n.localize(CONFIG.DH.GENERAL.abilityCosts[x.key].label)
|
||||
}));
|
||||
context.canRoll = this.action.hasCost(updatedCosts);
|
||||
context.canRoll = game.system.api.fields.ActionFields.CostField.hasCost.call(this.action, updatedCosts);
|
||||
this.config.data.scale = this.config.costs[0].total;
|
||||
}
|
||||
if (this.config.uses?.max) {
|
||||
context.uses = this.action.calcUses(this.config.uses);
|
||||
context.canRoll = context.canRoll && this.action.hasUses(context.uses);
|
||||
context.uses = game.system.api.fields.ActionFields.UsesField.calcUses.call(this.action, this.config.uses);
|
||||
context.canRoll = context.canRoll && game.system.api.fields.ActionFields.UsesField.hasUses.call(this.action, context.uses);
|
||||
}
|
||||
if (this.roll) {
|
||||
context.roll = this.roll;
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
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.getRealIndex = this.getRealIndex.bind(this);
|
||||
context.getEffectDetails = this.getEffectDetails.bind(this);
|
||||
context.costOptions = this.getCostOptions();
|
||||
context.disableOption = this.disableOption.bind(this);
|
||||
|
|
@ -147,11 +146,6 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
return filtered;
|
||||
}
|
||||
|
||||
getRealIndex(index) {
|
||||
const data = this.action.toObject(false);
|
||||
return data.damage.parts.find(d => d.base) ? index - 1 : index;
|
||||
}
|
||||
|
||||
getEffectDetails(id) {
|
||||
return this.action.item.effects.get(id);
|
||||
}
|
||||
|
|
@ -175,19 +169,8 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
|
||||
static async updateForm(event, _, formData) {
|
||||
const submitData = this._prepareSubmitData(event, formData),
|
||||
data = foundry.utils.mergeObject(this.action.toObject(), submitData),
|
||||
container = foundry.utils.getProperty(this.action.parent, this.action.systemPath);
|
||||
let newActions;
|
||||
if (Array.isArray(container)) {
|
||||
newActions = foundry.utils.getProperty(this.action.parent, this.action.systemPath).map(x => x.toObject());
|
||||
if (!newActions.findSplice(x => x._id === data._id, data)) newActions.push(data);
|
||||
} else newActions = data;
|
||||
|
||||
const updates = await this.action.parent.parent.update({ [`system.${this.action.systemPath}`]: newActions });
|
||||
if (!updates) return;
|
||||
this.action = Array.isArray(container)
|
||||
? foundry.utils.getProperty(updates.system, this.action.systemPath)[this.action.index]
|
||||
: foundry.utils.getProperty(updates.system, this.action.systemPath);
|
||||
data = foundry.utils.mergeObject(this.action.toObject(), submitData);
|
||||
this.action = await this.action.update(data);
|
||||
this.render();
|
||||
}
|
||||
|
||||
|
|
@ -210,8 +193,10 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) {
|
|||
|
||||
static addDamage(event) {
|
||||
if (!this.action.damage.parts) return;
|
||||
const data = this.action.toObject();
|
||||
data.damage.parts.push({});
|
||||
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) });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ export default function DHApplicationMixin(Base) {
|
|||
deleteDoc: DHSheetV2.#deleteDoc,
|
||||
toChat: DHSheetV2.#toChat,
|
||||
useItem: DHSheetV2.#useItem,
|
||||
useAction: DHSheetV2.#useAction,
|
||||
toggleEffect: DHSheetV2.#toggleEffect,
|
||||
toggleExtended: DHSheetV2.#toggleExtended
|
||||
},
|
||||
|
|
@ -271,65 +270,8 @@ export default function DHApplicationMixin(Base) {
|
|||
*/
|
||||
static #getActionContextOptions() {
|
||||
/**@type {import('@client/applications/ux/context-menu.mjs').ContextMenuEntry[]} */
|
||||
const getAction = target => {
|
||||
const { actionId } = target.closest('[data-action-id]').dataset;
|
||||
const { actions, attack } = this.document.system;
|
||||
return attack?.id === actionId ? attack : actions?.find(a => a.id === actionId);
|
||||
};
|
||||
|
||||
const options = [
|
||||
{
|
||||
name: 'DAGGERHEART.APPLICATIONS.ContextMenu.useItem',
|
||||
icon: 'fa-solid fa-burst',
|
||||
condition:
|
||||
this.document instanceof foundry.documents.Actor ||
|
||||
(this.document instanceof foundry.documents.Item && this.document.parent),
|
||||
callback: (target, event) => getAction(target).use(event)
|
||||
},
|
||||
{
|
||||
name: 'DAGGERHEART.APPLICATIONS.ContextMenu.sendToChat',
|
||||
icon: 'fa-solid fa-message',
|
||||
callback: target => getAction(target).toChat(this.document.id)
|
||||
},
|
||||
{
|
||||
name: 'CONTROLS.CommonEdit',
|
||||
icon: 'fa-solid fa-pen-to-square',
|
||||
callback: target => new DHActionConfig(getAction(target)).render({ force: true })
|
||||
},
|
||||
{
|
||||
name: 'CONTROLS.CommonDelete',
|
||||
icon: 'fa-solid fa-trash',
|
||||
condition: target => {
|
||||
const { actionId } = target.closest('[data-action-id]').dataset;
|
||||
const { attack } = this.document.system;
|
||||
return attack?.id !== actionId;
|
||||
},
|
||||
callback: async target => {
|
||||
const action = getAction(target);
|
||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||
window: {
|
||||
title: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.title', {
|
||||
type: game.i18n.localize(`DAGGERHEART.GENERAL.Action.single`),
|
||||
name: action.name
|
||||
})
|
||||
},
|
||||
content: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.text', {
|
||||
name: action.name
|
||||
})
|
||||
});
|
||||
if (!confirmed) return;
|
||||
|
||||
return this.document.update({
|
||||
'system.actions': this.document.system.actions.filter(a => a.id !== action.id)
|
||||
});
|
||||
}
|
||||
}
|
||||
].map(option => ({
|
||||
...option,
|
||||
icon: `<i class="${option.icon}"></i>`
|
||||
}));
|
||||
|
||||
return options;
|
||||
const options = [];
|
||||
return [...options, ...this._getContextMenuCommonOptions.call(this, { usable: true, toChat: true })];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -341,6 +283,10 @@ export default function DHApplicationMixin(Base) {
|
|||
{
|
||||
name: 'CONTROLS.CommonEdit',
|
||||
icon: 'fa-solid fa-pen-to-square',
|
||||
condition: target => {
|
||||
const doc = getDocFromElement(target);
|
||||
return !doc.hasOwnProperty('systemPath') || doc.inCollection
|
||||
},
|
||||
callback: target => getDocFromElement(target).sheet.render({ force: true })
|
||||
}
|
||||
];
|
||||
|
|
@ -409,7 +355,7 @@ export default function DHApplicationMixin(Base) {
|
|||
? getDocFromElement(extensibleElement)
|
||||
: this.document.system.attack?.id === actionId
|
||||
? this.document.system.attack
|
||||
: this.document.system.actions?.find(a => a.id === actionId);
|
||||
: this.document.system.actions?.get(actionId);
|
||||
if (!doc) return;
|
||||
|
||||
const description = doc.system?.description ?? doc.description;
|
||||
|
|
@ -435,61 +381,29 @@ export default function DHApplicationMixin(Base) {
|
|||
static async #createDoc(event, target) {
|
||||
const { documentClass, type, inVault, disabled } = target.dataset;
|
||||
const parentIsItem = this.document.documentName === 'Item';
|
||||
const parent = parentIsItem && documentClass === 'Item' ? null : this.document;
|
||||
const parent =
|
||||
parentIsItem && documentClass === 'Item'
|
||||
? type === 'action'
|
||||
? this.document.system
|
||||
: null
|
||||
: this.document;
|
||||
|
||||
if (type === 'action') {
|
||||
const { type: actionType } =
|
||||
(await foundry.applications.api.DialogV2.input({
|
||||
window: { title: 'Select Action Type' },
|
||||
classes: ['daggerheart', 'dh-style'],
|
||||
content: await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/daggerheart/templates/actionTypes/actionType.hbs',
|
||||
{
|
||||
types: CONFIG.DH.ACTIONS.actionTypes,
|
||||
itemName: game.i18n.localize('DAGGERHEART.CONFIG.SelectAction.selectAction')
|
||||
}
|
||||
),
|
||||
ok: {
|
||||
label: game.i18n.format('DOCUMENT.Create', {
|
||||
type: game.i18n.localize('DAGGERHEART.GENERAL.Action.single')
|
||||
})
|
||||
}
|
||||
})) ?? {};
|
||||
if (!actionType) return;
|
||||
const cls = game.system.api.models.actions.actionsTypes[actionType];
|
||||
const action = new cls(
|
||||
{
|
||||
_id: foundry.utils.randomID(),
|
||||
type: actionType,
|
||||
name: game.i18n.localize(CONFIG.DH.ACTIONS.actionTypes[actionType].name),
|
||||
...cls.getSourceConfig(this.document)
|
||||
},
|
||||
{
|
||||
parent: this.document
|
||||
}
|
||||
);
|
||||
await this.document.update({ 'system.actions': [...this.document.system.actions, action] });
|
||||
await new DHActionConfig(this.document.system.actions[this.document.system.actions.length - 1]).render({
|
||||
force: true
|
||||
const cls =
|
||||
type === 'action' ? game.system.api.models.actions.actionsTypes.base : getDocumentClass(documentClass);
|
||||
const data = {
|
||||
name: cls.defaultName({ type, parent }),
|
||||
type
|
||||
};
|
||||
if (inVault) data['system.inVault'] = true;
|
||||
if (disabled) data.disabled = true;
|
||||
|
||||
const doc = await cls.create(data, { parent, renderSheet: !event.shiftKey });
|
||||
if (parentIsItem && type === 'feature') {
|
||||
await this.document.update({
|
||||
'system.features': this.document.system.toObject().features.concat(doc.uuid)
|
||||
});
|
||||
return action;
|
||||
} else {
|
||||
const cls = getDocumentClass(documentClass);
|
||||
const data = {
|
||||
name: cls.defaultName({ type, parent }),
|
||||
type
|
||||
};
|
||||
if (inVault) data['system.inVault'] = true;
|
||||
if (disabled) data.disabled = true;
|
||||
|
||||
const doc = await cls.create(data, { parent, renderSheet: !event.shiftKey });
|
||||
if (parentIsItem && type === 'feature') {
|
||||
await this.document.update({
|
||||
'system.features': this.document.system.toObject().features.concat(doc.uuid)
|
||||
});
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -499,12 +413,6 @@ export default function DHApplicationMixin(Base) {
|
|||
static #editDoc(_event, target) {
|
||||
const doc = getDocFromElement(target);
|
||||
if (doc) return doc.sheet.render({ force: true });
|
||||
|
||||
// TODO: REDO this
|
||||
const { actionId } = target.closest('[data-action-id]').dataset;
|
||||
const { actions, attack } = this.document.system;
|
||||
const action = attack?.id === actionId ? attack : actions?.find(a => a.id === actionId);
|
||||
new DHActionConfig(action).render({ force: true });
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -513,34 +421,10 @@ export default function DHApplicationMixin(Base) {
|
|||
*/
|
||||
static async #deleteDoc(event, target) {
|
||||
const doc = getDocFromElement(target);
|
||||
|
||||
if (doc) {
|
||||
if (event.shiftKey) return doc.delete();
|
||||
else return await doc.deleteDialog();
|
||||
}
|
||||
|
||||
// TODO: REDO this
|
||||
const { actionId } = target.closest('[data-action-id]').dataset;
|
||||
const { actions, attack } = this.document.system;
|
||||
if (attack?.id === actionId) return;
|
||||
const action = actions.find(a => a.id === actionId);
|
||||
|
||||
if (!event.shiftKey) {
|
||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||
window: {
|
||||
title: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.title', {
|
||||
type: game.i18n.localize(`DAGGERHEART.GENERAL.Action.single`),
|
||||
name: action.name
|
||||
})
|
||||
},
|
||||
content: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.text', { name: action.name })
|
||||
});
|
||||
if (!confirmed) return;
|
||||
}
|
||||
|
||||
return await this.document.update({
|
||||
'system.actions': actions.filter(a => a.id !== action.id)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -549,13 +433,6 @@ export default function DHApplicationMixin(Base) {
|
|||
*/
|
||||
static async #toChat(_event, target) {
|
||||
let doc = getDocFromElement(target);
|
||||
|
||||
// TODO: REDO this
|
||||
if (!doc) {
|
||||
const { actionId } = target.closest('[data-action-id]').dataset;
|
||||
const { actions, attack } = this.document.system;
|
||||
doc = attack?.id === actionId ? attack : actions?.find(a => a.id === actionId);
|
||||
}
|
||||
return doc.toChat(this.document.id);
|
||||
}
|
||||
|
||||
|
|
@ -565,29 +442,9 @@ export default function DHApplicationMixin(Base) {
|
|||
*/
|
||||
static async #useItem(event, target) {
|
||||
let doc = getDocFromElement(target);
|
||||
// TODO: REDO this
|
||||
if (!doc) {
|
||||
const { actionId } = target.closest('[data-action-id]').dataset;
|
||||
const { actions, attack } = this.document.system;
|
||||
doc = attack?.id === actionId ? attack : actions?.find(a => a.id === actionId);
|
||||
if (this.document instanceof foundry.documents.Item && !this.document.parent) return;
|
||||
}
|
||||
|
||||
await doc.use(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a item
|
||||
* @type {ApplicationClickAction}
|
||||
*/
|
||||
static async #useAction(event, target) {
|
||||
const doc = getDocFromElement(target);
|
||||
const { actionId } = target.closest('[data-action-id]').dataset;
|
||||
const { actions, attack } = doc.system;
|
||||
const action = attack?.id === actionId ? attack : actions?.find(a => a.id === actionId);
|
||||
await action.use(event, doc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle a ActiveEffect
|
||||
* @type {ApplicationClickAction}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
|
|||
submitOnChange: true
|
||||
},
|
||||
actions: {
|
||||
removeAction: DHBaseItemSheet.#removeAction,
|
||||
addFeature: DHBaseItemSheet.#addFeature,
|
||||
deleteFeature: DHBaseItemSheet.#deleteFeature,
|
||||
addResource: DHBaseItemSheet.#addResource,
|
||||
|
|
@ -144,33 +143,6 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
|
|||
/* Application Clicks Actions */
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Remove an action from the item.
|
||||
* @type {ApplicationClickAction}
|
||||
*/
|
||||
static async #removeAction(event, button) {
|
||||
event.stopPropagation();
|
||||
const actionIndex = button.closest('[data-index]').dataset.index;
|
||||
const action = this.document.system.actions[actionIndex];
|
||||
|
||||
if (!event.shiftKey) {
|
||||
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||
window: {
|
||||
title: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.title', {
|
||||
type: game.i18n.localize(`DAGGERHEART.GENERAL.Action.single`),
|
||||
name: action.name
|
||||
})
|
||||
},
|
||||
content: game.i18n.format('DAGGERHEART.APPLICATIONS.DeleteConfirmation.text', { name: action.name })
|
||||
});
|
||||
if (!confirmed) return;
|
||||
}
|
||||
|
||||
await this.document.update({
|
||||
'system.actions': this.document.system.actions.filter((_, index) => index !== Number.parseInt(actionIndex))
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new feature to the item, prompting the user for its type.
|
||||
* @type {ApplicationClickAction}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
? actor.system.attack
|
||||
: item.system.attack?._id === actionId
|
||||
? item.system.attack
|
||||
: item?.system?.actions?.find(a => a._id === actionId);
|
||||
: item?.system?.actions?.get(actionId);
|
||||
return action;
|
||||
}
|
||||
|
||||
|
|
@ -254,8 +254,8 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
|
||||
const action = message.system.actions[Number.parseInt(event.currentTarget.dataset.index)];
|
||||
const actor = game.actors.get(message.system.source.actor);
|
||||
await actor.useAction(action);
|
||||
}
|
||||
await actor.use(action);
|
||||
};
|
||||
|
||||
async actionUseButton(event, message) {
|
||||
const { moveIndex, actionIndex } = event.currentTarget.dataset;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export default class DhHotbar extends foundry.applications.ui.Hotbar {
|
|||
});
|
||||
}
|
||||
|
||||
const action = item.system.actions.find(x => x.id === actionId);
|
||||
const action = item.system.actions.get(actionId);
|
||||
if (!action) {
|
||||
return ui.notifications.warn('DAGGERHEART.UI.Notifications.actionIsMissing');
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue