mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-12 03:31:07 +01:00
Task/415 action refactor part 2 (#1094)
This commit is contained in:
parent
8e5dd22370
commit
1eb3ff11c0
47 changed files with 1244 additions and 641 deletions
|
|
@ -1,3 +1,5 @@
|
|||
import { abilities } from "../../config/actorConfig.mjs";
|
||||
|
||||
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
|
||||
|
||||
export default class D20RollDialog extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||
|
|
@ -7,7 +9,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
this.roll = roll;
|
||||
this.config = config;
|
||||
this.config.experiences = [];
|
||||
this.reactionOverride = config.roll?.type === 'reaction';
|
||||
this.reactionOverride = config.actionType === 'reaction';
|
||||
|
||||
if (config.source?.action) {
|
||||
this.item = config.data.parent.items.get(config.source.item) ?? config.data.parent;
|
||||
|
|
@ -20,7 +22,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
id: 'roll-selection',
|
||||
// id: 'roll-selection',
|
||||
classes: ['daggerheart', 'dialog', 'dh-style', 'views', 'roll-selection'],
|
||||
position: {
|
||||
width: 'auto'
|
||||
|
|
@ -42,7 +44,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
};
|
||||
|
||||
get title() {
|
||||
return this.config.title;
|
||||
return `${this.config.title}${this.actor ? `: ${this.actor.name}` : ''}`;
|
||||
}
|
||||
|
||||
get actor() {
|
||||
|
|
@ -113,15 +115,21 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
context.isLite = this.config.roll?.lite;
|
||||
context.extraFormula = this.config.extraFormula;
|
||||
context.formula = this.roll.constructFormula(this.config);
|
||||
if(this.actor.system.traits) context.abilities = this.getTraitModifiers();
|
||||
|
||||
context.showReaction = !context.rollConfig.type && context.rollType === 'DualityRoll';
|
||||
context.showReaction = !this.config.roll?.type && context.rollType === 'DualityRoll';
|
||||
context.reactionOverride = this.reactionOverride;
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
getTraitModifiers() {
|
||||
return Object.values(abilities).map(a => ({ id: a.id, label: `${game.i18n.localize(a.label)} (${this.actor.system.traits[a.id]?.value.signedString() ?? 0})` }))
|
||||
}
|
||||
|
||||
static updateRollConfiguration(event, _, formData) {
|
||||
const { ...rest } = foundry.utils.expandObject(formData.object);
|
||||
|
||||
this.config.selectedRollMode = rest.selectedRollMode;
|
||||
|
||||
if (this.config.costs) {
|
||||
|
|
@ -133,6 +141,12 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
this.roll[key] = value;
|
||||
});
|
||||
}
|
||||
if(rest.hasOwnProperty("trait")) {
|
||||
this.config.roll.trait = rest.trait;
|
||||
this.config.title = game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||
ability: game.i18n.localize(abilities[this.config.roll.trait]?.label)
|
||||
});
|
||||
}
|
||||
this.config.extraFormula = rest.extraFormula;
|
||||
this.render();
|
||||
}
|
||||
|
|
@ -151,31 +165,29 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
this.config.experiences.indexOf(button.dataset.key) > -1
|
||||
? this.config.experiences.filter(x => x !== button.dataset.key)
|
||||
: [...this.config.experiences, button.dataset.key];
|
||||
if (this.config?.data?.parent?.type === 'character' || this.config?.data?.parent?.type === 'companion') {
|
||||
this.config.costs =
|
||||
this.config.costs.indexOf(this.config.costs.find(c => c.extKey === button.dataset.key)) > -1
|
||||
? this.config.costs.filter(x => x.extKey !== button.dataset.key)
|
||||
: [
|
||||
...this.config.costs,
|
||||
{
|
||||
extKey: button.dataset.key,
|
||||
key: 'hope',
|
||||
value: 1,
|
||||
name: this.config.data?.experiences?.[button.dataset.key]?.name
|
||||
}
|
||||
];
|
||||
}
|
||||
this.config.costs =
|
||||
this.config.costs.indexOf(this.config.costs.find(c => c.extKey === button.dataset.key)) > -1
|
||||
? this.config.costs.filter(x => x.extKey !== button.dataset.key)
|
||||
: [
|
||||
...this.config.costs,
|
||||
{
|
||||
extKey: button.dataset.key,
|
||||
key: this.config?.data?.parent?.isNPC ? 'fear' : 'hope',
|
||||
value: 1,
|
||||
name: this.config.data?.experiences?.[button.dataset.key]?.name
|
||||
}
|
||||
];
|
||||
this.render();
|
||||
}
|
||||
|
||||
static toggleReaction() {
|
||||
if (this.config.roll) {
|
||||
this.reactionOverride = !this.reactionOverride;
|
||||
this.config.roll.type = this.reactionOverride
|
||||
this.config.actionType = this.reactionOverride
|
||||
? CONFIG.DH.ITEM.actionTypes.reaction.id
|
||||
: this.config.roll.type === CONFIG.DH.ITEM.actionTypes.reaction.id
|
||||
: this.config.actionType === CONFIG.DH.ITEM.actionTypes.reaction.id
|
||||
? null
|
||||
: this.config.roll.type;
|
||||
: this.config.actionType;
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,13 +35,14 @@ export default class DhAutomationSettings extends HandlebarsApplicationMixin(App
|
|||
header: { template: 'systems/daggerheart/templates/settings/automation-settings/header.hbs' },
|
||||
general: { template: 'systems/daggerheart/templates/settings/automation-settings/general.hbs' },
|
||||
rules: { template: 'systems/daggerheart/templates/settings/automation-settings/rules.hbs' },
|
||||
roll: { template: 'systems/daggerheart/templates/settings/automation-settings/roll.hbs' },
|
||||
footer: { template: 'systems/daggerheart/templates/settings/automation-settings/footer.hbs' }
|
||||
};
|
||||
|
||||
/** @inheritdoc */
|
||||
static TABS = {
|
||||
main: {
|
||||
tabs: [{ id: 'general' }, { id: 'rules' }],
|
||||
tabs: [{ id: 'general' }, { id: 'rules' }, { id: 'roll' }],
|
||||
initial: 'general',
|
||||
labelPrefix: 'DAGGERHEART.GENERAL.Tabs'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,9 +146,9 @@ export default class AdversarySheet extends DHBaseActorSheet {
|
|||
title: `Reaction Roll: ${this.actor.name}`,
|
||||
headerTitle: 'Adversary Reaction Roll',
|
||||
roll: {
|
||||
type: 'reaction'
|
||||
type: 'trait'
|
||||
},
|
||||
type: 'trait',
|
||||
actionType: 'reaction',
|
||||
hasRoll: true,
|
||||
data: this.actor.getRollData()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -679,31 +679,7 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
|||
})
|
||||
});
|
||||
|
||||
this.consumeResource(result?.costs);
|
||||
}
|
||||
|
||||
// Remove when Action Refactor part #2 done
|
||||
async consumeResource(costs) {
|
||||
if (!costs?.length) return;
|
||||
const usefulResources = {
|
||||
...foundry.utils.deepClone(this.actor.system.resources),
|
||||
fear: {
|
||||
value: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear),
|
||||
max: game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).maxFear,
|
||||
reversed: false
|
||||
}
|
||||
};
|
||||
const resources = game.system.api.fields.ActionFields.CostField.getRealCosts(costs).map(c => {
|
||||
const resource = usefulResources[c.key];
|
||||
return {
|
||||
key: c.key,
|
||||
value: (c.total ?? c.value) * (resource.isReversed ? 1 : -1),
|
||||
target: resource.target,
|
||||
keyIsID: resource.keyIsID
|
||||
};
|
||||
});
|
||||
|
||||
await this.actor.modifyResource(resources);
|
||||
if(result) game.system.api.fields.ActionFields.CostField.execute.call(this, result);
|
||||
}
|
||||
|
||||
//TODO: redo toggleEquipItem method
|
||||
|
|
|
|||
|
|
@ -412,6 +412,16 @@ export default function DHApplicationMixin(Base) {
|
|||
];
|
||||
|
||||
if (usable) {
|
||||
options.unshift({
|
||||
name: 'DAGGERHEART.APPLICATIONS.ContextMenu.cancelBeastform',
|
||||
icon: 'fa-solid fa-ban',
|
||||
condition: target => {
|
||||
const doc = getDocFromElementSync(target);
|
||||
return doc && doc.system?.actions?.some(a => a.type === "beastform");
|
||||
},
|
||||
callback: async target => game.system.api.fields.ActionFields.BeastformField.handleActiveTransformations.call(await getDocFromElement(target))
|
||||
});
|
||||
|
||||
options.unshift({
|
||||
name: 'DAGGERHEART.GENERAL.damage',
|
||||
icon: 'fa-solid fa-explosion',
|
||||
|
|
@ -422,7 +432,9 @@ export default function DHApplicationMixin(Base) {
|
|||
callback: async (target, event) => {
|
||||
const doc = await getDocFromElement(target),
|
||||
action = doc?.system?.attack ?? doc;
|
||||
return action && action.use(event, { byPassRoll: true });
|
||||
const config = action.prepareConfig(event);
|
||||
config.hasRoll = false;
|
||||
return action && action.workflow.get("damage").execute(config, null, true);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import { emitAsGM, GMUpdateEvent } from '../../systemRegistration/socket.mjs';
|
||||
|
||||
export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLog {
|
||||
constructor(options) {
|
||||
super(options);
|
||||
|
|
@ -55,21 +53,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
}
|
||||
|
||||
addChatListeners = async (app, html, data) => {
|
||||
html.querySelectorAll('.duality-action-damage').forEach(element =>
|
||||
element.addEventListener('click', event => this.onRollDamage(event, data.message))
|
||||
);
|
||||
html.querySelectorAll('.target-save').forEach(element =>
|
||||
element.addEventListener('click', event => this.onRollSave(event, data.message))
|
||||
);
|
||||
html.querySelectorAll('.roll-all-save-button').forEach(element =>
|
||||
element.addEventListener('click', event => this.onRollAllSave(event, data.message))
|
||||
);
|
||||
html.querySelectorAll('.simple-roll-button').forEach(element =>
|
||||
element.addEventListener('click', event => this.onRollSimple(event, data.message))
|
||||
);
|
||||
html.querySelectorAll('.healing-button').forEach(element =>
|
||||
element.addEventListener('click', event => this.onHealing(event, data.message))
|
||||
);
|
||||
html.querySelectorAll('.ability-use-button').forEach(element =>
|
||||
element.addEventListener('click', event => this.abilityUseButton(event, data.message))
|
||||
);
|
||||
|
|
@ -90,80 +76,6 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
super.close(options);
|
||||
}
|
||||
|
||||
async getActor(uuid) {
|
||||
return await foundry.utils.fromUuid(uuid);
|
||||
}
|
||||
|
||||
getAction(actor, itemId, actionId) {
|
||||
const item = actor.items.get(itemId),
|
||||
action =
|
||||
actor.system.attack?._id === actionId
|
||||
? actor.system.attack
|
||||
: item.system.attack?._id === actionId
|
||||
? item.system.attack
|
||||
: item?.system?.actions?.get(actionId);
|
||||
return action;
|
||||
}
|
||||
|
||||
async onRollDamage(event, message) {
|
||||
event.stopPropagation();
|
||||
const actor = await this.getActor(message.system.source.actor);
|
||||
if(!actor.isOwner) return true;
|
||||
if (message.system.source.item && message.system.source.action) {
|
||||
const action = this.getAction(actor, message.system.source.item, message.system.source.action);
|
||||
if (!action || !action?.rollDamage) return;
|
||||
await action.rollDamage(event, message);
|
||||
}
|
||||
}
|
||||
|
||||
async onRollSave(event, message) {
|
||||
event.stopPropagation();
|
||||
const actor = await this.getActor(message.system.source.actor),
|
||||
tokenId = event.target.closest('[data-token]')?.dataset.token,
|
||||
token = game.canvas.tokens.get(tokenId);
|
||||
if (!token?.actor || !token.isOwner) return true;
|
||||
if (message.system.source.item && message.system.source.action) {
|
||||
const action = this.getAction(actor, message.system.source.item, message.system.source.action);
|
||||
if (!action || !action?.hasSave) return;
|
||||
action.rollSave(token.actor, event, message).then(result =>
|
||||
emitAsGM(
|
||||
GMUpdateEvent.UpdateSaveMessage,
|
||||
action.updateSaveMessage.bind(action, result, message, token.id),
|
||||
{
|
||||
action: action.uuid,
|
||||
message: message._id,
|
||||
token: token.id,
|
||||
result
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async onRollAllSave(event, message) {
|
||||
event.stopPropagation();
|
||||
if (!game.user.isGM) return;
|
||||
const targets = event.target.parentElement.querySelectorAll('[data-token] .target-save');
|
||||
const actor = await this.getActor(message.system.source.actor),
|
||||
action = this.getAction(actor, message.system.source.item, message.system.source.action);
|
||||
targets.forEach(async el => {
|
||||
const tokenId = el.closest('[data-token]')?.dataset.token,
|
||||
token = game.canvas.tokens.get(tokenId);
|
||||
if (!token.actor) return;
|
||||
if (game.user === token.actor.owner) el.dispatchEvent(new PointerEvent('click', { shiftKey: true }));
|
||||
else {
|
||||
token.actor.owner
|
||||
.query('reactionRoll', {
|
||||
actionId: action.uuid,
|
||||
actorId: token.actor.uuid,
|
||||
event,
|
||||
message
|
||||
})
|
||||
.then(result => action.updateSaveMessage(result, message, token.id));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async onRollSimple(event, message) {
|
||||
const buttonType = event.target.dataset.type ?? 'damage',
|
||||
total = message.rolls.reduce((a, c) => a + Roll.fromJSON(c).total, 0),
|
||||
|
|
@ -197,8 +109,11 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
|||
item.system.attack?.id === event.currentTarget.id
|
||||
? item.system.attack
|
||||
: item.system.actions.get(event.currentTarget.id);
|
||||
if (event.currentTarget.dataset.directDamage) action.use(event, { byPassRoll: true });
|
||||
else action.use(event);
|
||||
if (event.currentTarget.dataset.directDamage) {
|
||||
const config = action.prepareConfig(event);
|
||||
config.hasRoll = false;
|
||||
action.workflow.get("damage").execute(config, null, true);
|
||||
} else action.use(event);
|
||||
}
|
||||
|
||||
async actionUseButton(event, message) {
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV
|
|||
|
||||
/** @override */
|
||||
async _preRender(context, options) {
|
||||
if (this.currentFear > this.maxFear)
|
||||
if (this.currentFear > this.maxFear && game.user.isGM)
|
||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear, this.maxFear);
|
||||
}
|
||||
|
||||
|
|
@ -107,18 +107,5 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV
|
|||
|
||||
async updateFear(value) {
|
||||
return emitAsGM(GMUpdateEvent.UpdateFear, game.settings.set.bind(game.settings, CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear), value);
|
||||
/* if(!game.user.isGM)
|
||||
await game.socket.emit(`system.${CONFIG.DH.id}`, {
|
||||
action: socketEvent.GMUpdate,
|
||||
data: {
|
||||
action: GMUpdateEvent.UpdateFear,
|
||||
update: value
|
||||
}
|
||||
});
|
||||
else
|
||||
game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear, value); */
|
||||
/* if (!game.user.isGM) return;
|
||||
value = Math.max(0, Math.min(this.maxFear, value));
|
||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear, value); */
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue