mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-17 07:36:26 +01:00
Some fixes
This commit is contained in:
parent
92a0883806
commit
fb9240e130
18 changed files with 94 additions and 82 deletions
|
|
@ -2228,11 +2228,11 @@
|
|||
},
|
||||
"damageApply": {
|
||||
"label": "Apply Damage/Healing",
|
||||
"hint": "Automatically apply damages & healings. Targets must be selected before the action is made. Bypass users permissions."
|
||||
"hint": "Automatically apply damages & healings. Targets must be selected before the action is made and Reaction Roll Automation must be different than Never. Bypass users permissions."
|
||||
},
|
||||
"effect": {
|
||||
"label": "Apply Effects",
|
||||
"hint": "Automatically apply effects. Targets must be selected before the action is made. Bypass users permissions."
|
||||
"hint": "Automatically apply effects. Targets must be selected before the action is made and Reaction Roll Automation must be different than Never. Bypass users permissions."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
|||
prepareBaseConfig(event) {
|
||||
const config = {
|
||||
event,
|
||||
title: `${this.item.name}: ${game.i18n.localize(this.name)}`,
|
||||
title: `${this.item instanceof CONFIG.Actor.documentClass ? "" : `${this.item.name}: `}${game.i18n.localize(this.name)}`,
|
||||
source: {
|
||||
item: this.item._id,
|
||||
action: this._id,
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel {
|
|||
}
|
||||
|
||||
registerTargetHook() {
|
||||
if (!this.parent.isAuthor) return;
|
||||
if (!this.parent.isAuthor || !this.hasTarget) return;
|
||||
if (this.targetMode && this.parent.targetHook !== null) {
|
||||
Hooks.off('targetToken', this.parent.targetHook);
|
||||
return (this.parent.targetHook = null);
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ export default class CostField extends fields.ArrayField {
|
|||
c.key === 'fear'
|
||||
? game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear)
|
||||
: resources[c.key].isReversed
|
||||
? resources[c.key].max
|
||||
? resources[c.key].max - resources[c.key].value
|
||||
: resources[c.key].value;
|
||||
if (c.scalable) c.maxStep = Math.floor((c.max - c.value) / c.step);
|
||||
return c;
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ export default class DamageField extends fields.SchemaField {
|
|||
const damageResult = await CONFIG.Dice.daggerheart.DamageRoll.build(damageConfig);
|
||||
if(!damageResult) return false;
|
||||
config.damage = damageResult.damage;
|
||||
config.message ??= damageConfig.message;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,7 +72,7 @@ export default class DamageField extends fields.SchemaField {
|
|||
* @param {boolean} force If the method should be executed outside of Action workflow, for ChatMessage button for example.
|
||||
*/
|
||||
static async applyDamage(config, targets = null, force = false) {
|
||||
targets ??= config.targets;
|
||||
targets ??= config.targets.filter(target => target.hit);
|
||||
if(!config.damage || !targets?.length || (!DamageField.getApplyAutomation() && !force)) return;
|
||||
for (let target of targets) {
|
||||
const actor = fromUuidSync(target.actorId);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { emitAsGM, GMUpdateEvent } from "../../../systemRegistration/socket.mjs";
|
||||
|
||||
const fields = foundry.data.fields;
|
||||
|
||||
export default class EffectsField extends fields.ArrayField {
|
||||
|
|
@ -31,8 +33,14 @@ export default class EffectsField extends fields.ArrayField {
|
|||
message = config.message = await CONFIG.Dice.daggerheart.DHRoll.toMessage(roll, config);
|
||||
}
|
||||
if(EffectsField.getAutomation() || force) {
|
||||
targets ??= config.targets.filter(t => !config.hasRoll || t.hit);
|
||||
EffectsField.applyEffects.call(this, config.targets.filter(t => !config.hasRoll || t.hit));
|
||||
targets ??= (message.system?.targets ?? config.targets).filter(t => !config.hasRoll || t.hit);
|
||||
await emitAsGM(
|
||||
GMUpdateEvent.UpdateEffect,
|
||||
EffectsField.applyEffects.bind(this),
|
||||
targets,
|
||||
this.uuid
|
||||
);
|
||||
// EffectsField.applyEffects.call(this, config.targets.filter(t => !config.hasRoll || t.hit));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,29 +71,6 @@ export class DHActionRollData extends foundry.abstract.DataModel {
|
|||
const modifiers = [];
|
||||
if (!this.parent?.actor) return modifiers;
|
||||
switch (this.parent.actor.type) {
|
||||
case 'character':
|
||||
// const spellcastingTrait =
|
||||
// this.type === 'spellcast'
|
||||
// ? (this.parent.actor?.system?.spellcastModifierTrait?.key ?? 'agility')
|
||||
// : null;
|
||||
// const trait =
|
||||
// this.useDefault || !this.trait
|
||||
// ? (spellcastingTrait ?? this.parent.item.system.attack?.roll?.trait ?? 'agility')
|
||||
// : this.trait;
|
||||
// if (
|
||||
// this.type === CONFIG.DH.GENERAL.rollTypes.attack.id ||
|
||||
// this.type === CONFIG.DH.GENERAL.rollTypes.trait.id
|
||||
// )
|
||||
// modifiers.push({
|
||||
// label: `DAGGERHEART.CONFIG.Traits.${trait}.name`,
|
||||
// value: this.parent.actor.system.traits[trait].value
|
||||
// });
|
||||
// else if (this.type === CONFIG.DH.GENERAL.rollTypes.spellcast.id)
|
||||
// modifiers.push({
|
||||
// label: `DAGGERHEART.CONFIG.RollTypes.spellcast.name`,
|
||||
// value: this.parent.actor.system.spellcastModifier
|
||||
// });
|
||||
break;
|
||||
case 'companion':
|
||||
case 'adversary':
|
||||
if (this.type === CONFIG.DH.GENERAL.rollTypes.attack.id)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ export default class SaveField extends fields.SchemaField {
|
|||
static async execute(config, targets = null, force = false) {
|
||||
if(!config.hasSave) return;
|
||||
let message = config.message ?? ui.chat.collection.get(config.parent?._id);
|
||||
|
||||
if(!message) {
|
||||
const roll = new CONFIG.Dice.daggerheart.DHRoll('');
|
||||
roll._evaluated = true;
|
||||
|
|
@ -42,8 +43,8 @@ export default class SaveField extends fields.SchemaField {
|
|||
}
|
||||
if(SaveField.getAutomation() !== CONFIG.DH.SETTINGS.actionAutomationChoices.never.id || force) {
|
||||
targets ??= config.targets.filter(t => !config.hasRoll || t.hit);
|
||||
SaveField.rollAllSave.call(this, targets, config.event, message);
|
||||
}
|
||||
await SaveField.rollAllSave.call(this, targets, config.event, message);
|
||||
} else return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -54,12 +55,16 @@ export default class SaveField extends fields.SchemaField {
|
|||
* @param {ChatMessage} message The ChatMessage the triggered button comes from.
|
||||
*/
|
||||
static async rollAllSave(targets, event, message) {
|
||||
if(!targets || !game.user.isGM) return;
|
||||
if(!targets) return;
|
||||
return new Promise(resolve => {
|
||||
const aPromise = [];
|
||||
targets.forEach(target => {
|
||||
aPromise.push(
|
||||
new Promise(async subResolve => {
|
||||
const actor = fromUuidSync(target.actorId);
|
||||
if(actor) {
|
||||
const rollSave = game.user === actor.owner ?
|
||||
SaveField.rollSave.call(this, actor, event, message)
|
||||
SaveField.rollSave.call(this, actor, event)
|
||||
: actor.owner
|
||||
.query('reactionRoll', {
|
||||
actionId: this.uuid,
|
||||
|
|
@ -67,9 +72,15 @@ export default class SaveField extends fields.SchemaField {
|
|||
event,
|
||||
message
|
||||
});
|
||||
rollSave.then(result => SaveField.updateSaveMessage.call(this, result, message, target.id));
|
||||
}
|
||||
const result = await rollSave;
|
||||
await SaveField.updateSaveMessage.call(this, result, message, target.id);
|
||||
subResolve();
|
||||
} else subResolve();
|
||||
})
|
||||
)
|
||||
});
|
||||
Promise.all(aPromise).then(result => resolve());
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -92,13 +103,13 @@ export default class SaveField extends fields.SchemaField {
|
|||
roll: {
|
||||
trait: this.save.trait,
|
||||
difficulty: this.save.difficulty ?? this.actor?.baseSaveDifficulty,
|
||||
type: 'reaction'
|
||||
type: 'trait'
|
||||
},
|
||||
type: 'trait',
|
||||
actionType: 'reaction',
|
||||
hasRoll: true,
|
||||
data: actor.getRollData()
|
||||
};
|
||||
if(SaveField.getAutomation() == CONFIG.DH.SETTINGS.actionAutomationChoices.always.id) rollConfig.dialog = { configure: false };
|
||||
if(SaveField.getAutomation() === CONFIG.DH.SETTINGS.actionAutomationChoices.always.id) rollConfig.dialog = { configure: false };
|
||||
return actor.diceRoll(rollConfig);
|
||||
}
|
||||
|
||||
|
|
@ -108,10 +119,10 @@ export default class SaveField extends fields.SchemaField {
|
|||
* @param {object} message ChatMessage to update
|
||||
* @param {string} targetId Token ID
|
||||
*/
|
||||
static updateSaveMessage(result, message, targetId) {
|
||||
static async updateSaveMessage(result, message, targetId) {
|
||||
if (!result) return;
|
||||
const updateMsg = function(message, targetId, result) {
|
||||
setTimeout(async () => {
|
||||
const updateMsg = async function(message, targetId, result) {
|
||||
// setTimeout(async () => {
|
||||
const chatMessage = ui.chat.collection.get(message._id),
|
||||
changes = {
|
||||
flags: {
|
||||
|
|
@ -127,11 +138,11 @@ export default class SaveField extends fields.SchemaField {
|
|||
}
|
||||
};
|
||||
await chatMessage.update(changes);
|
||||
}, 100);
|
||||
// }, 100);
|
||||
};
|
||||
if (game.modules.get('dice-so-nice')?.active)
|
||||
game.dice3d.waitFor3DAnimationByMessageID(result.message.id ?? result.message._id).then(() => updateMsg(message, targetId, result));
|
||||
else updateMsg(message, targetId, result);
|
||||
game.dice3d.waitFor3DAnimationByMessageID(result.message.id ?? result.message._id).then(async () => await updateMsg(message, targetId, result));
|
||||
else await updateMsg(message, targetId, result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ export default class DHRoll extends Roll {
|
|||
static async buildConfigure(config = {}, message = {}) {
|
||||
config.hooks = [...this.getHooks(), ''];
|
||||
config.dialog ??= {};
|
||||
|
||||
for (const hook of config.hooks) {
|
||||
if (Hooks.call(`${CONFIG.DH.id}.preRoll${hook.capitalize()}`, config, message) === false) return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ export default class DualityRoll extends D20Roll {
|
|||
applyBaseBonus() {
|
||||
const modifiers = super.applyBaseBonus();
|
||||
|
||||
if (this.options.roll.trait && this.data.traits[this.options.roll.trait])
|
||||
if (this.options.roll.trait && this.data.traits?.[this.options.roll.trait])
|
||||
modifiers.unshift({
|
||||
label: this.options.roll.type === CONFIG.DH.GENERAL.rollTypes.spellcast.id ? "DAGGERHEART.CONFIG.RollTypes.spellcast.name" : `DAGGERHEART.CONFIG.Traits.${this.options.roll.trait}.name`,
|
||||
value: this.data.traits[this.options.roll.trait].value
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export default class DhpActor extends Actor {
|
|||
get owner() {
|
||||
const user =
|
||||
this.hasPlayerOwner && game.users.players.find(u => this.testUserPermission(u, 'OWNER') && u.active);
|
||||
if (!user) return game.user.isGM ? game.user : null;
|
||||
if (!user) return game.users.activeGM;
|
||||
return user;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,12 +147,16 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
|||
|
||||
async onRollDamage(event) {
|
||||
event.stopPropagation();
|
||||
this.system.action?.workflow.get("damage")?.execute(this.system, this._id, true);
|
||||
const config = foundry.utils.deepClone(this.system);
|
||||
config.event = event;
|
||||
this.system.action?.workflow.get("damage")?.execute(config, this._id, true);
|
||||
}
|
||||
|
||||
async onApplyDamage(event) {
|
||||
event.stopPropagation();
|
||||
const targets = this.filterPermTargets(this.system.hitTargets);
|
||||
const targets = this.filterPermTargets(this.system.hitTargets),
|
||||
config = foundry.utils.deepClone(this.system);
|
||||
config.event = event;
|
||||
|
||||
if (this.system.onSave) {
|
||||
const pendingingSaves = targets.filter(t => t.saved.success === null);
|
||||
|
|
@ -169,7 +173,7 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
|||
return ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelectedOrPerm'));
|
||||
|
||||
this.consumeOnSuccess();
|
||||
this.system.action?.workflow.get("applyDamage")?.execute(this.system, targets, true);
|
||||
this.system.action?.workflow.get("applyDamage")?.execute(config, targets, true);
|
||||
}
|
||||
|
||||
async onRollSave(event) {
|
||||
|
|
@ -198,17 +202,21 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
|
|||
async onRollAllSave(event) {
|
||||
event.stopPropagation();
|
||||
if (!game.user.isGM) return;
|
||||
const targets = this.system.hitTargets;
|
||||
this.system.action?.workflow.get("save")?.execute(this.system, targets, true);
|
||||
const targets = this.system.hitTargets,
|
||||
config = foundry.utils.deepClone(this.system);
|
||||
config.event = event;
|
||||
this.system.action?.workflow.get("save")?.execute(config, targets, true);
|
||||
}
|
||||
|
||||
async onApplyEffect(event) {
|
||||
event.stopPropagation();
|
||||
const targets = this.filterPermTargets(this.system.hitTargets);
|
||||
const targets = this.filterPermTargets(this.system.hitTargets),
|
||||
config = foundry.utils.deepClone(this.system);
|
||||
config.event = event;
|
||||
if (targets.length === 0)
|
||||
ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelectedOrPerm'));
|
||||
this.consumeOnSuccess();
|
||||
this.system.action?.workflow.get("effects")?.execute(this.system, targets, true);
|
||||
this.system.action?.workflow.get("effects")?.execute(config, targets, true);
|
||||
}
|
||||
|
||||
filterPermTargets(targets) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export const socketEvent = {
|
|||
|
||||
export const GMUpdateEvent = {
|
||||
UpdateDocument: 'DhGMUpdateDocument',
|
||||
UpdateEffect: 'DhGMUpdateEffect',
|
||||
UpdateSetting: 'DhGMUpdateSetting',
|
||||
UpdateFear: 'DhGMUpdateFear',
|
||||
UpdateSaveMessage: 'DhGMUpdateSaveMessage'
|
||||
|
|
@ -37,9 +38,12 @@ export const registerSocketHooks = () => {
|
|||
const document = data.uuid ? await fromUuid(data.uuid) : null;
|
||||
switch (data.action) {
|
||||
case GMUpdateEvent.UpdateDocument:
|
||||
if (document && data.update) {
|
||||
if (document && data.update)
|
||||
await document.update(data.update);
|
||||
}
|
||||
break;
|
||||
case GMUpdateEvent.UpdateEffect:
|
||||
if (document && data.update)
|
||||
await game.system.api.fields.ActionFields.EffectsField.applyEffects.call(document, data.update);
|
||||
break;
|
||||
case GMUpdateEvent.UpdateSetting:
|
||||
await game.settings.set(CONFIG.DH.id, data.uuid, data.update);
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@
|
|||
<div class="nest-inputs">
|
||||
<input type="hidden" name="{{../path}}damage.parts.{{realIndex}}.valueAlt.multiplier" value="flat">
|
||||
{{formField ../fields.valueAlt.fields.flatMultiplier value=dmg.valueAlt.flatMultiplier name=(concat ../path "damage.parts." realIndex ".valueAlt.flatMultiplier") label="DAGGERHEART.ACTIONS.Settings.multiplier" classes="inline-child" localize=true }}
|
||||
{{formField ../fields.valueAlt.fields.dice value=dmg.valueAlt.dice name=(concat ../path "damage.parts." realIndex ".valueAlt.dice") classes="inline-child"}}
|
||||
{{formField ../fields.valueAlt.fields.dice value=dmg.valueAlt.dice name=(concat ../path "damage.parts." realIndex ".valueAlt.dice") classes="inline-child" localize=true}}
|
||||
{{formField ../fields.valueAlt.fields.bonus value=dmg.valueAlt.bonus name=(concat ../path "damage.parts." realIndex ".valueAlt.bonus") localize=true classes="inline-child"}}
|
||||
</div>
|
||||
</fieldset>
|
||||
|
|
@ -70,7 +70,7 @@
|
|||
|
||||
{{#*inline "formula"}}
|
||||
{{#unless dmg.base}}
|
||||
{{formField fields.custom.fields.enabled value=source.custom.enabled name=(concat path "damage.parts." realIndex "." target ".custom.enabled") classes="checkbox"}}
|
||||
{{formField fields.custom.fields.enabled value=source.custom.enabled name=(concat path "damage.parts." realIndex "." target ".custom.enabled") classes="checkbox" localize=true}}
|
||||
{{/unless}}
|
||||
{{#if source.custom.enabled}}
|
||||
{{formField fields.custom.fields.formula value=source.custom.formula name=(concat path "damage.parts." realIndex "." target ".custom.formula") localize=true}}
|
||||
|
|
@ -79,8 +79,8 @@
|
|||
{{#unless @root.isNPC}}
|
||||
{{formField fields.multiplier value=source.multiplier name=(concat path "damage.parts." realIndex "." target ".multiplier") localize=true}}
|
||||
{{/unless}}
|
||||
{{#if (eq source.multiplier 'flat')}}{{formField fields.flatMultiplier value=source.flatMultiplier name=(concat path "damage.parts." realIndex "." target ".flatMultiplier") }}{{/if}}
|
||||
{{formField fields.dice value=source.dice name=(concat path "damage.parts." realIndex "." target ".dice")}}
|
||||
{{#if (eq source.multiplier 'flat')}}{{formField fields.flatMultiplier value=source.flatMultiplier name=(concat path "damage.parts." realIndex "." target ".flatMultiplier") localize=true }}{{/if}}
|
||||
{{formField fields.dice value=source.dice name=(concat path "damage.parts." realIndex "." target ".dice") localize=true}}
|
||||
{{formField fields.bonus value=source.bonus name=(concat path "damage.parts." realIndex "." target ".bonus") localize=true}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
|
|||
|
|
@ -126,10 +126,12 @@
|
|||
{{selectOptions diceOptions selected=@root.roll.dAdvantage.denomination}}
|
||||
</select>
|
||||
</div>
|
||||
{{#if abilities}}
|
||||
<span>{{localize "DAGGERHEART.GENERAL.traitModifier"}}</span>
|
||||
<select name="trait">
|
||||
{{selectOptions abilities selected=@root.rollConfig.roll.trait valueAttr="id" labelAttr="label" localize=true}}
|
||||
</select>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{#if @root.rallyDie.length}}
|
||||
<span class="formula-label">{{localize "DAGGERHEART.CLASS.Feature.rallyDice"}}</span>
|
||||
|
|
|
|||
|
|
@ -13,10 +13,10 @@
|
|||
{{#each damage as | roll index | }}
|
||||
<fieldset>
|
||||
<legend>
|
||||
{{localize (concat 'DAGGERHEART.CONFIG.HealingType.' index '.inChatRoll')}} <div class="roll-formula">{{localize "DAGGERHEART.GENERAL.total"}}: {{roll.total}}</div>{{#if (and (eq index "hitPoints")../isDirect)}} <div class="roll-formula">{{localize "DAGGERHEART.CONFIG.DamageType.direct.short"}}</div>{{/if}}
|
||||
{{#if ../hasHealing}}{{localize (concat 'DAGGERHEART.CONFIG.HealingType.' index '.name')}}{{else}}{{localize (concat 'DAGGERHEART.CONFIG.HealingType.' index '.inChatRoll')}}{{/if}} <div class="roll-formula">{{localize "DAGGERHEART.GENERAL.total"}}: {{roll.total}}</div>{{#if (and (eq index "hitPoints") ../isDirect)}} <div class="roll-formula">{{localize "DAGGERHEART.CONFIG.DamageType.direct.short"}}</div>{{/if}}
|
||||
</legend>
|
||||
{{#each roll.parts}}
|
||||
{{#if damageTypes.length}}
|
||||
{{#if (and (not @root.hasHealing) damageTypes.length)}}
|
||||
<label class="roll-part-header"><span>
|
||||
{{#each damageTypes}}
|
||||
{{localize (concat 'DAGGERHEART.CONFIG.ArmorFeature.' this '.name')}}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if (and ../hasSave (or hit (not @root.hasRoll)))}}
|
||||
{{#if (and ../hasSave (or hit (not @root.hasRoll) (not @root.targetMode)))}}
|
||||
<div class="target-save{{#if saved.result includeZero=true}} is-rolled{{/if}}" data-perm-id="{{actorId}}">
|
||||
<i class="fa-solid {{#if saved.result includeZero=true}}{{#if saved.success}}fa-check{{else}}fa-xmark{{/if}}{{else}}fa-shield{{/if}} fa-lg"></i>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue