Fix adjusting tiers of higher level creatures and an error that may occur with hordes (#2059)

This commit is contained in:
Carlos Fernandez 2026-07-03 04:37:43 -04:00 committed by GitHub
parent 53ed9fc792
commit b3d96c25d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -2,8 +2,14 @@ import { calculateExpectedValue, parseTermsFromSimpleFormula } from '../../helpe
import { adversaryExpectedDamage, adversaryScalingData } from '../../config/actorConfig.mjs'; import { adversaryExpectedDamage, adversaryScalingData } from '../../config/actorConfig.mjs';
import { parseInlineParams } from '../../enrichers/parser.mjs'; import { parseInlineParams } from '../../enrichers/parser.mjs';
/**
* Accepts source data for an adversary and a target tier, and returns new source data
* @type {object} source
* @type {number} tier
* @returns {object} adjusted source data
*/
export function getTierAdjustedAdversary(source, tier) { export function getTierAdjustedAdversary(source, tier) {
const currentTier = source.tier ?? 1; const currentTier = source.system.tier ?? 1;
/** @type {(2 | 3 | 4)[]} */ /** @type {(2 | 3 | 4)[]} */
const tiers = new Array(Math.abs(tier - currentTier)) const tiers = new Array(Math.abs(tier - currentTier))
@ -35,7 +41,7 @@ export function getTierAdjustedAdversary(source, tier) {
// Store initial attack damage for abilities that have you deal a "standard attack" // Store initial attack damage for abilities that have you deal a "standard attack"
const initialAttack = { const initialAttack = {
type: source.system.attack.damage?.parts.hitPoints?.type?.toSorted(), type: source.system.attack.damage?.parts.hitPoints?.type?.toSorted(),
value: getDamagePartsFormula(source.system.attack.damage?.parts.hitPoints?.value) value: getFormula(source.system.attack.damage?.parts.hitPoints?.value)
}; };
// Update damage of base attack. // Update damage of base attack.
@ -45,9 +51,9 @@ export function getTierAdjustedAdversary(source, tier) {
for (const property of ['value', 'valueAlt']) { for (const property of ['value', 'valueAlt']) {
const data = damage.parts.hitPoints[property]; const data = damage.parts.hitPoints[property];
const previousFormula = getDamagePartsFormula(data); const previousFormula = getFormula(data);
const { value, formula } = calculateAdjustedDamage(previousFormula, 'attack', damageMeta); const value = calculateAdjustedDamage(previousFormula, 'attack', damageMeta);
applyAdjustedDamage(data, value, formula); applyAdjustedDamage(data, value);
} }
} catch (err) { } catch (err) {
ui.notifications.warn('Failed to convert attack damage of adversary'); ui.notifications.warn('Failed to convert attack damage of adversary');
@ -65,7 +71,7 @@ export function getTierAdjustedAdversary(source, tier) {
if (!formula) return match; if (!formula) return match;
try { try {
const newFormula = calculateAdjustedDamage(formula, 'action', damageMeta)?.formula; const newFormula = getFormula(calculateAdjustedDamage(formula, 'action', damageMeta));
descriptionFormulas.push(formula); descriptionFormulas.push(formula);
return match.replace(formula, newFormula); return match.replace(formula, newFormula);
} catch { } catch {
@ -82,15 +88,15 @@ export function getTierAdjustedAdversary(source, tier) {
const result = []; const result = [];
for (const property of ['value', 'valueAlt']) { for (const property of ['value', 'valueAlt']) {
const { [property]: data, type: damageType } = action.damage.parts.hitPoints; const { [property]: data, type: damageType } = action.damage.parts.hitPoints;
const previousFormula = getDamagePartsFormula(data); const previousFormula = getFormula(data);
const isActuallyAttack = const isActuallyAttack =
previousFormula === initialAttack.value && previousFormula === initialAttack.value &&
foundry.utils.equals(damageType.toSorted(), initialAttack.type) && foundry.utils.equals(damageType.toSorted(), initialAttack.type) &&
!descriptionFormulas.includes(previousFormula); !descriptionFormulas.includes(previousFormula);
const type = isActuallyAttack ? 'attack' : 'action'; const type = isActuallyAttack ? 'attack' : 'action';
const { value, formula } = calculateAdjustedDamage(previousFormula, type, damageMeta); const value = calculateAdjustedDamage(previousFormula, type, damageMeta);
applyAdjustedDamage(data, value, formula); applyAdjustedDamage(data, value);
result.push({ previousFormula, formula }); result.push({ previousFormula, formula: getFormula(value) });
} }
// Override text in the description with those values // Override text in the description with those values
@ -189,24 +195,30 @@ function calculateAdjustedDamage(formula, type, { currentDamageRange, newDamageR
value.bonus = Math.round(expected - getBaseAverage()); value.bonus = Math.round(expected - getBaseAverage());
} }
const newFormula = [value.diceQuantity ? `${value.diceQuantity}d${value.faces}` : null, value.bonus] return value;
.filter(p => !!p)
.join('+');
return { value, formula: newFormula };
} }
function getDamagePartsFormula(data) { /**
return data.custom.enabled * Get formula from either damage parts *or* a simple formula object.
? data.custom.formula * @returns {string} the new formula data
: [data.flatMultiplier ? `${data.flatMultiplier}${data.dice}` : 0, data.bonus ?? 0].filter(p => !!p).join('+'); */
function getFormula(data) {
if (data.custom?.enabled) {
return data.custom.formula;
}
const diceQuantity = data.flatMultiplier ?? data.diceQuantity;
const dice = data.faces ? `d${data.faces}` : data.dice;
const mod = data.bonus;
return [diceQuantity ? `${diceQuantity}${dice}` : 0, mod].filter(p => !!p).join('+');
} }
/** /**
* Updates damage to reflect a specific value. * Updates damage to reflect a specific value.
* @throws if damage structure is invalid for conversion * @param {object} diceData
* @returns the converted formula and value as a simplified term, or null if it doesn't deal HP damage * @param {object} value
*/ */
function applyAdjustedDamage(diceData, value, formula) { function applyAdjustedDamage(diceData, value) {
if (value.diceQuantity) { if (value.diceQuantity) {
diceData.custom.enabled = false; diceData.custom.enabled = false;
diceData.bonus = value.bonus; diceData.bonus = value.bonus;
@ -214,6 +226,6 @@ function applyAdjustedDamage(diceData, value, formula) {
diceData.flatMultiplier = value.diceQuantity; diceData.flatMultiplier = value.diceQuantity;
} else if (!value.diceQuantity) { } else if (!value.diceQuantity) {
diceData.custom.enabled = true; diceData.custom.enabled = true;
diceData.custom.formula = formula; diceData.custom.formula = getFormula(value);
} }
} }