Update Healer Man server

This commit is contained in:
phenom committed 2026-10-02 10:38:12 -04:00
1 parent 4c768fbec6
commit b16821e92e
330 files changed
+35406 -1760

No files matched your search

+167 -6
View File
@@ -1,6 +1,6 @@
import { beforeAll, beforeEach, describe, expect, it } from "vitest";
import type { AbilityEffect } from "./abilityCatalog";
import { abilitiesForCharacter, preloadAbilityCatalogsForClasses } from "./abilityCatalog";
import { abilitiesForCharacter, learnedAbilityForBuild, preloadAbilityCatalogsForClasses } from "./abilityCatalog";
import { cooldownResetCandidates } from "./cooldownReset";
import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry";
import {
@@ -194,18 +194,179 @@ describe("RuneWaker Warlock runtime", () => {
))).toBe(false);
});
it("converts the RoM Warlock/Warrior Rage pool to psi at 35:1", () => {
it("converts a fixed 75 Rage cost into six Psi for Mind Transference", () => {
prepareWarlock("rom-warrior");
useCombatStore.setState((state) => ({
resourcePools: { ...state.resourcePools, rage: 70, psi: 1 },
resourcePools: { ...state.resourcePools, rage: 100, psi: 1 },
}));
const mindTransference = ability(498642);
expect(mindTransference.costs).toEqual([]);
expect(mindTransference.costs).toEqual([{ resource: "rage", amount: 75, percentage: false }]);
expect(mindTransference.cooldownMs).toBe(1_000);
expect(mindTransference.effects).toEqual([{ kind: "resource", resource: "psi", amount: 6 }]);
expect(useCombatStore.getState().castAbility(mindTransference.id, { now: 1_000 }).ok).toBe(true);
expect(useCombatStore.getState().resourcePools.rage).toBe(0);
expect(useCombatStore.getState().resourcePools.psi).toBe(3);
expect(useCombatStore.getState().resourcePools.rage).toBe(25);
expect(useCombatStore.getState().resourcePools.psi).toBe(6);
});
it("uses current Warlock/Priest passive effects and pair upgrades", () => {
const context = {
sealStacks: 0,
bleedCount: 0,
charged: false,
mainHandDagger: false,
casterMaxHealth: 10_000,
targetHealthPercent: 1,
learnedPassiveSpellIds: [498633, 498643, 498648, 498668],
} as const;
const divineAssistance = ability(498668);
expect(divineAssistance.description).toContain("magical damage and healing by 16%");
expect(divineAssistance.effects).toContainEqual(expect.objectContaining({
kind: "apply-aura",
aura: expect.objectContaining({
durationMs: null,
modifiers: expect.arrayContaining([
expect.objectContaining({ kind: "damage", direction: "dealt", school: "shadow", value: 0.16 }),
expect.objectContaining({ kind: "healing", direction: "done", value: 0.16 }),
]),
}),
}));
const healingFortune = romEffectsForCast(ability(497957), context)
.find((effect) => effect.kind === "apply-aura");
expect(healingFortune).toMatchObject({
kind: "apply-aura",
recipient: "caster",
requiresLandedHit: true,
aura: {
durationMs: 20_000,
modifiers: expect.arrayContaining([
expect.objectContaining({ kind: "healing", direction: "done", value: 0.12 }),
expect.objectContaining({ kind: "stat", stat: "wisdom", value: 0.12 }),
]),
},
});
const pairAbilities = abilitiesForCharacter("rom-warlock", "rom-priest");
const risingTide = pairAbilities.find((candidate) => candidate.dbcSpellId === 490256)!;
expect(learnedAbilityForBuild(risingTide, 29, {})).toMatchObject({ castTimeMs: 2_000, cooldownMs: 0 });
const upgradedRisingTide = learnedAbilityForBuild(risingTide, 30, {})!;
expect(upgradedRisingTide).toMatchObject({ castMode: "instant", castTimeMs: 0, cooldownMs: 5_000 });
expect(upgradedRisingTide.description).toContain("cannot redirect an ally-targeted cast");
expect(romEffectsForCast(upgradedRisingTide, context)).toContainEqual({
kind: "resource", resource: "psi", amount: 1,
});
expect(romEffectsForCast(upgradedRisingTide, context).find((effect) => (
effect.kind === "apply-aura" && effect.requiresCriticalHit
))).toBeDefined();
const warpCharge = pairAbilities.find((candidate) => candidate.dbcSpellId === 497958)!;
expect(learnedAbilityForBuild(warpCharge, 14, {})?.target).toBe("hostile");
const upgradedWarpCharge = learnedAbilityForBuild(warpCharge, 15, {})!;
expect(upgradedWarpCharge.target).toBe("any");
const friendlyEffects = romEffectsForCast(upgradedWarpCharge, {
...context,
selectedTargetRelationship: "friendly",
});
expect(friendlyEffects.some((effect) => effect.kind === "heal")).toBe(true);
expect(friendlyEffects.some((effect) => effect.kind === "damage")).toBe(false);
expect(romEffectsForCast(upgradedWarpCharge, {
...context,
selectedTargetRelationship: "hostile",
}).some((effect) => effect.kind === "damage")).toBe(true);
expect(romEffectsForCast(ability(491147), context)).toContainEqual({
kind: "resource", resource: "psi", amount: 1,
});
expect(ability(498633).description).toContain("12% Wisdom for 20 seconds");
expect(ability(498648).description).toContain("Ring of Comfort's reset chance is not specified");
});
it("applies Healing Fortune and Divine Assistance for the player and generated companion", () => {
prepareWarlock("rom-priest");
expect(useCombatStore.getState().auras.some((aura) => aura.sourceId === PLAYER_AURA_ENTITY_ID
&& aura.targetId === PLAYER_AURA_ENTITY_ID
&& aura.definition.id === "rom-warlock-divine-assistance-498668")).toBe(true);
registerTarget();
const psychicArrows = ability(497957);
expect(useCombatStore.getState().castAbility(psychicArrows.id, {
targetActorId: TARGET_ID,
now: 1_000,
}).ok).toBe(true);
finishCast(1_000);
expect(useCombatStore.getState().auras.some((aura) => aura.sourceId === PLAYER_AURA_ENTITY_ID
&& aura.targetId === PLAYER_AURA_ENTITY_ID
&& aura.definition.id === "rom-warlock-healing-fortune-498633")).toBe(true);
useCombatStore.getState().initializeCharacter({ classId: "rom-priest", raceId: "rom-dwarf", level: 80 });
usePartyStore.getState().initializeParty("rom-warlock-priest-companion", 80,
useCombatStore.getState().health, "damage", 2, "rom");
const companion = createConfiguredPartyMember({
name: "Warlock/Priest Companion",
classId: "rom-warlock",
secondaryClassId: "rom-priest",
raceId: "rom-dwarf",
specialization: "Warlock",
role: "damage",
}, 80, 0, "rom-warlock-priest-companion");
const pairAbilities = abilitiesForCharacter("rom-warlock", "rom-priest");
usePartyStore.setState({
command: "attack",
members: [{
...companion,
cooldowns: Object.fromEntries(pairAbilities
.filter((candidate) => candidate.dbcSpellId !== 497957)
.map((candidate) => [candidate.id, 100_000])),
resourcePools: { ...companion.resourcePools, focus: 100 },
resource: 100,
}],
});
useCombatStore.getState().synchronizeActors();
registerPartyRuntimePosition(companion.id, [0, 0, 0]);
registerTarget();
useCombatStore.getState().damageMob(TARGET_ID, 1, 900);
updatePartyRuntimeTargetVisibility(companion.id, TARGET_ID, true);
advanceDungeonPartyCombat(1_000);
advanceDungeonPartyCombat(3_100);
expect(useCombatStore.getState().auras.some((aura) => aura.sourceId === companion.id
&& aura.targetId === companion.id
&& aura.definition.id === "rom-warlock-divine-assistance-498668")).toBe(true);
expect(useCombatStore.getState().auras.some((aura) => aura.sourceId === companion.id
&& aura.targetId === companion.id
&& aura.definition.id === "rom-warlock-healing-fortune-498633")).toBe(true);
});
it("turns friendly Warp Charge into a heal for a Warlock/Priest player", () => {
prepareWarlock("rom-priest");
useCombatStore.setState((state) => ({
health: Math.max(1, state.maxHealth - 100),
}));
usePartyStore.getState().selectSelf();
const warpCharge = abilitiesForCharacter("rom-warlock", "rom-priest")
.find((candidate) => candidate.dbcSpellId === 497958)!;
const result = useCombatStore.getState().castAbility(warpCharge.id, {
now: 1_000,
});
expect(result.ok).toBe(true);
expect(useCombatStore.getState().health).toBeGreaterThan(useCombatStore.getState().maxHealth - 100);
});
it("applies the pair upgrade when the player casts Rising Tide", () => {
prepareWarlock("rom-priest");
registerTarget();
const risingTide = abilitiesForCharacter("rom-warlock", "rom-priest")
.find((candidate) => candidate.dbcSpellId === 490256)!;
expect(useCombatStore.getState().castAbility(risingTide.id, {
targetActorId: TARGET_ID,
now: 1_000,
}).ok).toBe(true);
expect(useCombatStore.getState().activeCast).toBeNull();
expect(useCombatStore.getState().resourcePools.psi).toBe(1);
expect(useCombatStore.getState().cooldowns[risingTide.id]).toBe(6_000);
});
it("consumes all Rage for Heart Fence and extends its duration by one second per 20 Rage", () => {