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

@@ -0,0 +1,155 @@
import { beforeEach, describe, expect, it } from "vitest";
import { PLAYER_AGGRO_ID } from "./aggro";
import { useCombatStore, stableCombatUnit } from "./combatStore";
import { DEFAULT_ENEMY_ATTACK } from "./enemyAttacks";
import { EMPTY_ITEM_STATS } from "./itemStats";
import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry";
import { clearPartyRuntimeRegistry, registerPartyRuntimePosition } from "./partyRuntimeRegistry";
import { createConfiguredPartyMember, usePartyStore } from "./partyStore";
import { advanceDungeonPartyCombat, resetPartyRuntimeClock } from "./partyRuntime";
import {
WOW335_PALADIN_TOUCHED_BY_THE_LIGHT_TALENT_ID,
WOW335_WARRIOR_CRITICAL_BLOCK_TALENT_ID,
} from "./wow335WarriorCriticalBlockRuntime";
const SWING = {
...DEFAULT_ENEMY_ATTACK,
id: "critical-block-test-swing",
name: "Critical Block Test Swing",
cooldownMs: 10_000,
initialCooldownMs: [0, 0] as const,
repeatCooldownMs: [10_000, 10_000] as const,
damageMultiplier: 1,
};
function timeForBlock(mobId: string, actorId: string): number {
for (let now = 1_000; now < 200_000; now += 1) {
const roll = stableCombatUnit(`${mobId}:${SWING.id}:${actorId}:0:${now}:outcome`);
if (roll >= 0.2 && roll < 0.9) return now;
}
throw new Error("Could not find a stable Critical Block test roll.");
}
function registerAttacker(mobId: string, targetActorId: string, now: number): void {
useCombatStore.getState().registerMob(mobId, {
name: mobId,
level: 80,
maxHealth: 100_000,
xpReward: 0,
attacks: [SWING],
});
setMobPosition(mobId, [2, 0, 0]);
useCombatStore.getState().damageMob(mobId, 1, now - 1, {
actorId: targetActorId,
role: "tank",
}, "physical");
}
function incomingEvent(mobId: string, targetActorId: string) {
const event = useCombatStore.getState().combatEvents.find((candidate) => (
candidate.kind === "damage"
&& candidate.sourceActorId === mobId
&& candidate.targetActorId === targetActorId
));
if (!event) throw new Error(`Expected a recorded incoming hit on ${targetActorId}.`);
return event;
}
function runPlayerBlock(
rank: number,
options: { readonly attackerIsPlayer?: boolean; readonly touchedByTheLightRank?: number } = {},
) {
clearMobRuntimeRegistry();
useCombatStore.getState().initializeCharacter({ classId: "warrior", level: 80, role: "tank" });
useCombatStore.setState((state) => ({
health: 100_000,
maxHealth: 100_000,
gearStats: { ...EMPTY_ITEM_STATS, blockRating: 1_000_000, blockValue: 100 },
talentRanks: {
...state.talentRanks,
[WOW335_WARRIOR_CRITICAL_BLOCK_TALENT_ID]: rank,
[WOW335_PALADIN_TOUCHED_BY_THE_LIGHT_TALENT_ID]: options.touchedByTheLightRank ?? 0,
},
}));
const mobId = "critical-block-player-attacker";
const now = timeForBlock(mobId, PLAYER_AGGRO_ID);
registerAttacker(mobId, PLAYER_AGGRO_ID, now);
if (options.attackerIsPlayer) {
useCombatStore.setState((state) => ({
mobs: {
...state.mobs,
[mobId]: { ...state.mobs[mobId]!, characterDefender: { level: 80 } },
},
}));
}
useCombatStore.getState().advanceMobCombat(now);
return incomingEvent(mobId, PLAYER_AGGRO_ID);
}
function runPartyBlock(rank: number) {
clearMobRuntimeRegistry();
clearPartyRuntimeRegistry();
resetPartyRuntimeClock();
useCombatStore.getState().initializeCharacter({ classId: "mage", level: 80 });
const partyId = "critical-block-party";
usePartyStore.getState().initializeParty(partyId, 80, useCombatStore.getState().health, "damage", 1);
const warrior = createConfiguredPartyMember({
name: "Critical Block Warrior",
classId: "warrior",
specialization: "Protection",
specializationId: "warrior:protection",
talentTreeId: "warrior-protection",
talentRanks: { [WOW335_WARRIOR_CRITICAL_BLOCK_TALENT_ID]: rank },
role: "tank",
}, 80, 0, partyId);
usePartyStore.setState({
members: [{
...warrior,
gearStats: { ...EMPTY_ITEM_STATS, blockRating: 1_000_000, blockValue: 100 },
}],
});
registerPartyRuntimePosition(warrior.id, [0, 0, 0]);
useCombatStore.getState().synchronizeActors();
const mobId = "critical-block-party-attacker";
const now = timeForBlock(mobId, warrior.id);
registerAttacker(mobId, warrior.id, now);
advanceDungeonPartyCombat(now);
useCombatStore.getState().advanceMobCombat(now);
return incomingEvent(mobId, warrior.id);
}
describe("WoW Warrior Critical Block runtime integration", () => {
beforeEach(() => {
clearMobRuntimeRegistry();
clearPartyRuntimeRegistry();
resetPartyRuntimeClock();
useCombatStore.getState().initializeCharacter({ classId: "mage", level: 80 });
usePartyStore.getState().initializeParty("critical-block-tests", 80, useCombatStore.getState().health, "damage", 1);
});
it("reduces successful player and generated companion blocks by the generated rank-3 25%", () => {
const playerRank0 = runPlayerBlock(0);
const playerRank3 = runPlayerBlock(3);
expect(playerRank0.outcome).toBe("block");
expect(playerRank3.outcome).toBe("block");
expect(playerRank3.effectiveAmount).toBe(Math.round(playerRank0.effectiveAmount * 0.75));
const partyRank0 = runPartyBlock(0);
const partyRank3 = runPartyBlock(3);
expect(partyRank0.outcome).toBe("block");
expect(partyRank3.outcome).toBe("block");
expect(partyRank3.effectiveAmount).toBe(Math.round(partyRank0.effectiveAmount * 0.75));
});
it("keeps the generated rank-3 block reduction disabled against player attackers and with Touched by the Light", () => {
const ordinary = runPlayerBlock(0);
expect(runPlayerBlock(3, { attackerIsPlayer: true })).toMatchObject({
outcome: "block",
effectiveAmount: ordinary.effectiveAmount,
});
expect(runPlayerBlock(3, { touchedByTheLightRank: 1 })).toMatchObject({
outcome: "block",
effectiveAmount: ordinary.effectiveAmount,
});
});
});