Release Healer Man 0.1.37
This commit is contained in:
1 parent
03a4e3f51c
commit
361734bc41
41 files changed
+1714
-110
No files matched your search
@@ -0,0 +1,78 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { useCombatStore } from "./combatStore";
|
||||
import { activateDungeonEncounterDefinitions, activeDungeonCompletedObjectiveIds, advanceDungeonEncounters, dispatchActiveDungeonEntityEvent, resetDungeonEncounters } from "./dungeonEncounterRuntime";
|
||||
import { requireDungeonDefinition } from "./dungeonRegistry";
|
||||
import { respawnDefeatedPlayer } from "./deathRespawn";
|
||||
import { availableResurrectionCheckpoints, dungeonResurrectionCheckpoints } from "./resurrectionCheckpoints";
|
||||
import { useGameStore } from "./store";
|
||||
|
||||
const dungeon = requireDungeonDefinition("stormwind-stockade");
|
||||
|
||||
describe("boss resurrection checkpoints", () => {
|
||||
beforeEach(() => {
|
||||
useGameStore.getState().activateDungeon("stormwind-stockade");
|
||||
activateDungeonEncounterDefinitions(dungeon.id, dungeon.encounters ?? []);
|
||||
resetDungeonEncounters("dungeon", dungeon.id);
|
||||
useCombatStore.getState().initializeCharacter({ classId: "priest", level: 16 });
|
||||
useCombatStore.setState({ mobs: {} });
|
||||
});
|
||||
|
||||
it("always offers the entrance and unlocks every killed boss, including optional bosses", () => {
|
||||
expect(dungeonResurrectionCheckpoints(dungeon, {})).toHaveLength(1);
|
||||
const result = dungeonResurrectionCheckpoints(dungeon, {}, dungeon.bosses.map((boss) => boss.id));
|
||||
expect(result.map((checkpoint) => checkpoint.id)).toEqual(["entrance", ...dungeon.bosses.map((boss) => `boss:${boss.id}`)]);
|
||||
dungeon.bosses.forEach((boss, index) => expect(result[index + 1].spawn.footPosition).toEqual(boss.position));
|
||||
});
|
||||
|
||||
it("uses durable encounter completion after hydration when no corpse is registered", () => {
|
||||
const boss = dungeon.bosses[0];
|
||||
dispatchActiveDungeonEntityEvent({ kind: "entity-death", entityId: boss.id, now: 100 });
|
||||
advanceDungeonEncounters(dungeon.id, { kind: "tick", now: 100, facts: { deadEntityIds: [boss.id], registeredEntityIds: [boss.id] } });
|
||||
expect(activeDungeonCompletedObjectiveIds(dungeon.id)).toContain(boss.id);
|
||||
expect(availableResurrectionCheckpoints().map((checkpoint) => checkpoint.id)).toContain(`boss:${boss.id}`);
|
||||
resetDungeonEncounters("boss-wipe", dungeon.id);
|
||||
expect(availableResurrectionCheckpoints().map((checkpoint) => checkpoint.id)).toContain(`boss:${boss.id}`);
|
||||
resetDungeonEncounters("dungeon", dungeon.id);
|
||||
expect(availableResurrectionCheckpoints()).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("does not award a checkpoint for an alive or script-despawned boss", () => {
|
||||
const boss = dungeon.bosses[0];
|
||||
useCombatStore.getState().registerMob(boss.id, { name: boss.name, maxHealth: 100, boss: true });
|
||||
expect(availableResurrectionCheckpoints()).toHaveLength(1);
|
||||
const mob = useCombatStore.getState().mobs[boss.id];
|
||||
useCombatStore.setState({ mobs: { [boss.id]: { ...mob, dead: true, health: 0, despawned: true } } });
|
||||
expect(availableResurrectionCheckpoints()).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("returns the defeated player and party reset signal to the selected boss, preserving the kill", () => {
|
||||
const boss = dungeon.bosses[0];
|
||||
useCombatStore.getState().registerMob(boss.id, { name: boss.name, maxHealth: 1, boss: true });
|
||||
useCombatStore.getState().damageMob(boss.id, 1, 100);
|
||||
useCombatStore.getState().damagePlayer(useCombatStore.getState().maxHealth * 10);
|
||||
const before = useGameStore.getState().resetRevision;
|
||||
expect(respawnDefeatedPlayer(`boss:${boss.id}`)).toBe(true);
|
||||
expect(useGameStore.getState().playerPosition).toEqual(boss.position);
|
||||
expect(useGameStore.getState().resetRevision).toBe(before + 1);
|
||||
expect(useCombatStore.getState().playerPosition).toEqual(boss.position);
|
||||
expect(useCombatStore.getState().health).toBe(useCombatStore.getState().maxHealth);
|
||||
expect(useCombatStore.getState().mobs[boss.id].dead).toBe(true);
|
||||
expect(availableResurrectionCheckpoints().map((checkpoint) => checkpoint.id)).toContain(`boss:${boss.id}`);
|
||||
});
|
||||
|
||||
it("lets a defeated player explicitly choose the entrance instead of a previously saved boss spawn", () => {
|
||||
useGameStore.setState({ activeSpawn: { footPosition: dungeon.bosses[0].position, yaw: 1 } });
|
||||
useCombatStore.getState().damagePlayer(useCombatStore.getState().maxHealth * 10);
|
||||
expect(respawnDefeatedPlayer("entrance")).toBe(true);
|
||||
expect(useGameStore.getState().playerPosition).toEqual(dungeon.entrance.footPosition);
|
||||
});
|
||||
|
||||
it("rejects locked boss choices and cannot teleport a living player", () => {
|
||||
const before = useGameStore.getState();
|
||||
expect(respawnDefeatedPlayer("entrance")).toBe(false);
|
||||
useCombatStore.getState().damagePlayer(useCombatStore.getState().maxHealth * 10);
|
||||
expect(respawnDefeatedPlayer(`boss:${dungeon.bosses[0].id}`)).toBe(false);
|
||||
expect(useCombatStore.getState().health).toBe(0);
|
||||
expect(useGameStore.getState()).toBe(before);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user