diff --git a/module/applications/dialogs/damageDialog.mjs b/module/applications/dialogs/damageDialog.mjs index 21b2c0ad..0d98ce24 100644 --- a/module/applications/dialogs/damageDialog.mjs +++ b/module/applications/dialogs/damageDialog.mjs @@ -6,6 +6,7 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application this.roll = roll; this.config = config; + this.originalIsCritical = config.isCritical; this.selectedEffects = this.config.bonusEffects; } @@ -122,6 +123,16 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application static async submitRoll() { const { damageFormula, resourceFormulas } = this.roll.constructFormulas({ ...this.config, isCritical: false }); + /* Sideeffect occuring in constructFormulas that sets this.config.isCritical to the false value. Can remove the below if it can be prevented */ + this.config.isCritical = this.originalIsCritical; + + /* If a critical has been forced in the Dialog, save that forced state to the damage roll */ + if (this.config.isCritical && !this.originalIsCritical) { + damageFormula.roll.options.isCritical = true; + for (const formula of resourceFormulas) + formula.roll.options.isCritical = true; + } + this.config.damageFormula = damageFormula; this.config.resourceFormulas = resourceFormulas; await this.close({ submitted: true }); diff --git a/module/applications/dialogs/tagTeamDialog.mjs b/module/applications/dialogs/tagTeamDialog.mjs index 5779bd00..e0517abe 100644 --- a/module/applications/dialogs/tagTeamDialog.mjs +++ b/module/applications/dialogs/tagTeamDialog.mjs @@ -1,6 +1,7 @@ import { ResourceUpdateMap } from '../../data/action/baseAction.mjs'; import { ChatDamageData } from '../../data/chat-message/chatDamageData.mjs'; import { MemberData } from '../../data/tagTeamData.mjs'; +import DamageRoll from '../../dice/damageRoll.mjs'; import { getCritDamageBonus, shouldUseHopeFearAutomation } from '../../helpers/utils.mjs'; import { emitGMUpdate, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs'; import PartySheet from '../sheets/actors/party.mjs'; @@ -237,6 +238,10 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio const selectedRoll = Object.values(this.party.system.tagTeam.members).find(member => member.selected); const critSelected = !selectedRoll ? undefined : (selectedRoll?.roll?.isCritical ?? false); + const isCritical = critSelected || (critSelected === undefined && data.roll?.isCritical); + if (data.damageRollData.main) { + data.damageRollData.main.options.isCritical = isCritical; + } return { ...data, @@ -248,8 +253,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio rollOptions, damageRollOptions, damage: data.damageRollData, - critDamage: this.getCriticalDamage(data.damageRollData), - useCritDamage: critSelected || (critSelected === undefined && data.roll?.isCritical) + isCritical }; } @@ -640,17 +644,13 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio secondaryRoll.damageRollData = baseSecondaryRoll.damageRollData ? ChatDamageData.fromJSON(JSON.stringify(baseSecondaryRoll.damageRollData)) : null; - const isCritical = overrideIsCritical ?? mainRoll.roll.isCritical; - if (isCritical) mainRoll.damageRollData = this.getCriticalDamage(mainRoll.damageRollData); - if (secondaryRoll.damageRollData) { - const secondaryDamage = (displayVersion ? overrideIsCritical : isCritical) - ? this.getCriticalDamage(secondaryRoll.damageRollData) - : secondaryRoll.damageRollData; + const secondaryDamage = secondaryRoll.damageRollData; + if (mainRoll.damageRollData) { if (secondaryDamage.main) { if (mainRoll.damageRollData.main) { - mainRoll.damageRollData.main = Roll.fromTerms([ + mainRoll.damageRollData.main = DamageRoll.fromTerms([ ...baseMainRoll.damageRollData.main.terms, new foundry.dice.terms.OperatorTerm({ operator: '+' }), ...baseSecondaryRoll.damageRollData.main.terms @@ -672,7 +672,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio for (const [key, damage] of Object.entries(secondaryDamage.resources ?? {})) { if (key in mainRoll.damageRollData.resources) { - mainRoll.damageRollData.resources[key] = Roll.fromTerms([ + mainRoll.damageRollData.resources[key] = DamageRoll.fromTerms([ ...baseMainRoll.damageRollData.resources[key].terms, new foundry.dice.terms.OperatorTerm({ operator: '+' }), ...baseSecondaryRoll.damageRollData.resources[key].terms @@ -696,6 +696,12 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio } } + if (mainRoll.damageRollData.main) { + const isCritical = overrideIsCritical ?? mainRoll.roll.isCritical; + mainRoll.damageRollData.main.options.isCritical = isCritical; + } + + return mainRoll; } catch (err) { console.error(err); @@ -755,7 +761,11 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio }; if (joinedRoll.damageRollData.main) { - systemData.damage.main = joinedRoll.damageRollData.toJSON(); + systemData.damage.main = joinedRoll.damageRollData.main.toJSON(); + // isCritical is used internally in TagTeamDialog to force-flip damage from normal to critical and vice versa. + // It's deleted here to avoid interupting normal critical damage logic in the chatMessage. + // If someone explicitly set their own damage roll to be a forced critical, then I think it's fine that isn't transmitted to the final joined roll. + delete systemData.damage.main.options.isCritical; } for (const type of Object.keys(joinedRoll.damageRollData?.resources ?? {})) { systemData.damage.resources[type] = joinedRoll.damageRollData.resources[type].toJSON(); diff --git a/module/data/chat-message/chatDamageData.mjs b/module/data/chat-message/chatDamageData.mjs index 404cda43..da28061f 100644 --- a/module/data/chat-message/chatDamageData.mjs +++ b/module/data/chat-message/chatDamageData.mjs @@ -1,4 +1,6 @@ import { triggerChatRollFx } from '../../helpers/utils.mjs'; +import { MemberData } from '../tagTeamData.mjs'; +import DHActorRoll from './actorRoll.mjs'; export class ChatDamageData extends foundry.abstract.DataModel { constructor(data = {}, options = {}) { @@ -7,6 +9,17 @@ export class ChatDamageData extends foundry.abstract.DataModel { this._prepareRolls(); } + get isCritical() { + if (this.parent && this.parent instanceof MemberData) { + return this.parent.roll.isCritical; + } + if (this.parent && this.parent instanceof DHActorRoll && this.parent.parent) { + return Roll.fromJSON(this.parent.parent._source.rolls[0]).isCritical; + } + + return false; + } + static defineSchema() { const fields = foundry.data.fields; @@ -28,7 +41,15 @@ export class ChatDamageData extends foundry.abstract.DataModel { } _prepareRolls() { - this.main &&= Roll.fromData(this.main); + this.main &&= Roll.fromData({ + ...this.main, + options: { + ...this.main.options, + isCritical: + this.main.options.isCritical === false ? false : (this.main.options.isCritical || this.isCritical) + } + }); + for (const key of Object.keys(this.resources)) { this.resources[key] = Roll.fromData(this.resources[key]); } diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index 25b3ba97..05d9f664 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -107,7 +107,7 @@ export default class DamageField extends fields.SchemaField { if (configDamage.main) { const multiplier = config.actionActor?.system.rules?.attack?.damage?.hpDamageMultiplier ?? 1; const takenMultiplier = actor.system.rules?.attack?.damage?.hpDamageTakenMultiplier; - configDamage.main.total = Math.ceil(configDamage.main.total * multiplier * takenMultiplier); + configDamage.main.total = Math.ceil(config.damage.main.total * multiplier * takenMultiplier); } damagePromises.push( diff --git a/module/dice/damageRoll.mjs b/module/dice/damageRoll.mjs index 2ca04a06..722b05f6 100644 --- a/module/dice/damageRoll.mjs +++ b/module/dice/damageRoll.mjs @@ -8,7 +8,7 @@ export default class DamageRoll extends DHRoll { } get isCritical() { - return true; + return this.options.isCritical; } get modifierTotal() { @@ -16,6 +16,11 @@ export default class DamageRoll extends DHRoll { return super.modifierTotal + criticalDamageBonus; } + get total() { + const criticalDamageBonus = this.isCritical ? getCritDamageBonus(this.terms) : 0; + return super.total + criticalDamageBonus; + } + static DefaultDialog = DamageDialog; static createRollInstance(config) { @@ -28,7 +33,7 @@ export default class DamageRoll extends DHRoll { const evaluateRoll = async roll => { await roll.roll.evaluate(); - roll.roll.options = { damageTypes: roll.damageTypes ? [...roll.damageTypes] : [] }; + roll.roll.options = { ...roll.roll.options, damageTypes: roll.damageTypes ? [...roll.damageTypes] : [] }; return roll.roll; } @@ -36,8 +41,10 @@ export default class DamageRoll extends DHRoll { if (config.damageFormula) { config.damage.main = await evaluateRoll(config.damageFormula); - config.damage.main.options = { damageTypes: - config.damageFormula.damageTypes ? [...config.damageFormula.damageTypes] : [] + config.damage.main.options = { + ...config.damage.main.options, + damageTypes: + config.damageFormula.damageTypes ? [...config.damageFormula.damageTypes] : [] }; } diff --git a/styles/less/dialog/tag-team-dialog/sheet.less b/styles/less/dialog/tag-team-dialog/sheet.less index 82bc0270..3a6778d8 100644 --- a/styles/less/dialog/tag-team-dialog/sheet.less +++ b/styles/less/dialog/tag-team-dialog/sheet.less @@ -252,11 +252,8 @@ width: 100%; text-align: center; - .result-info { - display: flex; - gap: 4px; - align-items: center; - justify-content: center; + .damage-info { + text-decoration: underline; } } } diff --git a/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs b/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs index e8bec150..4727d7e8 100644 --- a/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs +++ b/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs @@ -1,5 +1,5 @@ {{#if damage.main}} - {{> damage roll=damage.main label=(localize "DAGGERHEART.GENERAL.damage") memberKey=key}} + {{> damage roll=damage.main label=(localize "DAGGERHEART.GENERAL.damage") memberKey=key isCritical=isCritical}} {{/if}} {{#each damage.resources as |roll key|}} diff --git a/templates/dialogs/tagTeamDialog/result.hbs b/templates/dialogs/tagTeamDialog/result.hbs index 88f579a6..4351823e 100644 --- a/templates/dialogs/tagTeamDialog/result.hbs +++ b/templates/dialogs/tagTeamDialog/result.hbs @@ -6,23 +6,14 @@ {{#if hintText}}