mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-07-25 11:59:54 +02:00
[Fix] 2094 - Critical Damage (#2096)
Some checks failed
Project CI / build (24.x) (push) Has been cancelled
Some checks failed
Project CI / build (24.x) (push) Has been cancelled
This commit is contained in:
parent
66ddb5c032
commit
7fd2a7f17e
12 changed files with 109 additions and 78 deletions
|
|
@ -6,6 +6,11 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application
|
|||
|
||||
this.roll = roll;
|
||||
this.config = config;
|
||||
|
||||
/** The original isCritical state before any alterations in the dialog.
|
||||
* Used for checking if the state has been altered
|
||||
*/
|
||||
this.originalIsCritical = config.isCritical;
|
||||
this.selectedEffects = this.config.bonusEffects;
|
||||
}
|
||||
|
||||
|
|
@ -121,6 +126,22 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application
|
|||
}
|
||||
|
||||
static async submitRoll() {
|
||||
/* Sideeffect occuring in constructFormulas that sets this.config.isCritical to the false value. Can remove the below if it can be prevented */
|
||||
const sideEffectSafeIsCritical = this.config.isCritical;
|
||||
const { damageFormula, resourceFormulas } = this.roll.constructFormulas({ ...this.config, isCritical: false });
|
||||
|
||||
this.config.isCritical = sideEffectSafeIsCritical;
|
||||
|
||||
/* If the isCritical state has been altered in the dialog, we update the roll options */
|
||||
if (this.config.isCritical !== this.originalIsCritical) {
|
||||
damageFormula.roll.options.isCritical = this.config.isCritical;
|
||||
|
||||
for (const formula of resourceFormulas)
|
||||
formula.roll.optionsisCritical = this.config.isCritical;
|
||||
}
|
||||
|
||||
this.config.damageFormula = damageFormula;
|
||||
this.config.resourceFormulas = resourceFormulas;
|
||||
await this.close({ submitted: true });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { ResourceUpdateMap } from '../../data/action/baseAction.mjs';
|
||||
import { ChatDamageData } from '../../data/chat-message/chatDamageData.mjs';
|
||||
import { MemberData } from '../../data/tagTeamData.mjs';
|
||||
import { getCritDamageBonus, shouldUseHopeFearAutomation } from '../../helpers/utils.mjs';
|
||||
import DamageRoll from '../../dice/damageRoll.mjs';
|
||||
import { shouldUseHopeFearAutomation } from '../../helpers/utils.mjs';
|
||||
import { emitGMUpdate, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs';
|
||||
import PartySheet from '../sheets/actors/party.mjs';
|
||||
|
||||
|
|
@ -184,8 +185,8 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
? undefined
|
||||
: (selectedRoll?.roll?.isCritical ?? false);
|
||||
|
||||
partContext.hintText = await this.getInfoTexts(this.party.system.tagTeam.members);
|
||||
partContext.joinedRoll = await this.getJoinedRoll({
|
||||
partContext.hintText = this.getInfoTexts(this.party.system.tagTeam.members);
|
||||
partContext.joinedRoll = this.getJoinedRoll({
|
||||
overrideIsCritical: critSelected,
|
||||
displayVersion: true
|
||||
});
|
||||
|
|
@ -194,7 +195,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
}
|
||||
|
||||
if (Object.keys(this.party.system.tagTeam.members).includes(partId)) {
|
||||
const data = await this.#prepareMemberContext(partId);
|
||||
const data = this.#prepareMemberContext(partId);
|
||||
partContext.hasDamage |= Boolean(data?.damage);
|
||||
partContext.members[partId] = data;
|
||||
}
|
||||
|
|
@ -202,7 +203,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
return partContext;
|
||||
}
|
||||
|
||||
async #prepareMemberContext(partId) {
|
||||
#prepareMemberContext(partId) {
|
||||
const data = this.party.system.tagTeam.members[partId] ?? {};
|
||||
const actor = game.actors.get(partId);
|
||||
if (!actor) console.error(`Failed to get actor ${partId}`);
|
||||
|
|
@ -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: await this.getCriticalDamage(data.damageRollData),
|
||||
useCritDamage: critSelected || (critSelected === undefined && data.roll?.isCritical)
|
||||
isCritical
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -374,7 +378,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
//#endregion
|
||||
//#region Tag Team Roll
|
||||
|
||||
async getInfoTexts(members) {
|
||||
getInfoTexts(members) {
|
||||
let rollsAreFinished = true;
|
||||
let rollIsSelected = false;
|
||||
for (const member of Object.values(members)) {
|
||||
|
|
@ -579,25 +583,6 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
);
|
||||
}
|
||||
|
||||
async getCriticalDamage(origDamage) {
|
||||
const newDamage = origDamage ? ChatDamageData.fromJSON(JSON.stringify(origDamage)) : null;
|
||||
if (newDamage?.main) {
|
||||
const criticalDamage = await getCritDamageBonus(newDamage.main.formula);
|
||||
if (criticalDamage) {
|
||||
const criticalTerm = new foundry.dice.terms.NumericTerm({ number: criticalDamage, evaluated: true });
|
||||
criticalTerm.evaluate();
|
||||
newDamage.main = await Roll.fromTerms([
|
||||
...origDamage.main.terms,
|
||||
new foundry.dice.terms.OperatorTerm({ operator: '+' }),
|
||||
criticalTerm
|
||||
]);
|
||||
newDamage.main.options = foundry.utils.deepClone(origDamage.main.options);
|
||||
}
|
||||
}
|
||||
|
||||
return newDamage;
|
||||
}
|
||||
|
||||
static async #selectRoll(_, button) {
|
||||
const { memberKey } = button.dataset;
|
||||
|
||||
|
|
@ -620,7 +605,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
);
|
||||
}
|
||||
|
||||
async getJoinedRoll({ overrideIsCritical, displayVersion } = {}) {
|
||||
getJoinedRoll({ overrideIsCritical, displayVersion } = {}) {
|
||||
try {
|
||||
const memberValues = Object.values(this.party.system.tagTeam.members);
|
||||
const selectedRoll = memberValues.find(x => x.selected);
|
||||
|
|
@ -640,17 +625,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 = await this.getCriticalDamage(mainRoll.damageRollData);
|
||||
|
||||
if (secondaryRoll.damageRollData) {
|
||||
const secondaryDamage = (displayVersion ? overrideIsCritical : isCritical)
|
||||
? await 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 +653,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 +677,11 @@ 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);
|
||||
|
|
@ -741,7 +727,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
const error = this.checkInitiatorHopeError(this.party.system.tagTeam.initiator);
|
||||
if (error) return error;
|
||||
|
||||
const joinedRoll = await this.getJoinedRoll();
|
||||
const joinedRoll = this.getJoinedRoll();
|
||||
const mainRoll = joinedRoll.rollData;
|
||||
const finalRoll = foundry.utils.deepClone(joinedRoll.roll);
|
||||
|
||||
|
|
@ -755,7 +741,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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue