Update Healer Man server

This commit is contained in:
phenom committed 2026-09-28 22:46:45 -04:00
1 parent 9d7e0e2f9e
commit 35dfdaed61
94 files changed
+17034 -418

No files matched your search

@@ -0,0 +1,84 @@
import { beforeEach, describe, expect, it } from "vitest";
import { abilitiesForClass, abilityAtLevel } from "./abilityCatalog";
import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry";
import { useCombatStore } from "./combatStore";
import { clearPartyRuntimeRegistry, registerPartyRuntimePosition } from "./partyRuntimeRegistry";
import { usePartyStore } from "./partyStore";
const HEALING_STREAM_RANKS = [
{ level: 20, spellId: 5394, heal: 6 },
{ level: 30, spellId: 6375, heal: 8 },
{ level: 40, spellId: 6377, heal: 10 },
{ level: 50, spellId: 10462, heal: 12 },
{ level: 60, spellId: 10463, heal: 14 },
{ level: 69, spellId: 25567, heal: 18 },
{ level: 71, spellId: 58755, heal: 20 },
{ level: 76, spellId: 58756, heal: 23 },
{ level: 80, spellId: 58757, heal: 25 },
] as const;
function healingStreamAbility() {
const ability = abilitiesForClass("shaman").find((candidate) => candidate.name === "Healing Stream Totem");
expect(ability, "Healing Stream Totem").toBeDefined();
return ability!;
}
describe("WoW Shaman Healing Stream Totem", () => {
beforeEach(() => {
clearMobRuntimeRegistry();
clearPartyRuntimeRegistry();
useCombatStore.getState().initializeCharacter({ classId: "shaman", level: 80, xp: 0 });
useCombatStore.getState().setPlayerPosition([0, 0, 0]);
usePartyStore.getState().initializeParty("wow-healing-stream-test", 80, useCombatStore.getState().health);
});
it("uses each source rank’s 2-second heal amount", () => {
const base = healingStreamAbility();
for (const expected of HEALING_STREAM_RANKS) {
const ranked = abilityAtLevel(base, expected.level);
const summon = ranked.effects.find((effect) => effect.kind === "summon");
expect(ranked.dbcSpellId).toBe(expected.spellId);
expect(summon?.kind).toBe("summon");
if (summon?.kind !== "summon") continue;
expect(summon.healingPulse).toEqual({ amount: expected.heal, intervalMs: 2_000, radius: 10 });
expect(summon.durationMs).toBe(300_000);
}
});
it("heals every nearby party member and never attacks the selected enemy", () => {
const state = useCombatStore.getState();
const members = usePartyStore.getState().members;
useCombatStore.setState((current) => ({ health: current.maxHealth - 25 }));
usePartyStore.setState((current) => ({
members: current.members.map((member) => ({ ...member, health: member.maxHealth - 25 })),
}));
members.forEach((member, index) => {
registerPartyRuntimePosition(member.id, index === 0 ? [5, 0, 0] : index === 1 ? [9, 0, 0] : [10.1 + index, 0, 0]);
});
useCombatStore.getState().registerMob("healing-stream-nearby-enemy", { name: "Nearby enemy", maxHealth: 10_000 });
setMobPosition("healing-stream-nearby-enemy", [4, 0, 0]);
useCombatStore.getState().selectMob("healing-stream-nearby-enemy");
const cast = useCombatStore.getState().castAbility(healingStreamAbility().id, undefined, 1_000);
expect(cast.ok, JSON.stringify(cast)).toBe(true);
const totem = useCombatStore.getState().summons.find((summon) => (
summon.sourceAbilityId === healingStreamAbility().id
));
expect(totem).toBeDefined();
expect(totem?.kind).toBe("totem");
expect(totem?.maxHealth).toBe(5);
expect(totem?.attackDamage).toBe(0);
expect(totem?.expiresAt).toBe(301_000);
useCombatStore.getState().tick(0, 3_000);
const after = useCombatStore.getState();
expect(after.health).toBe(after.maxHealth);
expect(usePartyStore.getState().members[0]?.health).toBe(usePartyStore.getState().members[0]?.maxHealth);
expect(usePartyStore.getState().members[1]?.health).toBe(usePartyStore.getState().members[1]?.maxHealth);
expect(usePartyStore.getState().members[2]?.health).toBe((usePartyStore.getState().members[2]?.maxHealth ?? 0) - 25);
expect(after.mobs["healing-stream-nearby-enemy"]?.health).toBe(10_000);
expect(after.combatEvents.filter((event) => event.kind === "healing"
&& event.abilityId === healingStreamAbility().id)).toHaveLength(3);
});
});