import { describe, expect, it } from "vitest"; import { adaptRunewakerEnemyDamage, resolveRunewakerNativeResolvedPower, runewakerAttackDefenseRate, runewakerOrgPower, type RunewakerDamageFormulaSource, } from "./runewakerCombatFormula"; function formula( overrides: Partial = {}, ): 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); }); });