Use standard deviation instead and change dialog type

This commit is contained in:
Carlos Fernandez 2026-01-27 04:57:13 -05:00
parent 5a95744b6f
commit 57cd7c0679
5 changed files with 72 additions and 23 deletions

View file

@ -47,7 +47,7 @@ export default class DhActorDirectory extends foundry.applications.sidebar.tabs.
_getEntryContextOptions() {
const options = super._getEntryContextOptions();
options.push({
name: 'Duplicate To New Tier',
name: 'DAGGERHEART.UI.Sidebar.actorDirectory.duplicateToNewTier',
icon: `<i class="fa-solid fa-arrow-trend-up" inert></i>`,
condition: li => {
const actor = game.actors.get(li.dataset.entryId);
@ -57,12 +57,24 @@ export default class DhActorDirectory extends foundry.applications.sidebar.tabs.
const actor = game.actors.get(li.dataset.entryId);
if (!actor) throw new Error('Unexpected missing actor');
const tiers = [1, 2, 3, 4].filter((t) => t !== actor.system.tier);
const content = document.createElement("div");
const select = document.createElement("select");
select.name = "tier";
select.append(...tiers.map(t => {
const option = document.createElement("option");
option.value = t;
option.textContent = game.i18n.localize(`DAGGERHEART.GENERAL.Tiers.${t}`);
return option;
}));
content.append(select);
const tier = await foundry.applications.api.Dialog.input({
window: { title: 'Pick a new tier for this adversary' },
content: '<input name="tier" type="number" min="1" max="4" step="1" autofocus>',
window: { title: 'DAGGERHEART.UI.Sidebar.actorDirectory.pickTierTitle' },
content,
ok: {
label: 'Create Adversary',
callback: (event, button, dialog) => Math.clamp(button.form.elements.tier.valueAsNumber, 1, 4)
callback: (event, button, dialog) => Number(button.form.elements.tier.value)
}
});

View file

@ -747,18 +747,22 @@ export const adversaryScalingData = {
}
};
/** Scaling data used for an adversary's damage */
/**
* Scaling data used for an adversary's damage.
* Tier 4 is missing certain adversary types and therefore skews upwards.
* We manually set tier 4 data to hopefully lead to better results
*/
export const adversaryExpectedDamage = {
basic: {
1: { median: 7.5, deviation: 1 },
2: { median: 13, deviation: 2 },
3: { median: 15.5, deviation: 1.5 },
4: { median: 27, deviation: 3 }
1: { mean: 7.321428571428571, deviation: 1.962519002770912 },
2: { mean: 12.444444444444445, deviation: 2.0631069425529676 },
3: { mean: 15.722222222222221, deviation: 2.486565208464823 },
4: { mean: 26, deviation: 5.2 }
},
minion: {
1: { median: 2, deviation: 1 },
2: { median: 5, deviation: 0.5 },
3: { median: 6.5, deviation: 1.5 },
4: { median: 11, deviation: 1 }
1: { mean: 2.142857142857143, deviation: 1.0690449676496976 },
2: { mean: 5, deviation: 0.816496580927726 },
3: { mean: 6.5, deviation: 2.1213203435596424 },
4: { mean: 11, deviation: 1 }
}
};

View file

@ -193,7 +193,6 @@ export default class DhpAdversary extends BaseDataActor {
adjustForTier(tier) {
const source = this.parent.toObject(true);
console.log('Actors and source', this.parent, source);
/** @type {(2 | 3 | 4)[]} */
const tiers = new Array(Math.abs(tier - this.tier))
@ -214,7 +213,7 @@ export default class DhpAdversary extends BaseDataActor {
source.system.attack.roll.bonus += scale * entry.attack;
}
// Get the median and median absolute deviation of expected damage in the previous and new tier
// Get the mean and standard deviation of expected damage in the previous and new tier
const expectedDamageData = adversaryExpectedDamage[source.system.type] ?? adversaryExpectedDamage.basic;
const currentDamageRange = { tier: source.system.tier, ...expectedDamageData[source.system.tier] };
const newDamageRange = { tier, ...expectedDamageData[tier] };
@ -274,8 +273,8 @@ export default class DhpAdversary extends BaseDataActor {
const dieSizes = ['d4', 'd6', 'd8', 'd10', 'd12', 'd20'];
const steps = newDamageRange.tier - currentDamageRange.tier;
const increasing = steps > 0;
const deviation = (previousExpected - currentDamageRange.median) / currentDamageRange.deviation;
const expected = newDamageRange.median + newDamageRange.deviation * deviation;
const deviation = (previousExpected - currentDamageRange.mean) / currentDamageRange.deviation;
const expected = newDamageRange.mean + newDamageRange.deviation * deviation;
const value = hitPointParts[0].value;
const getExpectedDie = () => Number(value.dice.replace('d', '')) / 2;