forked from phenom/healer-man
Update Healer Man server
This commit is contained in:
1 parent
9d7e0e2f9e
commit
35dfdaed61
94 files changed
+17034
-418
No files matched your search
@@ -0,0 +1,107 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { abilityById } from "./abilityCatalog";
|
||||
import { PLAYER_AGGRO_ID } from "./aggro";
|
||||
import { EMPTY_ITEM_STATS } from "./itemStats";
|
||||
import { clearMobRuntimeRegistry, setMobPosition } from "./mobRuntimeRegistry";
|
||||
import { resolveDamageValue, resolveStatValue } from "./combatAuras";
|
||||
import { useCombatStore } from "./combatStore";
|
||||
|
||||
describe("RoM Scout ranged weapon masteries", () => {
|
||||
beforeEach(() => {
|
||||
clearMobRuntimeRegistry();
|
||||
});
|
||||
|
||||
it.each(["bow", "crossbow"] as const)(
|
||||
"applies Ranged Weapon Mastery and Speed Shooting Mastery once with an equipped %s",
|
||||
(weaponType) => {
|
||||
const rangedWeapon = {
|
||||
instanceId: `scout-mastery-${weaponType}`,
|
||||
itemId: 1,
|
||||
itemKey: `scout-mastery-${weaponType}`,
|
||||
name: `Test ${weaponType}`,
|
||||
quality: "uncommon" as const,
|
||||
inventorySlot: "ranged",
|
||||
armorType: null,
|
||||
weaponType,
|
||||
itemLevel: 1,
|
||||
sourceItemLevel: 1,
|
||||
stats: EMPTY_ITEM_STATS,
|
||||
quantity: 1,
|
||||
sourceBossKey: "test",
|
||||
sourceBossName: "test",
|
||||
acquiredAt: 1,
|
||||
};
|
||||
useCombatStore.getState().initializeCharacter({
|
||||
classId: "rom-scout",
|
||||
raceId: "rom-human",
|
||||
level: 50,
|
||||
inventory: [rangedWeapon],
|
||||
equipment: { player: { ranged: rangedWeapon.instanceId } },
|
||||
});
|
||||
|
||||
const state = useCombatStore.getState();
|
||||
expect(state.equipment.player?.ranged).toBe(rangedWeapon.instanceId);
|
||||
const playerAuras = state.auras.filter((aura) => aura.targetId === PLAYER_AGGRO_ID);
|
||||
const rangedDamageAuras = playerAuras.filter((aura) => aura.definition.modifiers?.some((modifier) => (
|
||||
modifier.kind === "damage"
|
||||
&& modifier.direction === "dealt"
|
||||
&& modifier.attackKind === "ranged"
|
||||
&& modifier.operation === "percent"
|
||||
)));
|
||||
|
||||
expect(rangedDamageAuras).toHaveLength(1);
|
||||
expect(resolveDamageValue(100, playerAuras, { direction: "dealt", school: "physical", attackKind: "ranged" }))
|
||||
.toBeCloseTo(108);
|
||||
expect(resolveStatValue(0, playerAuras, "ranged-hit")).toBe(8);
|
||||
expect(resolveStatValue(0, playerAuras, "physical-hit")).toBe(0);
|
||||
expect(resolveStatValue(0, playerAuras, "ranged-haste")).toBe(11);
|
||||
|
||||
const masteryDamageModifiers = abilityById("rom-scout-primary-2")!.effects.flatMap((effect) => (
|
||||
effect.kind === "apply-aura" ? effect.aura.modifiers ?? [] : []
|
||||
)).filter((modifier) => modifier.kind === "damage"
|
||||
&& modifier.direction === "dealt"
|
||||
&& modifier.attackKind === "ranged"
|
||||
&& modifier.operation === "percent");
|
||||
const speedMasteryModifiers = abilityById("rom-scout-general-8")!.effects.flatMap((effect) => (
|
||||
effect.kind === "apply-aura" ? effect.aura.modifiers ?? [] : []
|
||||
)).filter((modifier) => modifier.kind === "stat" && modifier.stat === "ranged-haste");
|
||||
expect(masteryDamageModifiers).toHaveLength(1);
|
||||
expect(speedMasteryModifiers).toHaveLength(1);
|
||||
},
|
||||
);
|
||||
|
||||
it("Cripple Joint roots on Joint Blow hits, not on other Scout attacks", () => {
|
||||
useCombatStore.getState().initializeCharacter({
|
||||
classId: "rom-scout",
|
||||
raceId: "rom-human",
|
||||
level: 50,
|
||||
});
|
||||
for (const id of ["shot-target", "joint-target"]) {
|
||||
useCombatStore.getState().registerMob(id, { name: id, maxHealth: 1_000_000 });
|
||||
setMobPosition(id, [3, 0, 0]);
|
||||
}
|
||||
|
||||
// Make the proc deterministic here; its catalog regression separately checks the sourced 55% chance.
|
||||
useCombatStore.setState((state) => ({
|
||||
auras: state.auras.map((aura) => aura.definition.utilityTags?.includes("rom-cripple-joint")
|
||||
? {
|
||||
...aura,
|
||||
definition: {
|
||||
...aura.definition,
|
||||
procs: aura.definition.procs?.map((proc) => ({ ...proc, chance: 1 })),
|
||||
},
|
||||
}
|
||||
: aura),
|
||||
}));
|
||||
|
||||
useCombatStore.getState().selectMob("shot-target");
|
||||
expect(useCombatStore.getState().castAbility("rom-scout-general-0", undefined, 1_000)).toMatchObject({ ok: true });
|
||||
expect(useCombatStore.getState().mobs["shot-target"]?.statuses.some((status) => status.kind === "root")).toBe(false);
|
||||
|
||||
useCombatStore.getState().selectMob("joint-target");
|
||||
expect(useCombatStore.getState().castAbility("rom-scout-general-3", undefined, 2_600)).toMatchObject({ ok: true });
|
||||
expect(useCombatStore.getState().mobs["joint-target"]?.statuses).toEqual(expect.arrayContaining([
|
||||
expect.objectContaining({ kind: "root", endsAt: 7_600, sourceAbilityId: "rom-scout-general-3" }),
|
||||
]));
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user