Update Healer Man server
This commit is contained in:
1 parent
4c768fbec6
commit
b16821e92e
330 files changed
+35406
-1760
No files matched your search
@@ -0,0 +1,138 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { ROM_ALL_ABILITIES, ROM_ELITE_ABILITIES } from "./romAbilityCatalog";
|
||||
import { channelAmountEffects, channelPulseAt, channelPulseCount } from "./combatChannelAmounts";
|
||||
import { romAbilityRequiredTargetStateTag, romEffectsForCast, type RomCastMechanics } from "./romCombatMechanics";
|
||||
import { ROM_DRUID_ROGUE_CORROSIVE_POISON_TAG } from "./romDruidRogueCurrentCoa";
|
||||
|
||||
const empty: RomCastMechanics = {
|
||||
sealStacks: 0,
|
||||
bleedCount: 0,
|
||||
charged: false,
|
||||
mainHandDagger: false,
|
||||
casterMaxHealth: 10_000,
|
||||
targetHealthPercent: 1,
|
||||
};
|
||||
|
||||
function ability(spellId: number) {
|
||||
const found = ROM_ALL_ABILITIES.find((entry) => entry.dbcSpellId === spellId
|
||||
&& entry.classId === "rom-druid" && entry.secondaryClassId === "rom-rogue");
|
||||
expect(found, `Druid/Rogue ability ${spellId}`).toBeDefined();
|
||||
return found!;
|
||||
}
|
||||
|
||||
describe("current CoA Druid/Rogue Necrotic Wound profile", () => {
|
||||
it("uses the sourced gate, costs, channel, range, radius, and three full per-hit values", () => {
|
||||
const wound = ability(494321);
|
||||
expect(wound).toMatchObject({
|
||||
name: "Necrotic Wound",
|
||||
target: "hostile",
|
||||
range: { min: 0, max: 15 },
|
||||
radius: 8,
|
||||
targeting: { shape: "circle", radius: 8 },
|
||||
castMode: "channel",
|
||||
castTimeMs: 1_500,
|
||||
channelPulses: 3,
|
||||
channelTickMs: 500,
|
||||
cooldownMs: 0,
|
||||
costs: [
|
||||
{ resource: "mana", amount: 4, percentage: true },
|
||||
{ resource: "nature-power", amount: 1 },
|
||||
],
|
||||
});
|
||||
expect(romAbilityRequiredTargetStateTag(wound)).toBe(ROM_DRUID_ROGUE_CORROSIVE_POISON_TAG);
|
||||
expect(romEffectsForCast(wound, { ...empty, naturePower: 1 })).toEqual([]);
|
||||
|
||||
const currentEffects = romEffectsForCast(wound, {
|
||||
...empty,
|
||||
naturePower: 1,
|
||||
targetTags: [ROM_DRUID_ROGUE_CORROSIVE_POISON_TAG],
|
||||
});
|
||||
expect(currentEffects.filter((effect) => effect.kind === "apply-aura"
|
||||
&& effect.aura.modifiers?.some((modifier) => modifier.kind === "healing" && modifier.direction === "taken")))
|
||||
.toHaveLength(0);
|
||||
expect(currentEffects.filter((effect) => effect.kind === "apply-aura" && effect.control?.kind === "root"))
|
||||
.toHaveLength(0);
|
||||
expect(currentEffects.filter((effect) => effect.kind === "damage"))
|
||||
.toEqual([{ kind: "damage", coefficient: 3.297, school: "shadow" }]);
|
||||
expect(currentEffects.filter((effect) => effect.kind === "utility" && effect.action === "class-script"))
|
||||
.toEqual([expect.objectContaining({ triggerSpellId: 494024, durationMs: 12_000 })]);
|
||||
expect(currentEffects.filter((effect) => effect.kind === "cooldown-reset"))
|
||||
.toEqual([{ kind: "cooldown-reset", mode: "reduce", abilityName: "Sinister Request", amountMs: 1_000 }]);
|
||||
|
||||
const channelAmounts = channelAmountEffects(wound, 3);
|
||||
expect(channelAmounts).toEqual([{ effect: currentEffects.find((effect) => effect.kind === "damage"), multiplier: 1 }]);
|
||||
expect(channelPulseCount(wound)).toBe(3);
|
||||
expect([0, 1, 2].map((pulse) => channelPulseAt(wound, 1_000, 1_500, pulse)))
|
||||
.toEqual([1_500, 2_000, 2_500]);
|
||||
});
|
||||
|
||||
it("replaces Corrosive Poison with the current +105, one-second Dark DoT and adds the spread prerequisite", () => {
|
||||
const poison = ability(494024);
|
||||
const dot = poison.effects.find((effect) => effect.kind === "dot");
|
||||
expect(poison).toMatchObject({
|
||||
range: { max: 15 },
|
||||
castMode: "instant",
|
||||
castTimeMs: 0,
|
||||
cooldownMs: 1_000,
|
||||
costs: [{ resource: "energy", amount: 25 }],
|
||||
});
|
||||
expect(dot).toMatchObject({
|
||||
kind: "dot",
|
||||
school: "shadow",
|
||||
basePoints: 11_342,
|
||||
sourceLevel: 105,
|
||||
ticks: 12,
|
||||
intervalMs: 1_000,
|
||||
tag: ROM_DRUID_ROGUE_CORROSIVE_POISON_TAG,
|
||||
});
|
||||
});
|
||||
|
||||
it("adds the exact one-second cooldown rider to both successful casts", () => {
|
||||
const cooldownRiders = [494022, 494321].map((spellId) => romEffectsForCast(ability(spellId), {
|
||||
...empty,
|
||||
naturePower: 1,
|
||||
targetTags: spellId === 494321 ? [ROM_DRUID_ROGUE_CORROSIVE_POISON_TAG] : [],
|
||||
}).filter((effect) => effect.kind === "cooldown-reset"));
|
||||
expect(cooldownRiders).toEqual([
|
||||
[{ kind: "cooldown-reset", mode: "reduce", abilityName: "Sinister Request", amountMs: 1_000 }],
|
||||
[{ kind: "cooldown-reset", mode: "reduce", abilityName: "Sinister Request", amountMs: 1_000 }],
|
||||
]);
|
||||
|
||||
const kneeUlcer = ROM_ELITE_ABILITIES.find((entry) => entry.dbcSpellId === 499944);
|
||||
expect(kneeUlcer).toBeDefined();
|
||||
const passiveTag = kneeUlcer!.effects.find((effect) => effect.kind === "apply-aura");
|
||||
expect(passiveTag?.kind).toBe("apply-aura");
|
||||
const withObsoletePassive = romEffectsForCast(ability(494321), {
|
||||
...empty,
|
||||
naturePower: 1,
|
||||
targetTags: [ROM_DRUID_ROGUE_CORROSIVE_POISON_TAG],
|
||||
passiveTags: passiveTag?.kind === "apply-aura" ? passiveTag.aura.utilityTags : [],
|
||||
});
|
||||
expect(withObsoletePassive.some((effect) => effect.kind === "apply-aura" && effect.control?.kind === "root"))
|
||||
.toBe(false);
|
||||
});
|
||||
|
||||
it("uses the current Sinister Request identity and does not leak the old Speed Catalysis aura", () => {
|
||||
const request = ability(494023);
|
||||
expect(request).toMatchObject({
|
||||
name: "Sinister Request",
|
||||
target: "self",
|
||||
range: { max: 5 },
|
||||
radius: 15,
|
||||
cooldownMs: 15_000,
|
||||
costs: [],
|
||||
effects: expect.arrayContaining([
|
||||
{ kind: "resource", amount: 100, resource: "mana", percentage: true, scope: "party" },
|
||||
{ kind: "resource", amount: 100, resource: "rage", percentage: true, scope: "party" },
|
||||
{ kind: "resource", amount: 100, resource: "focus", percentage: true, scope: "party" },
|
||||
{ kind: "resource", amount: 100, resource: "energy", percentage: true, scope: "party" },
|
||||
{ kind: "resource", amount: 100, resource: "psi", percentage: true, scope: "party" },
|
||||
{ kind: "resource", amount: 100, resource: "nature-power", percentage: true, scope: "party" },
|
||||
]),
|
||||
});
|
||||
expect(request.description).toContain("restores the MP, Rage, Focus, Energy, Psi, and Nature's Power");
|
||||
expect(request.description).toContain("within radius 150");
|
||||
expect(request.description).toContain("Cooldown: 15 seconds");
|
||||
expect(request.description).not.toContain("attack and casting speed");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user