Files
healer-man/src/game/enemyAttacks.test.ts
T
2026-09-15 14:43:15 -04:00

94 lines
2.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
ENEMY_SLOW_MOVEMENT_MULTIPLIER,
enemyControlMovementMultiplier,
enemyControlPreventsActions,
enemyControlPreventsMovement,
normalizeEnemyAttack,
type EnemyAttackDefinition,
} from "./enemyAttacks";
function attack(overrides: Partial<EnemyAttackDefinition>): EnemyAttackDefinition {
return {
id: "test-special",
name: "Test Special",
delivery: "area",
target: "nearby-party",
school: "physical",
animation: "attack",
range: 12,
cooldownMs: 10_000,
damageMultiplier: 1,
...overrides,
};
}
describe("enemy attack telegraphs", () => {
it("infers a warned cone for legacy frontal mechanics", () => {
const normalized = normalizeEnemyAttack(attack({ name: "Stone Cleave" }));
expect(normalized.telegraph).toMatchObject({
shape: "cone",
anchor: "source",
warningMs: 1_650,
});
expect(normalized.castTimeMs).toBe(1_650);
});
it("preserves authored geometry and extends too-short cast warnings", () => {
const normalized = normalizeEnemyAttack(attack({
name: "Falling Ruin",
castTimeMs: 500,
telegraph: {
shape: "circle",
anchor: "target",
warningMs: 2_200,
radius: 7,
},
}));
expect(normalized.castTimeMs).toBe(2_200);
expect(normalized.telegraph).toEqual({
shape: "circle",
anchor: "target",
warningMs: 2_200,
radius: 7,
});
});
it("does not telegraph basic attacks or beneficial mechanics", () => {
expect(normalizeEnemyAttack(attack({ id: "basic-attack" })).telegraph).toBeUndefined();
expect(normalizeEnemyAttack(attack({
effect: { kind: "heal", multiplier: 1 },
})).telegraph).toBeUndefined();
expect(normalizeEnemyAttack(attack({
effect: {
kind: "composite",
effects: [{ kind: "summon", creatureEntry: 1, count: 1 }],
},
})).telegraph).toBeUndefined();
expect(normalizeEnemyAttack(attack({
effect: {
kind: "composite",
effects: [
{ kind: "damage", multiplier: 1 },
{ kind: "summon", creatureEntry: 1, count: 1 },
],
},
})).telegraph).toMatchObject({ shape: "circle" });
});
});
describe("enemy control movement", () => {
it("keeps slowed actors active while reducing movement", () => {
expect(enemyControlPreventsActions("slow")).toBe(false);
expect(enemyControlPreventsMovement("slow")).toBe(false);
expect(enemyControlMovementMultiplier("slow")).toBe(ENEMY_SLOW_MOVEMENT_MULTIPLIER);
});
it("keeps roots movement-only while preserving hard-control action locks", () => {
expect(enemyControlPreventsActions("root")).toBe(false);
expect(enemyControlPreventsMovement("root")).toBe(true);
expect(enemyControlMovementMultiplier("root")).toBe(1);
expect(enemyControlPreventsActions("stun")).toBe(true);
});
});