Update Healer Man server

This commit is contained in:
phenom committed 2026-09-30 09:57:13 -04:00
1 parent 35dfdaed61
commit 4fb7a0b9c8
161 files changed
+24618 -529

No files matched your search

+244 -1
View File
@@ -1,10 +1,11 @@
import { beforeEach, describe, expect, it } from "vitest";
import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry";
import { clearPartyRuntimeRegistry, updatePartyRuntimePosition } from "./partyRuntimeRegistry";
import { PLAYER_AURA_ENTITY_ID, useCombatStore } from "./combatStore";
import { characterCombatDefender, PLAYER_AURA_ENTITY_ID, useCombatStore } from "./combatStore";
import { usePartyStore } from "./partyStore";
import { abilityTalentNodeId, preloadAbilityCatalogsForClasses } from "./abilityCatalog";
import { applyAura } from "./combatAuras";
import { EMPTY_ITEM_STATS } from "./itemStats";
import { WOW335_TALENT_NODES } from "./wow335Talents.generated";
function abilityId(name: string): string {
@@ -97,6 +98,81 @@ describe("WoW 3.3.5 Paladin source-backed runtime mechanics", () => {
expect(useCombatStore.getState().controlledUntil).toBe(14_450);
});
it("makes Aura Mastery immune to incoming interrupts while a spell is casting", () => {
const mobId = "paladin-aura-mastery-interrupt";
useCombatStore.getState().registerMob(mobId, {
name: "Interrupt attacker",
maxHealth: 10_000,
attacks: [{
id: "interrupt",
name: "Interrupt",
delivery: "area",
target: "primary",
school: "shadow",
animation: "cast",
castTimeMs: 0,
range: 30,
cooldownMs: 10_000,
initialCooldownMs: [0, 0],
repeatCooldownMs: [10_000, 10_000],
damageMultiplier: 0,
effect: { kind: "control", mechanic: "interrupt", durationMs: 3_000 },
}],
});
setMobPosition(mobId, [2, 0, 0]);
useCombatStore.getState().selectMob(mobId);
useCombatStore.getState().damageMob(mobId, 1, 1_000);
const activate = useCombatStore.getState().castAbility(unlockTalentAbility("Aura Mastery"), undefined, 1_000);
expect(activate).toMatchObject({ ok: true });
const playerAura = useCombatStore.getState().auras.find((aura) => (
aura.targetId === PLAYER_AURA_ENTITY_ID
&& aura.definition.controlImmunities?.includes("interrupt")
));
expect(playerAura).toBeDefined();
const member = usePartyStore.getState().members[0]!;
updatePartyRuntimePosition(member.id, 4, 0, 0);
useCombatStore.getState().synchronizeActors();
const holyLight = useCombatStore.getState().castAbility(abilityId("Holy Light"), {
targetActorId: member.id,
now: 2_500,
});
expect(holyLight).toMatchObject({ ok: true });
expect(useCombatStore.getState().activeCast).not.toBeNull();
useCombatStore.getState().advanceMobCombat(2_600);
expect(useCombatStore.getState().controlMechanic).toBeNull();
expect(useCombatStore.getState().activeCast).not.toBeNull();
});
it("doubles the active Paladin aura on each Aura Mastery recipient for the generated spell duration", () => {
const armor = () => characterCombatDefender(useCombatStore.getState()).armor ?? 0;
const baseArmor = armor();
expect(useCombatStore.getState().castAbility(abilityId("Devotion Aura"), undefined, 1_000))
.toMatchObject({ ok: true });
expect(armor() - baseArmor).toBe(1_205);
const mastery = useCombatStore.getState().castAbility(
unlockTalentAbility("Aura Mastery"),
undefined,
2_500,
);
expect(mastery).toMatchObject({ ok: true });
const partyMember = usePartyStore.getState().members[0]!;
const masteryAuras = useCombatStore.getState().auras.filter((aura) => (
aura.definition.utilityTags?.includes("wow335-aura-mastery-aura-effectiveness")
));
for (const targetId of [PLAYER_AURA_ENTITY_ID, partyMember.id]) {
expect(masteryAuras.some((aura) => aura.targetId === targetId && aura.expiresAt === 12_500)).toBe(true);
}
expect(armor() - baseArmor).toBe(2_410);
useCombatStore.getState().tick(0.1, 12_501);
expect(armor() - baseArmor).toBe(1_205);
});
it("lets Redemption target and revive a defeated party member at the rank's source health", () => {
const member = usePartyStore.getState().members[0]!;
usePartyStore.setState((party) => ({
@@ -162,6 +238,173 @@ describe("WoW 3.3.5 Paladin source-backed runtime mechanics", () => {
expect(result).toMatchObject({ ok: false, reason: "condition-not-met" });
});
it("adds Redoubt's generated shield block chance only while a shield is equipped", () => {
setTalentRank("Redoubt", 2);
const withoutShield = characterCombatDefender(useCombatStore.getState()).blockPercent ?? 0;
const shieldId = "paladin-redoubt-block-test";
const shield = {
instanceId: shieldId,
itemId: 1,
itemKey: shieldId,
name: "Redoubt Test Shield",
quality: "uncommon" as const,
inventorySlot: "off-hand",
armorType: "shield",
weaponType: null,
itemLevel: 1,
sourceItemLevel: 1,
stats: { ...EMPTY_ITEM_STATS, blockValue: 40 },
quantity: 1,
sourceBossKey: "test",
sourceBossName: "Test",
acquiredAt: 1,
};
useCombatStore.setState((state) => ({
inventory: [shield],
equipment: { player: { "off-hand": shieldId } },
gearStats: { ...state.gearStats, blockValue: 40 },
}));
const withShield = characterCombatDefender(useCombatStore.getState()).blockPercent ?? 0;
expect(withShield - withoutShield).toBe(12);
});
it("procs Redoubt from a shield block with the generated rank values and duration", () => {
setTalentRank("Redoubt", 3);
const shieldId = "paladin-redoubt-proc-test";
const shield = {
instanceId: shieldId,
itemId: 1,
itemKey: shieldId,
name: "Redoubt Proc Shield",
quality: "uncommon" as const,
inventorySlot: "off-hand",
armorType: "shield",
weaponType: null,
itemLevel: 1,
sourceItemLevel: 1,
stats: { ...EMPTY_ITEM_STATS, blockRating: 1_000_000, blockValue: 40 },
quantity: 1,
sourceBossKey: "test",
sourceBossName: "Test",
acquiredAt: 1,
};
useCombatStore.setState((state) => ({
inventory: [shield],
equipment: { player: { "off-hand": shieldId } },
gearStats: { ...state.gearStats, blockRating: 1_000_000, blockValue: 40 },
}));
const mobId = "paladin-redoubt-proc-attacker";
useCombatStore.getState().registerMob(mobId, {
name: "Redoubt attacker",
level: 80,
maxHealth: 100_000,
attacks: [{
id: "redoubt-proc-melee",
name: "Melee attack",
delivery: "melee",
target: "primary",
school: "physical",
animation: "attack",
castTimeMs: 0,
range: 8,
cooldownMs: 500,
initialCooldownMs: [0, 0],
repeatCooldownMs: [500, 500],
damageMultiplier: 0.1,
}],
});
setMobPosition(mobId, [2, 0, 0]);
useCombatStore.getState().damageMob(mobId, 1, 1_000);
let redoubt = undefined as ReturnType<typeof useCombatStore.getState>["auras"][number] | undefined;
for (let now = 1_450; now <= 30_000; now += 250) {
useCombatStore.getState().advanceMobCombat(now);
redoubt = useCombatStore.getState().auras.find((aura) => (
aura.targetId === PLAYER_AURA_ENTITY_ID
&& aura.definition.utilityTags?.includes("wow335-paladin-redoubt")
));
if (redoubt) break;
}
expect(useCombatStore.getState().combatEvents.some((event) => (
event.kind === "damage" && event.targetActorId === PLAYER_AURA_ENTITY_ID && event.outcome === "block"
))).toBe(true);
expect(redoubt).toBeDefined();
expect(redoubt?.expiresAt).toBe(redoubt!.appliedAt + 10_000);
expect(redoubt?.definition.modifiers).toContainEqual({
kind: "damage", direction: "taken", operation: "percent", value: -0.06,
});
expect(redoubt?.definition.modifiers).toContainEqual({
kind: "stat", stat: "strength", operation: "percent", value: 0.1,
});
});
it("spends Holy Shield's eight source-defined charges on successful blocks", () => {
const shieldId = "paladin-holy-shield-charge-test";
const shield = {
instanceId: shieldId,
itemId: 1,
itemKey: shieldId,
name: "Test Shield",
quality: "uncommon" as const,
inventorySlot: "off-hand",
armorType: "shield",
weaponType: null,
itemLevel: 1,
sourceItemLevel: 1,
stats: { ...EMPTY_ITEM_STATS, blockRating: 1_000_000, blockValue: 40 },
quantity: 1,
sourceBossKey: "test",
sourceBossName: "Test",
acquiredAt: 1,
};
useCombatStore.setState((state) => ({
inventory: [shield],
equipment: { player: { "off-hand": shieldId } },
gearStats: { ...state.gearStats, blockRating: 1_000_000, blockValue: 40 },
}));
const targetId = "paladin-holy-shield-charge-target";
useCombatStore.getState().registerMob(targetId, {
name: "Melee attacker",
level: 80,
maxHealth: 100_000,
attacks: [{
id: "holy-shield-charge-melee",
name: "Melee attack",
delivery: "melee",
target: "primary",
school: "physical",
animation: "attack",
castTimeMs: 0,
range: 8,
cooldownMs: 500,
initialCooldownMs: [0, 0],
repeatCooldownMs: [500, 500],
damageMultiplier: 0.1,
}],
});
setMobPosition(targetId, [2, 0, 0]);
useCombatStore.getState().damageMob(targetId, 1, 1_000);
const holyShieldId = unlockTalentAbility("Holy Shield");
const cast = useCombatStore.getState().castAbility(holyShieldId, undefined, 1_000);
expect(cast, JSON.stringify(cast)).toMatchObject({ ok: true });
const findHolyShieldProc = () => useCombatStore.getState().auras.find((aura) => (
aura.targetId === PLAYER_AURA_ENTITY_ID
&& aura.definition.procs?.some((proc) => proc.id.endsWith(":holy-shield"))
));
expect(findHolyShieldProc()?.procStates[0]?.remainingCharges).toBe(8);
for (let now = 1_450; now <= 10_000; now += 250) {
useCombatStore.getState().advanceMobCombat(now);
if (findHolyShieldProc()?.procStates[0]?.remainingCharges === 0) break;
}
expect(findHolyShieldProc()?.procStates[0]?.remainingCharges).toBe(0);
});
it("procs three 8-second Reckoning charges from melee hits and adds one landed autoattack per charge", () => {
setTalentRank("Reckoning", 5);
const mobId = "paladin-reckoning-trigger";