Fixed UseItem and ToChat

This commit is contained in:
WBHarry 2025-07-01 12:49:00 +02:00
parent 8ea596544b
commit 6018763d47
3 changed files with 150 additions and 74 deletions

View file

@ -10,7 +10,8 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
position: { width: 660, height: 766 }, position: { width: 660, height: 766 },
actions: { actions: {
reactionRoll: this.reactionRoll, reactionRoll: this.reactionRoll,
attackRoll: this.attackRoll, useItem: this.useItem,
toChat: this.toChat,
attackConfigure: this.attackConfigure, attackConfigure: this.attackConfigure,
addExperience: this.addExperience, addExperience: this.addExperience,
removeExperience: this.removeExperience, removeExperience: this.removeExperience,
@ -70,6 +71,12 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
return context; return context;
} }
getAction(element) {
const itemId = (element.target ?? element).closest('[data-item-id]').dataset.itemId,
item = this.document.system.actions.find(x => x.id === itemId);
return item;
}
static async updateForm(event, _, formData) { static async updateForm(event, _, formData) {
await this.document.update(formData.object); await this.document.update(formData.object);
this.render(); this.render();
@ -100,8 +107,36 @@ export default class AdversarySheet extends DaggerheartSheet(ActorSheetV2) {
await new DHAdversarySettings(this.document).render(true); await new DHAdversarySettings(this.document).render(true);
} }
static async attackRoll(event) { static async useItem(event) {
this.actor.system.attack.use(event); const action = this.getAction(event) ?? this.actor.system.attack;
action.use(event);
}
static async toChat(event, button) {
if (button?.dataset?.type === 'experience') {
const experience = this.document.system.experiences[button.dataset.uuid];
const cls = getDocumentClass('ChatMessage');
const systemData = {
name: game.i18n.localize('DAGGERHEART.General.Experience.Single'),
description: `${experience.name} ${
experience.modifier < 0 ? experience.modifier : `+${experience.modifier}`
}`
};
const msg = new cls({
type: 'abilityUse',
user: game.user.id,
system: systemData,
content: await foundry.applications.handlebars.renderTemplate(
'systems/daggerheart/templates/chat/ability-use.hbs',
systemData
)
});
cls.create(msg.toObject());
} else {
const item = this.getAction(event) ?? this.document.system.attack;
item.toChat(this.document.id);
}
} }
static async attackConfigure(event) { static async attackConfigure(event) {

View file

@ -815,9 +815,7 @@ export default class CharacterSheet extends DaggerheartSheet(ActorSheetV2) {
const cls = getDocumentClass('ChatMessage'); const cls = getDocumentClass('ChatMessage');
const systemData = { const systemData = {
name: game.i18n.localize('DAGGERHEART.General.Experience.Single'), name: game.i18n.localize('DAGGERHEART.General.Experience.Single'),
description: `${experience.description} ${ description: `${experience.name} ${experience.total < 0 ? experience.total : `+${experience.total}`}`
experience.total < 0 ? experience.total : `+${experience.total}`
}`
}; };
const msg = new cls({ const msg = new cls({
type: 'abilityUse', type: 'abilityUse',

View file

@ -73,7 +73,10 @@ export class DHBaseAction extends foundry.abstract.DataModel {
save: new fields.SchemaField({ save: new fields.SchemaField({
trait: new fields.StringField({ nullable: true, initial: null, choices: SYSTEM.ACTOR.abilities }), trait: new fields.StringField({ nullable: true, initial: null, choices: SYSTEM.ACTOR.abilities }),
difficulty: new fields.NumberField({ nullable: true, initial: 10, integer: true, min: 0 }), difficulty: new fields.NumberField({ nullable: true, initial: 10, integer: true, min: 0 }),
damageMod: new fields.StringField({ initial: SYSTEM.ACTIONS.damageOnSave.none.id, choices: SYSTEM.ACTIONS.damageOnSave }) damageMod: new fields.StringField({
initial: SYSTEM.ACTIONS.damageOnSave.none.id,
choices: SYSTEM.ACTIONS.damageOnSave
})
}), }),
target: new fields.SchemaField({ target: new fields.SchemaField({
type: new fields.StringField({ type: new fields.StringField({
@ -98,9 +101,12 @@ export class DHBaseAction extends foundry.abstract.DataModel {
initial: SYSTEM.GENERAL.healingTypes.hitPoints.id, initial: SYSTEM.GENERAL.healingTypes.hitPoints.id,
label: 'Healing' label: 'Healing'
}), }),
resultBased: new fields.BooleanField({ initial: false, label: "DAGGERHEART.Actions.Settings.ResultBased.label" }), resultBased: new fields.BooleanField({
initial: false,
label: 'DAGGERHEART.Actions.Settings.ResultBased.label'
}),
value: new fields.EmbeddedDataField(DHActionDiceData), value: new fields.EmbeddedDataField(DHActionDiceData),
valueAlt: new fields.EmbeddedDataField(DHActionDiceData), valueAlt: new fields.EmbeddedDataField(DHActionDiceData)
}) })
}, },
extraSchemas = {}; extraSchemas = {};
@ -191,12 +197,14 @@ export class DHBaseAction extends foundry.abstract.DataModel {
// Prepare Costs // Prepare Costs
const costsConfig = this.prepareCost(); const costsConfig = this.prepareCost();
if(isFastForward && !this.hasCost(costsConfig)) return ui.notifications.warn("You don't have the resources to use that action."); if (isFastForward && !this.hasCost(costsConfig))
return ui.notifications.warn("You don't have the resources to use that action.");
// config = this.prepareUseCost(config) // config = this.prepareUseCost(config)
// Prepare Uses // Prepare Uses
const usesConfig = this.prepareUse(); const usesConfig = this.prepareUse();
if(isFastForward && !this.hasUses(usesConfig)) return ui.notifications.warn("That action doesn't have remaining uses."); if (isFastForward && !this.hasUses(usesConfig))
return ui.notifications.warn("That action doesn't have remaining uses.");
// config = this.prepareUseCost(config) // config = this.prepareUseCost(config)
// Prepare Roll Data // Prepare Roll Data
@ -209,7 +217,7 @@ export class DHBaseAction extends foundry.abstract.DataModel {
costs: costsConfig, costs: costsConfig,
uses: usesConfig, uses: usesConfig,
data: actorData data: actorData
} };
if (Hooks.call(`${SYSTEM.id}.preUseAction`, this, config) === false) return; if (Hooks.call(`${SYSTEM.id}.preUseAction`, this, config) === false) return;
@ -287,7 +295,7 @@ export class DHBaseAction extends foundry.abstract.DataModel {
hasHealing: !!this.healing, hasHealing: !!this.healing,
hasEffect: !!this.effects?.length, hasEffect: !!this.effects?.length,
hasSave: this.hasSave hasSave: this.hasSave
} };
} }
requireConfigurationDialog(config) { requireConfigurationDialog(config) {
@ -317,7 +325,6 @@ export class DHBaseAction extends foundry.abstract.DataModel {
} }
targets = targets.map(t => this.formatTarget(t)); targets = targets.map(t => this.formatTarget(t));
return targets; return targets;
} }
prepareRange() { prepareRange() {
@ -344,7 +351,9 @@ export class DHBaseAction extends foundry.abstract.DataModel {
} }
async consume(config) { async consume(config) {
const resources = config.costs.filter(c => c.enabled !== false).map(c => { const resources = config.costs
.filter(c => c.enabled !== false)
.map(c => {
return { type: c.type, value: (c.total ?? c.value) * -1 }; return { type: c.type, value: (c.total ?? c.value) * -1 };
}); });
@ -388,7 +397,10 @@ export class DHBaseAction extends foundry.abstract.DataModel {
hasCost(costs) { hasCost(costs) {
const realCosts = this.getRealCosts(costs); const realCosts = this.getRealCosts(costs);
return realCosts.reduce((a, c) => a && this.actor.system.resources[c.type]?.value >= (c.total ?? c.value), true); return realCosts.reduce(
(a, c) => a && this.actor.system.resources[c.type]?.value >= (c.total ?? c.value),
true
);
} }
/* COST */ /* COST */
@ -442,7 +454,7 @@ export class DHBaseAction extends foundry.abstract.DataModel {
data.system.targets.forEach(async token => { data.system.targets.forEach(async token => {
if (!token.hit && !force) return; if (!token.hit && !force) return;
if (this.hasSave && token.saved.success === true) { if (this.hasSave && token.saved.success === true) {
effects = this.effects.filter(e => e.onSave === true) effects = this.effects.filter(e => e.onSave === true);
} }
if (!effects.length) return; if (!effects.length) return;
effects.forEach(async e => { effects.forEach(async e => {
@ -480,18 +492,24 @@ export class DHBaseAction extends foundry.abstract.DataModel {
/* SAVE */ /* SAVE */
async rollSave(target, event, message) { async rollSave(target, event, message) {
if (!target?.actor) return; if (!target?.actor) return;
target.actor.diceRoll({ target.actor
.diceRoll({
event, event,
title: 'Roll Save', title: 'Roll Save',
roll: { roll: {
trait: this.save.trait, trait: this.save.trait,
difficulty: this.save.difficulty, difficulty: this.save.difficulty,
type: "reaction" type: 'reaction'
}, },
data: target.actor.getRollData() data: target.actor.getRollData()
}).then(async (result) => {
if(result) this.updateChatMessage(message, target.id, {result: result.roll.total, success: result.roll.success});
}) })
.then(async result => {
if (result)
this.updateChatMessage(message, target.id, {
result: result.roll.total,
success: result.roll.success
});
});
} }
async updateChatMessage(message, targetId, changes, chain = true) { async updateChatMessage(message, targetId, changes, chain = true) {
@ -503,14 +521,38 @@ export class DHBaseAction extends foundry.abstract.DataModel {
await chatMessage.update({ 'system.targets': msgTargets }); await chatMessage.update({ 'system.targets': msgTargets });
}, 100); }, 100);
if (chain) { if (chain) {
if(message.system.source.message) this.updateChatMessage(ui.chat.collection.get(message.system.source.message), targetId, changes, false); if (message.system.source.message)
this.updateChatMessage(ui.chat.collection.get(message.system.source.message), targetId, changes, false);
const relatedChatMessages = ui.chat.collection.filter(c => c.system.source.message === message._id); const relatedChatMessages = ui.chat.collection.filter(c => c.system.source.message === message._id);
relatedChatMessages.forEach(c => { relatedChatMessages.forEach(c => {
this.updateChatMessage(c, targetId, changes, false); this.updateChatMessage(c, targetId, changes, false);
}) });
} }
} }
/* SAVE */ /* SAVE */
async toChat(origin) {
const cls = getDocumentClass('ChatMessage');
const systemData = {
title: game.i18n.localize('DAGGERHEART.ActionType.action'),
origin: origin,
img: this.img,
name: this.name,
description: this.description,
actions: []
};
const msg = new cls({
type: 'abilityUse',
user: game.user.id,
system: systemData,
content: await foundry.applications.handlebars.renderTemplate(
'systems/daggerheart/templates/chat/ability-use.hbs',
systemData
)
});
cls.create(msg.toObject());
}
} }
export class DHDamageAction extends DHBaseAction { export class DHDamageAction extends DHBaseAction {
@ -541,7 +583,7 @@ export class DHDamageAction extends DHBaseAction {
const config = { const config = {
title: game.i18n.format('DAGGERHEART.Chat.DamageRoll.Title', { damage: this.name }), title: game.i18n.format('DAGGERHEART.Chat.DamageRoll.Title', { damage: this.name }),
roll: { formula }, roll: { formula },
targets: (data.system?.targets.filter(t => t.hit) ?? data.targets), targets: data.system?.targets.filter(t => t.hit) ?? data.targets,
hasSave: this.hasSave, hasSave: this.hasSave,
source: data.system?.source, source: data.system?.source,
event event
@ -597,7 +639,8 @@ export class DHHealingAction extends DHBaseAction {
getFormulaValue(data) { getFormulaValue(data) {
let formulaValue = this.healing.value; let formulaValue = this.healing.value;
if(this.hasRoll && this.healing.resultBased && data.system.roll.result.duality === -1) return this.healing.valueAlt; if (this.hasRoll && this.healing.resultBased && data.system.roll.result.duality === -1)
return this.healing.valueAlt;
return formulaValue; return formulaValue;
} }