Update Healer Man server

This commit is contained in:
phenom committed 2026-10-07 13:05:04 -04:00
1 parent 69809f7228
commit ff20ab8779
101 files changed
+16713 -945

No files matched your search

+146 -1
View File
@@ -1,10 +1,23 @@
import { describe, expect, it } from "vitest";
import { abilityAtLevel, type AbilityDefinition, type AbilityEffect } from "./abilityCatalog";
import {
abilityAtLevel,
abilityById,
isAbilityUnlocked,
preloadAbilityCatalogsForClasses,
type AbilityDefinition,
type AbilityEffect,
} from "./abilityCatalog";
import { aiHintsForAbility, targetingRulesForAbility } from "./abilityRules";
import {
WOW335_ABILITIES_BY_CLASS,
WOW335_HUNTER_PREVENTION_TYPES_BY_SPELL_ID,
WOW335_TRIGGERED_ABILITIES_BY_SPELL_ID,
wow335HunterPreventionTypeForAbility,
} from "./wow335AbilityCatalog";
import {
WOW335_HUNTER_DETERRENCE_LINKED_AURA_EFFECTS,
WOW335_HUNTER_DETERRENCE_PARENT_AURA_EFFECTS,
} from "./wow335DeterrenceRuntime";
import generatedData from "./wow335AbilityData.generated.json";
import { talentNodeById } from "./talentCatalog";
import { runtimeTalentNodeById } from "./talentRuntimeCatalog";
@@ -27,6 +40,138 @@ function effectsOfKind<K extends AbilityEffect["kind"]>(
}
describe("WoW 3.3.5 executable effect mapping", () => {
it("selects Hunter Deterrence 19263 and exposes its complete linked aura package", () => {
expect(generatedData.classes.hunter.some((chain) => chain.name === "Deterrence"
|| chain.ranks.some((rank) => [19_263, 65_871, 67_801].includes(rank.spellId)))).toBe(false);
const deterrence = byId("wow335-hunter-deterrence");
const catalogDeterrence = abilityById("wow335-hunter-deterrence");
expect(catalogDeterrence).toMatchObject({
id: "wow335-hunter-deterrence",
classId: "hunter",
dbcSpellId: 19_263,
source: "wow335-progression",
});
expect(isAbilityUnlocked(catalogDeterrence!, 60)).toBe(true);
expect(isAbilityUnlocked(catalogDeterrence!, 59)).toBe(false);
expect(WOW335_ABILITIES_BY_CLASS.hunter.filter((ability) => ability.name === "Deterrence")).toHaveLength(1);
expect(deterrence).toMatchObject({
id: "wow335-hunter-deterrence",
classId: "hunter",
source: "wow335-progression",
dbcSpellId: 19_263,
name: "Deterrence",
unlockLevel: 60,
sourceUnlockLevel: 60,
target: "self",
range: { min: 0, max: 0 },
castMode: "instant",
castTimeMs: 0,
cooldownMs: 90_000,
gcdMs: 0,
cost: { resource: "mana", amount: 0 },
wowSpellDefense: {
damageClass: 0,
schoolMask: 1,
attributes0: 327_696,
attributes1: 16,
attributes3: 0,
attributes5: 0,
directDamageFromEffects: false,
sourceProfile: "wow335",
},
wowWeaponRequirements: {
equippedItemClass: 2,
equippedItemSubclassMask: 173_555,
equippedItemInventoryMask: 0,
},
});
expect(abilityAtLevel(deterrence, 80)).toMatchObject({
dbcSpellId: 19_263,
description: "When activated, increases parry chance by 100% and grants a 100% chance to deflect spells. While Deterrence is active, you cannot attack. Lasts 5 sec.",
cooldownMs: 90_000,
gcdMs: 0,
cost: { resource: "mana", amount: 0 },
wowWeaponRequirements: {
equippedItemClass: 2,
equippedItemSubclassMask: 173_555,
equippedItemInventoryMask: 0,
},
});
expect(effectsOfKind(abilityAtLevel(deterrence, 80), "apply-aura")
.map((effect) => effect.aura.durationMs)).toEqual([5_000, 5_000, 5_000]);
expect(deterrence.effects).toEqual(WOW335_HUNTER_DETERRENCE_PARENT_AURA_EFFECTS);
expect(WOW335_HUNTER_DETERRENCE_PARENT_AURA_EFFECTS[1]?.kind === "apply-aura"
? WOW335_HUNTER_DETERRENCE_PARENT_AURA_EFFECTS[1].aura.utilityTags
: undefined).toBeUndefined();
expect(effectsOfKind(deterrence, "apply-aura").map((effect) => [
effect.sourceEffectType,
effect.sourceAuraType,
effect.sourceBasePoints,
effect.aura.durationMs,
])).toEqual([
[6, 47, 99, 5_000],
[6, 287, 99, 5_000],
[6, 25, -1, 5_000],
]);
expect(WOW335_HUNTER_DETERRENCE_LINKED_AURA_EFFECTS.map((effect) => {
expect(effect.kind).toBe("apply-aura");
if (effect.kind !== "apply-aura") return [];
return [effect.aura.id, effect.sourceEffectType, effect.sourceAuraType, effect.sourceBasePoints, effect.aura.durationMs];
})).toEqual([
["wow335:67801:effect:0:aura:288", 6, 288, 99, 5_000],
["wow335:67801:effect:1:aura:185", 6, 185, -101, 5_000],
]);
const linkedRangedHit = WOW335_HUNTER_DETERRENCE_LINKED_AURA_EFFECTS[1];
expect(linkedRangedHit?.kind === "apply-aura" ? linkedRangedHit.aura.modifiers : undefined).toEqual([
{ kind: "stat", stat: "incoming-ranged-hit", operation: "flat", value: -100 },
]);
const linkedIgnoreFacing = WOW335_HUNTER_DETERRENCE_LINKED_AURA_EFFECTS[0];
expect(linkedIgnoreFacing?.kind === "apply-aura" ? linkedIgnoreFacing.aura.utilityTags : undefined).toBeUndefined();
expect(WOW335_TRIGGERED_ABILITIES_BY_SPELL_ID[67_801]).toBeUndefined();
expect(WOW335_ABILITIES_BY_CLASS.hunter.some((ability) => ability.dbcSpellId === 67_801)).toBe(false);
expect(WOW335_ABILITIES_BY_CLASS.hunter.some((ability) => ability.dbcSpellId === 65_871)).toBe(false);
});
it("retains pinned PreventionType for every selected Hunter rank and merged public aliases", async () => {
const selectedSpellIds = new Set<number>();
for (const ability of WOW335_ABILITIES_BY_CLASS.hunter) {
for (const rank of ability.ranks ?? []) {
selectedSpellIds.add(rank.spellId);
expect(WOW335_HUNTER_PREVENTION_TYPES_BY_SPELL_ID[rank.spellId]).toBeDefined();
expect(wow335HunterPreventionTypeForAbility({ ...ability, dbcSpellId: rank.spellId }))
.toBe(WOW335_HUNTER_PREVENTION_TYPES_BY_SPELL_ID[rank.spellId]);
}
}
expect(selectedSpellIds.size).toBe(190);
expect([...selectedSpellIds].sort((left, right) => left - right)).toEqual(
Object.keys(WOW335_HUNTER_PREVENTION_TYPES_BY_SPELL_ID).map(Number).sort((left, right) => left - right),
);
await preloadAbilityCatalogsForClasses(["hunter"]);
const publicArcaneShot = abilityById("hunter-arcane-shot");
expect(publicArcaneShot).toMatchObject({ id: "hunter-arcane-shot", classId: "hunter", source: "wow335-progression" });
expect(wow335HunterPreventionTypeForAbility(abilityAtLevel(publicArcaneShot!, 80))).toBe(2);
const publicSteadyShot = abilityById("hunter-steady-shot");
expect(wow335HunterPreventionTypeForAbility(abilityAtLevel(publicSteadyShot!, 80))).toBe(2);
const arcaneShot = byId("wow335-hunter-arcane-shot");
const selectedArcaneRank = { ...arcaneShot, dbcSpellId: 3_044 };
expect(wow335HunterPreventionTypeForAbility({ ...selectedArcaneRank, classId: "mage" })).toBeUndefined();
expect(wow335HunterPreventionTypeForAbility({ ...selectedArcaneRank, source: "core" })).toBeUndefined();
expect(wow335HunterPreventionTypeForAbility({ ...selectedArcaneRank, source: "ascension-progression" })).toBeUndefined();
expect(wow335HunterPreventionTypeForAbility({ ...selectedArcaneRank, name: "Deterrence" })).toBeUndefined();
expect(wow335HunterPreventionTypeForAbility({ ...selectedArcaneRank, id: "foreign-hunter-arcane-shot" })).toBeUndefined();
expect(wow335HunterPreventionTypeForAbility({ ...selectedArcaneRank, dbcSpellId: 999_999 })).toBeUndefined();
expect(wow335HunterPreventionTypeForAbility({ ...selectedArcaneRank, dbcSpellId: 65_871 })).toBeUndefined();
expect(wow335HunterPreventionTypeForAbility({ ...selectedArcaneRank, dbcSpellId: 67_801 })).toBeUndefined();
expect(WOW335_HUNTER_PREVENTION_TYPES_BY_SPELL_ID[19_263]).toBe(0);
expect(WOW335_HUNTER_PREVENTION_TYPES_BY_SPELL_ID[3044]).toBe(2);
expect(WOW335_HUNTER_PREVENTION_TYPES_BY_SPELL_ID[13_813]).toBe(1);
expect(WOW335_HUNTER_PREVENTION_TYPES_BY_SPELL_ID[136]).toBe(1);
});
it("resolves tooltip tokens that explicitly reference another DBC spell", () => {
const chains = Object.values(generatedData.classes).flat();
const dancingRuneWeapon = chains.find((chain) => chain.name === "Dancing Rune Weapon");