Files
healer-man/src/game/runewakerCombatFormula.test.ts
T
2026-09-08 10:40:26 -04:00

87 lines
2.7 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
adaptRunewakerEnemyDamage,
resolveRunewakerNativeResolvedPower,
runewakerAttackDefenseRate,
runewakerOrgPower,
type RunewakerDamageFormulaSource,
} from "./runewakerCombatFormula";
function formula(
overrides: Partial<RunewakerDamageFormulaSource> = {},
): RunewakerDamageFormulaSource {
return {
schemaVersion: 1,
spellId: 492_289,
componentId: 502_503,
spellLevel: 6,
calculationPath: "physical",
powerKind: "source-ratio",
damagePower: -0.7,
fixedValue: 0,
dotBase: 0,
runtimeBaselineMultiplier: 0.85,
provenance: {
sourceFile: "MagicProcess.cpp",
physicalFunctionLine: 3366,
magicFunctionLine: 3651,
magicObjectDatabase: "magicobject.db",
},
...overrides,
};
}
describe("RuneWaker combat formula adapter", () => {
it("preserves source ratio powers against HealerMan's explicit baseline", () => {
expect(adaptRunewakerEnemyDamage({ formula: formula(), baselineDamage: 100 })).toMatchObject({
amount: 70,
fidelity: "source-ratio-adapter",
appliedMultiplier: 0.7,
});
});
it("labels point-valued powers as scaled adapters instead of native damage", () => {
const result = adaptRunewakerEnemyDamage({
formula: formula({ powerKind: "source-points", damagePower: -300 }),
baselineDamage: 100,
});
expect(result).toMatchObject({ amount: 85, fidelity: "scaled-point-adapter" });
expect(result.unavailableSourceInputs).toContain("RuneWaker ATK or MATK");
expect(result.unavailableSourceInputs).toContain("RuneWaker global NPC/PvP/AoE/target damage rates");
});
it("fails closed when no damage family was proven", () => {
expect(adaptRunewakerEnemyDamage({
formula: formula({ powerKind: "unresolved", runtimeBaselineMultiplier: 0 }),
baselineDamage: 100,
})).toMatchObject({ amount: 0, fidelity: "unsupported" });
});
it("implements the preserved org-power and attack-defense expressions", () => {
expect(runewakerOrgPower(-100, 5, 10)).toBe(-150);
expect(runewakerAttackDefenseRate(400, 300)).toBe(1);
expect(runewakerAttackDefenseRate(0, 10_000)).toBe(0.2);
});
it("requires every native rate in the source-shaped resolved-power path", () => {
expect(resolveRunewakerNativeResolvedPower({
power: -100,
fixedValue: -0.5,
fixedAttributeValue: 20,
fixedDamageSkillLevelPercent: 10,
spellLevel: 5,
attackerPower: 400,
defenderPower: 300,
criticalMultiplier: 2,
levelRate: 1,
resistanceRate: 0.8,
pvpOrNpcDamageRate: 1,
areaPowerRate: 1,
areaDefenseRate: 1,
attackTargetRate: 1,
attackerOriginDefenseRate: 1,
sharedDamageRate: 1,
})).toBe(184);
});
});