diff --git a/daggerheart.mjs b/daggerheart.mjs index 31c9f63d..4641c34a 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -24,7 +24,7 @@ import TokenManager from './module/documents/tokenManager.mjs'; CONFIG.DH = SYSTEM; CONFIG.TextEditor.enrichers.push(...enricherConfig); -CONFIG.Dice.rolls = [BaseRoll, DHRoll, DualityRoll, D20Roll, DamageRoll, FateRoll]; +CONFIG.Dice.rolls = [Roll = BaseRoll, DHRoll, DualityRoll, D20Roll, DamageRoll, FateRoll]; CONFIG.Dice.daggerheart = { DHRoll: DHRoll, DualityRoll: DualityRoll, diff --git a/module/applications/dialogs/tagTeamDialog.mjs b/module/applications/dialogs/tagTeamDialog.mjs index 2b865304..c54720f4 100644 --- a/module/applications/dialogs/tagTeamDialog.mjs +++ b/module/applications/dialogs/tagTeamDialog.mjs @@ -141,7 +141,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio const hasRolled = Boolean(data.rollData); if (!hasRolled) return false; - return !data.rollData.options.hasDamage || Boolean(data.rollData.options.damage); + return !data.rollData.options.hasDamage || data.damageRollData.active; }); return context; @@ -182,7 +182,7 @@ 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?.rollData?.options?.roll?.isCritical ?? false); + : (selectedRoll?.roll?.isCritical ?? false); partContext.hintText = await this.getInfoTexts(this.party.system.tagTeam.members); partContext.joinedRoll = await this.getJoinedRoll({ @@ -236,7 +236,7 @@ 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?.rollData?.options?.roll?.isCritical ?? false); + const critSelected = !selectedRoll ? undefined : (selectedRoll?.roll?.isCritical ?? false); return { ...data, @@ -249,7 +249,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio damageRollOptions, damage: data.damageRollData, critDamage: await this.getCriticalDamage(data.damageRollData), - useCritDamage: critSelected || (critSelected === undefined && data.rollData?.options?.roll?.isCritical) + useCritDamage: critSelected || (critSelected === undefined && data.roll?.isCritical) }; } @@ -379,7 +379,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio let rollIsSelected = false; for (const member of Object.values(members)) { const rollFinished = Boolean(member.rollData); - const damageFinished = member.rollData?.options?.hasDamage ? Boolean(member.rollData.options.damage) : true; + const damageFinished = member.rollData?.options?.hasDamage ? member.damageRollData.active : true; rollsAreFinished = rollsAreFinished && rollFinished && damageFinished; rollIsSelected = rollIsSelected || member.selected; @@ -540,17 +540,10 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio await action.workflow.get('damage').execute(config, null, true); if (!config.damage) return; - - const current = this.party.system.tagTeam.members[memberKey].rollData; + await this.updatePartyData( { - [`system.tagTeam.members.${memberKey}.rollData`]: { - ...current, - options: { - ...current.options, - damage: config.damage - } - } + [`system.tagTeam.members.${memberKey}.damageRollData`]: config.damage }, this.getUpdatingParts(button) ); @@ -558,52 +551,25 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio static async #removeDamageRoll(_, button) { const { memberKey } = button.dataset; - const current = this.party.system.tagTeam.members[memberKey].rollData; this.updatePartyData( { - [`system.tagTeam.members.${memberKey}.rollData`]: { - ...current, - options: { - ...current.options, - damage: null - } - } + [`system.tagTeam.members.${memberKey}.damageRollData.types`]: + _replace({}) }, this.getUpdatingParts(button) ); } static async #rerollDamageDice(_, button) { - const { memberKey, damageKey, part, dice } = button.dataset; + const { memberKey, damageKey, diceIndex, resultIndex } = button.dataset; const memberData = this.party.system.tagTeam.members[memberKey]; - const partData = memberData.rollData.options.damage[damageKey].parts[part]; - const activeDiceResultKey = Object.keys(partData.dice[dice].results).find( - index => partData.dice[dice].results[index].active - ); - const { parsedRoll, rerolledDice } = await game.system.api.dice.DamageRoll.reroll( - partData, - dice, - activeDiceResultKey - ); - - const rollData = this.party.system.tagTeam.members[memberKey].rollData; - rollData.options.damage[damageKey].parts = rollData.options.damage[damageKey].parts.map((damagePart, index) => { - if (index !== Number.parseInt(part)) return damagePart; - - return { - ...damagePart, - total: parsedRoll.total, - dice: rerolledDice - }; - }); - rollData.options.damage[damageKey].total = rollData.options.damage[damageKey].parts.reduce((acc, part) => { - acc += part.total; - return acc; - }, 0); + await memberData.damageRollData.rerollDamageDie(damageKey, diceIndex, resultIndex); this.updatePartyData( { - [`system.tagTeam.members.${memberKey}.rollData`]: rollData + [`system.tagTeam.members.${memberKey}.damageRollData.types`]: { + [damageKey]: memberData.damageRollData.types[damageKey].toJSON() + } }, this.getUpdatingParts(button) ); @@ -622,6 +588,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio new foundry.dice.terms.OperatorTerm({ operator: '+' }), criticalTerm ]); + newDamage.types[key].options = foundry.utils.deepClone(origDamage.types[key].options); } return newDamage; @@ -629,6 +596,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio static async #selectRoll(_, button) { const { memberKey } = button.dataset; + this.updatePartyData( { [`system.tagTeam.members`]: Object.entries(this.party.system.tagTeam.members).reduce( @@ -639,7 +607,12 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio {} ) }, - this.getUpdatingParts(button) + /* Selecting a roll must update all member sections hbs to display the correct damage information incase of a critical */ + [ + ...Object.keys(this.party.system.tagTeam.members), + this.constructor.PARTS.rollSelection.id, + this.constructor.PARTS.result.id + ] ); } @@ -663,9 +636,8 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio secondaryRoll.damageRollData = baseSecondaryRoll.damageRollData ? ChatDamageData.fromJSON(JSON.stringify(baseSecondaryRoll.damageRollData)) : null; - const systemData = mainRoll.rollData.options; - const isCritical = overrideIsCritical ?? systemData.roll.isCritical; - if (isCritical) mainRoll.damageRollData = await this.getCriticalDamage(systemData.damageRollData); + const isCritical = overrideIsCritical ?? mainRoll.roll.isCritical; + if (isCritical) mainRoll.damageRollData = await this.getCriticalDamage(mainRoll.damageRollData); if (secondaryRoll.damageRollData) { const secondaryDamage = (displayVersion ? overrideIsCritical : isCritical) @@ -679,6 +651,16 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio new foundry.dice.terms.OperatorTerm({ operator: '+' }), ...baseSecondaryRoll.damageRollData.types[key].terms ]); + + /* Joining the roll.options of both rolls */ + const joinedDamageTypes = new Set([ + ...baseMainRoll.damageRollData.types[key].options.damageTypes, + ...baseSecondaryRoll.damageRollData.types[key].options.damageTypes + ]); + mainRoll.damageRollData.types[key].options = { + ...baseMainRoll.damageRollData.types[key].options, + damageTypes: [...joinedDamageTypes] + }; } else { mainRoll.damageRollData.types[key] = damage; } diff --git a/module/data/actor/party.mjs b/module/data/actor/party.mjs index b735c65a..5b9cccab 100644 --- a/module/data/actor/party.mjs +++ b/module/data/actor/party.mjs @@ -3,7 +3,6 @@ import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayFie import TagTeamData from '../tagTeamData.mjs'; import GroupRollData from '../groupRollData.mjs'; import { GoldField } from '../fields/actorField.mjs'; -import { ChatDamageData } from '../chat-message/chatDamageData.mjs'; export default class DhParty extends BaseDataActor { /** @inheritdoc */ @@ -49,14 +48,6 @@ export default class DhParty extends BaseDataActor { } } - prepareDerivedData() { - for (const memberKey in this.tagTeam.members) { - const member = this.tagTeam.members[memberKey]; - member.damageRollData = member.rollData?.options.damage ? - ChatDamageData.fromJSON(JSON.stringify(member.rollData.options.damage)) : null; - } - } - _onCreate(data, options, userId) { super._onCreate(data, options, userId); diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs index 6efa1f51..c4295e0d 100644 --- a/module/data/fields/action/damageField.mjs +++ b/module/data/fields/action/damageField.mjs @@ -118,9 +118,9 @@ export default class DamageField extends fields.SchemaField { const hpDamageMultiplier = config.actionActor?.system.rules?.attack?.damage?.hpDamageMultiplier ?? 1; const hpDamageTakenMultiplier = actor.system.rules?.attack?.damage?.hpDamageTakenMultiplier; if (configDamage.hitPoints) { - configDamage.hitPoints.roll = configDamage.hitPoints.roll.toJSON(); - configDamage.hitPoints.roll.total = Math.ceil( - configDamage.hitPoints.roll.total * hpDamageMultiplier * hpDamageTakenMultiplier + configDamage.hitPoints = configDamage.hitPoints.toJSON(); + configDamage.hitPoints.total = Math.ceil( + configDamage.hitPoints.total * hpDamageMultiplier * hpDamageTakenMultiplier ); } diff --git a/module/data/tagTeamData.mjs b/module/data/tagTeamData.mjs index 640c2f6c..ef6536f1 100644 --- a/module/data/tagTeamData.mjs +++ b/module/data/tagTeamData.mjs @@ -1,3 +1,5 @@ +import { ChatDamageData } from './chat-message/chatDamageData.mjs'; + export default class TagTeamData extends foundry.abstract.DataModel { static defineSchema() { const fields = foundry.data.fields; @@ -37,6 +39,7 @@ export class MemberData extends foundry.abstract.DataModel { }), rollChoice: new fields.StringField({ nullable: true, initial: null }), rollData: new fields.JSONField({ nullable: true, initial: null }), + damageRollData: new fields.EmbeddedDataField(ChatDamageData), selected: new fields.BooleanField({ initial: false }) }; } diff --git a/module/dice/baseRoll.mjs b/module/dice/baseRoll.mjs index 4d065fff..2c42d38a 100644 --- a/module/dice/baseRoll.mjs +++ b/module/dice/baseRoll.mjs @@ -4,4 +4,8 @@ export default class BaseRoll extends Roll { /** @inheritdoc */ static TOOLTIP_TEMPLATE = 'systems/daggerheart/templates/ui/chat/foundryRollTooltip.hbs'; + + get modifierTotal() { + return this.total - this.dice.reduce((acc, dice) => acc + dice.total, 0); + } } diff --git a/module/dice/damageRoll.mjs b/module/dice/damageRoll.mjs index 56712337..8667d89f 100644 --- a/module/dice/damageRoll.mjs +++ b/module/dice/damageRoll.mjs @@ -19,7 +19,7 @@ export default class DamageRoll extends DHRoll { for (const roll of config.roll) { await roll.roll.evaluate(); - roll.roll.options = { damageTypes: roll.damageTypes ?? [] }; + roll.roll.options = { damageTypes: roll.damageTypes ? [...roll.damageTypes] : [] }; if (!config.damage?.types) config.damage = { types: {} }; config.damage.types[roll.applyTo] = roll.roll; @@ -37,7 +37,7 @@ export default class DamageRoll extends DHRoll { if (game.modules.get('dice-so-nice')?.active) { config.mute = true; const pool = foundry.dice.terms.PoolTerm.fromRolls( - Object.values(config.damage.types).map(x => x.roll) + Object.values(config.damage.types) ); diceRolls.push(Roll.fromTerms([pool])); } diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index b85c13d5..d7733dd5 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -660,12 +660,12 @@ export default class DhpActor extends Actor { Object.entries(damages).forEach(([key, damage]) => { if (key === CONFIG.DH.GENERAL.healingTypes.hitPoints.id) - damage.roll.total = this.calculateDamage(damage.roll.total, damage.damageTypes); + damage.total = this.calculateDamage(damage.total, damage.damageTypes); const update = updates.find(u => u.key === key); if (update) { - update.value += damage.roll.total; + update.value += damage.total; update.damageTypes.add(...new Set(damage.damageTypes)); - } else updates.push({ value: damage.roll.total, key, damageTypes: new Set(damage.damageTypes) }); + } else updates.push({ value: damage.total, key, damageTypes: new Set(damage.damageTypes) }); }); if (Hooks.call(`${CONFIG.DH.id}.postCalculateDamage`, this, damages) === false) return null; diff --git a/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs b/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs index 5f37c6d1..3f7f457b 100644 --- a/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs +++ b/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs @@ -2,15 +2,19 @@