90 lines
5.5 KiB
TypeScript
90 lines
5.5 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { dungeonEnemyScaling } from "./dungeonBossScaling";
|
|
import { bossDifficultyMultipliers } from "./dungeonDifficulty";
|
|
import { requireDungeonDefinition } from "./dungeonRegistry";
|
|
import { finalDungeonBoss } from "./dungeonRunStore";
|
|
import { useCombatStore } from "./combatStore";
|
|
|
|
const dungeon = requireDungeonDefinition("barren-caves");
|
|
const boss = finalDungeonBoss(dungeon)!;
|
|
const bossSpawn = dungeon.staticSpawns.find((spawn) => spawn.id === boss.id)!;
|
|
const trashSpawn = dungeon.staticSpawns.find((spawn) => dungeon.entities[spawn.entityId].kind === "mob")!;
|
|
|
|
describe("native RoM dungeon health budgets", () => {
|
|
it("calibrates the level-one native Anglo boss without changing trash health", () => {
|
|
const nativeBoss = dungeonEnemyScaling(dungeon, dungeon.entities[bossSpawn.entityId], boss.id,
|
|
1, "normal", 1, "rom", "rom");
|
|
const legacyBoss = dungeonEnemyScaling(dungeon, dungeon.entities[bossSpawn.entityId], boss.id,
|
|
1, "normal", 1, "rom", "wow");
|
|
const nativeTrash = dungeonEnemyScaling(dungeon, dungeon.entities[trashSpawn.entityId], trashSpawn.id,
|
|
1, "normal", 1, "rom", "rom");
|
|
const legacyTrash = dungeonEnemyScaling(dungeon, dungeon.entities[trashSpawn.entityId], trashSpawn.id,
|
|
1, "normal", 1, "rom", "wow");
|
|
|
|
expect(nativeBoss.maxHealth).toBe(1_848);
|
|
expect(nativeBoss.maxHealth).toBeCloseTo(legacyBoss.maxHealth * 0.2);
|
|
expect(nativeTrash.maxHealth).toBeCloseTo(legacyTrash.maxHealth * 0.4);
|
|
expect(nativeTrash.nativeDamageBudgetScale).toBe(1);
|
|
});
|
|
|
|
it("keeps native training budgets independent of legacy stats and authored difficulty", () => {
|
|
for (const level of [1, 30, 66, 79, 80]) for (const spawn of [trashSpawn, bossSpawn]) {
|
|
const entity = dungeon.entities[spawn.entityId];
|
|
const legacy = dungeonEnemyScaling(dungeon, entity, spawn.id, level, "normal", 1, "rom");
|
|
expect(dungeonEnemyScaling(dungeon, entity, spawn.id, level, "normal", 1, "rom", "wow")).toEqual(legacy);
|
|
const native = dungeonEnemyScaling(dungeon, entity, spawn.id, level, "normal", 1, "rom", "rom");
|
|
expect(native.maxHealth).not.toBe(legacy.maxHealth);
|
|
expect(native.damageMultiplier).toBe(legacy.damageMultiplier);
|
|
expect(legacy.nativeDamageBudgetScale).toBe(1);
|
|
expect(native.nativeDamageBudgetScale).toBeGreaterThanOrEqual(1);
|
|
expect(native.level).toBe(legacy.level);
|
|
for (const source of ["wow", "coa"] as const) {
|
|
expect(dungeonEnemyScaling(dungeon, entity, spawn.id, level, "normal", 1, source, "rom"))
|
|
.toEqual(dungeonEnemyScaling(dungeon, entity, spawn.id, level, "normal", 1, source));
|
|
}
|
|
}
|
|
});
|
|
|
|
it("retains the level-80 cap and 79-to-80 native boss health plateau", () => {
|
|
const entity = dungeon.entities[bossSpawn.entityId];
|
|
const at = (level: number) => dungeonEnemyScaling(dungeon, entity, boss.id, level, "normal", 1, "rom", "rom");
|
|
expect(at(79)).toEqual(at(80));
|
|
expect(at(120)).toEqual(at(80));
|
|
expect(at(80).level).toBe(80);
|
|
});
|
|
|
|
it("does not compound damage during live registration or retain native pressure after a mode switch", () => {
|
|
const entity = dungeon.entities[bossSpawn.entityId];
|
|
const native = dungeonEnemyScaling(dungeon, entity, boss.id, 80, "normal", 1, "rom", "rom");
|
|
const legacy = dungeonEnemyScaling(dungeon, entity, boss.id, 80, "normal", 1, "rom", "wow");
|
|
const combat = useCombatStore.getState();
|
|
combat.initializeCharacter({ classId: "rom-priest", raceId: "rom-human", level: 80, statRuleset: "rom" });
|
|
combat.registerMob("legacy-reference", { name: "Anglo", boss: true, ...legacy, xpReward: 0 });
|
|
combat.registerMob("live-registration", { name: "Anglo", boss: true, ...native, xpReward: 0 });
|
|
const first = useCombatStore.getState().mobs["live-registration"];
|
|
combat.registerMob("live-registration", { name: "Anglo", boss: true, ...native, xpReward: 0 });
|
|
expect(useCombatStore.getState().mobs["live-registration"].attackDamage).toBe(first.attackDamage);
|
|
expect(useCombatStore.getState().mobs["live-registration"].attackPowerDamageContribution).toBe(first.attackPowerDamageContribution);
|
|
combat.registerMob("live-registration", { name: "Anglo", boss: true, ...legacy, xpReward: 0 });
|
|
const switched = useCombatStore.getState().mobs["live-registration"];
|
|
const reference = useCombatStore.getState().mobs["legacy-reference"];
|
|
expect(switched.attackDamage).toBe(reference.attackDamage);
|
|
expect(switched.attackPowerDamageContribution).toBe(reference.attackPowerDamageContribution);
|
|
expect(switched.nativeDamageBudgetScale).toBe(1);
|
|
});
|
|
|
|
it("keeps each difficulty multiplier and leaves trash independent of the boss slider", () => {
|
|
const entity = dungeon.entities[bossSpawn.entityId];
|
|
const easy = dungeonEnemyScaling(dungeon, entity, boss.id, 30, "normal", 1, "rom", "rom");
|
|
for (let difficulty = 2; difficulty <= 10; difficulty += 1) {
|
|
const scaled = dungeonEnemyScaling(dungeon, entity, boss.id, 30, "normal", difficulty, "rom", "rom");
|
|
expect(scaled.maxHealth).toBeCloseTo(easy.maxHealth * bossDifficultyMultipliers(difficulty).health);
|
|
expect(scaled.damageMultiplier).toBeCloseTo(easy.damageMultiplier * bossDifficultyMultipliers(difficulty).damage);
|
|
expect(dungeonEnemyScaling(dungeon, dungeon.entities[trashSpawn.entityId], trashSpawn.id,
|
|
30, "normal", difficulty, "rom", "rom"))
|
|
.toEqual(dungeonEnemyScaling(dungeon, dungeon.entities[trashSpawn.entityId], trashSpawn.id,
|
|
30, "normal", 1, "rom", "rom"));
|
|
}
|
|
});
|
|
});
|