Release Healer Man 0.1.59

This commit is contained in:
phenom committed 2026-09-27 10:16:42 -04:00
1 parent 11934a3979
commit ab1434a3b8
44 files changed
+1242 -103

No files matched your search

+35 -6
View File
@@ -2,6 +2,9 @@ import { describe, expect, it } from "vitest";
import { abilityAtLevel, type AbilityDefinition, type AbilityEffect } from "./abilityCatalog";
import { aiHintsForAbility, targetingRulesForAbility } from "./abilityRules";
import { WOW335_ABILITIES_BY_CLASS } from "./wow335AbilityCatalog";
import generatedData from "./wow335AbilityData.generated.json";
import { talentNodeById } from "./talentCatalog";
import { runtimeTalentNodeById } from "./talentRuntimeCatalog";
function byId(id: string): AbilityDefinition {
const ability = Object.values(WOW335_ABILITIES_BY_CLASS)
@@ -21,6 +24,14 @@ function effectsOfKind<K extends AbilityEffect["kind"]>(
}
describe("WoW 3.3.5 executable effect mapping", () => {
it("uses the same legal talent-node set as the full catalog", () => {
const talentNodeIds = new Set(Object.values(generatedData.classes)
.flatMap((chains) => chains.flatMap((chain) => chain.talentNodeId ? [chain.talentNodeId] : [])));
for (const nodeId of talentNodeIds) {
expect(Boolean(runtimeTalentNodeById(nodeId)), nodeId).toBe(Boolean(talentNodeById(nodeId)));
}
});
it("preserves source spells that do not trigger a global cooldown", () => {
expect(byId("wow335-priest-inner-focus").gcdMs).toBe(0);
expect(byId("wow335-rogue-cold-blood").gcdMs).toBe(0);
@@ -213,19 +224,37 @@ describe("WoW 3.3.5 executable effect mapping", () => {
it("models Penance as three healing or damaging pulses", () => {
const penance = byId("wow335-priest-penance");
expect(penance).toMatchObject({ castMode: "channel", castTimeMs: 2_000, channelTickMs: 1_000,
channelStartsWithPulse: true });
expect(penance.target).toBe("any");
expect(effectsOfKind(penance, "heal")).toEqual([
expect.objectContaining({ coefficient: 0.6 }),
]);
expect(effectsOfKind(penance, "hot")).toEqual([
expect.objectContaining({ coefficient: 0.6, ticks: 2, intervalMs: 1_000 }),
]);
expect(effectsOfKind(penance, "hot")).toEqual([]);
expect(effectsOfKind(penance, "damage")).toEqual([
expect.objectContaining({ coefficient: 0.6 }),
]);
expect(effectsOfKind(penance, "dot")).toEqual([
expect.objectContaining({ coefficient: 0.6, ticks: 2, intervalMs: 1_000 }),
]);
expect(effectsOfKind(penance, "dot")).toEqual([]);
});
it("keeps ground-channel damage children out of learned cast ranks", () => {
for (const id of ["wow335-mage-blizzard", "wow335-warlock-rain-of-fire", "wow335-druid-hurricane"]) {
const ability = byId(id);
expect(ability.ranks?.every((rank) => rank.castMode === "channel"), id).toBe(true);
expect(abilityAtLevel(ability, 80).castMode, id).toBe("channel");
}
const hurricane = abilityAtLevel(byId("wow335-druid-hurricane"), 80);
expect(hurricane).toMatchObject({ dbcSpellId: 48467, castTimeMs: 10_000,
channelTickMs: 1_000, channelPulses: 10 });
expect(hurricane.cost.amount).toBeGreaterThan(0);
});
it("keeps every rank of imported channels in channel mode", () => {
const mismatches = Object.values(WOW335_ABILITIES_BY_CLASS).flat()
.filter((ability) => ability.castMode === "channel" && ability.ranks?.some((rank) => rank.castMode !== "channel"))
.map((ability) => `${ability.name}: ${ability.ranks?.filter((rank) => rank.castMode !== "channel")
.map((rank) => rank.spellId).join(", ")}`);
expect(mismatches).toEqual([]);
});
it("maps the Ready-five missing spell payloads without cast-time damage on self buffs", () => {