Release Healer Man 0.1.14
This commit is contained in:
1 parent
67d7a8ebe7
commit
7b41b102fa
147 files changed
+169892
-1342
No files matched your search
@@ -0,0 +1,114 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { encounterTimeline } from "./encounterTimeline";
|
||||
import { useCombatStore } from "./combatStore";
|
||||
|
||||
describe("encounter mechanic timeline", () => {
|
||||
beforeEach(() => {
|
||||
useCombatStore.getState().initializeCharacter({ classId: "priest", level: 40 });
|
||||
useCombatStore.getState().registerMob("boss", {
|
||||
name: "Timeline Boss",
|
||||
boss: true,
|
||||
maxHealth: 1_000,
|
||||
attacks: [{
|
||||
id: "timed-quake",
|
||||
name: "Timed Quake",
|
||||
delivery: "area",
|
||||
target: "nearby-party",
|
||||
school: "nature",
|
||||
animation: "cast",
|
||||
range: 20,
|
||||
radius: 10,
|
||||
cooldownMs: 15_000,
|
||||
repeatCooldownMs: [12_000, 18_000],
|
||||
damageMultiplier: 1,
|
||||
}, {
|
||||
id: "health-adds",
|
||||
name: "Awaken Adds",
|
||||
delivery: "area",
|
||||
target: "self",
|
||||
school: "physical",
|
||||
animation: "cast",
|
||||
range: 0,
|
||||
cooldownMs: 1_000,
|
||||
maximumCasts: 1,
|
||||
damageMultiplier: 0,
|
||||
effect: { kind: "summon", creatureEntry: 1, count: 2 },
|
||||
condition: { kind: "self-health-percent", minimum: 0, maximum: 70 },
|
||||
}],
|
||||
});
|
||||
useCombatStore.setState((state) => ({
|
||||
mobs: {
|
||||
...state.mobs,
|
||||
boss: {
|
||||
...state.mobs.boss,
|
||||
engaged: true,
|
||||
abilityReadyAt: { "timed-quake": 16_000, "health-adds": 1_000 },
|
||||
},
|
||||
},
|
||||
}));
|
||||
});
|
||||
|
||||
it("shows both timer countdowns and pending health thresholds", () => {
|
||||
const model = encounterTimeline(useCombatStore.getState().mobs, 10_000);
|
||||
expect(model?.bossName).toBe("Timeline Boss");
|
||||
expect(model?.rows.map((row) => [row.name, row.kind, row.value])).toEqual([
|
||||
["Timed Quake", "timer", "6.0s"],
|
||||
["Awaken Adds", "health", "70% HP"],
|
||||
]);
|
||||
});
|
||||
|
||||
it("promotes an active cast and hides a completed one-shot threshold", () => {
|
||||
useCombatStore.setState((state) => ({
|
||||
mobs: {
|
||||
...state.mobs,
|
||||
boss: {
|
||||
...state.mobs.boss,
|
||||
abilityCastCounts: { "health-adds": 1 },
|
||||
activeCast: {
|
||||
attackId: "timed-quake",
|
||||
name: "Timed Quake",
|
||||
school: "nature",
|
||||
interruptible: true,
|
||||
targetActorId: "__player__",
|
||||
sourcePosition: [0, 0, 0],
|
||||
targetPosition: [0, 0, 5],
|
||||
sourceYaw: 0,
|
||||
startedAt: 10_000,
|
||||
completesAt: 12_000,
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
||||
expect(encounterTimeline(useCombatStore.getState().mobs, 11_250)?.rows).toMatchObject([{
|
||||
name: "Timed Quake",
|
||||
kind: "casting",
|
||||
value: "0.8s",
|
||||
}]);
|
||||
});
|
||||
|
||||
it("keeps every pending health threshold visible beyond the countdown row limit", () => {
|
||||
const boss = useCombatStore.getState().mobs.boss;
|
||||
const extraTimers = Array.from({ length: 5 }, (_, index) => ({
|
||||
...boss.attacks[0],
|
||||
id: `extra-timer-${index}`,
|
||||
name: `Extra Timer ${index}`,
|
||||
}));
|
||||
useCombatStore.setState((state) => ({
|
||||
mobs: {
|
||||
...state.mobs,
|
||||
boss: {
|
||||
...state.mobs.boss,
|
||||
attacks: [...state.mobs.boss.attacks, ...extraTimers],
|
||||
abilityReadyAt: {
|
||||
...state.mobs.boss.abilityReadyAt,
|
||||
...Object.fromEntries(extraTimers.map((attack, index) => [attack.id, 11_000 + index * 1_000])),
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
const rows = encounterTimeline(useCombatStore.getState().mobs, 10_000, 4)?.rows ?? [];
|
||||
expect(rows.filter((row) => row.kind === "timer")).toHaveLength(4);
|
||||
expect(rows.filter((row) => row.kind === "health").map((row) => row.value)).toEqual(["70% HP"]);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user