Files
healer-man/src/ui/PauseMenu.tsx
T
2026-08-14 15:56:39 -04:00

99 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useMemo } from "react";
import { useShellStore } from "../app/shellStore";
import { useGameStore } from "../game/store";
import { useMenuController, type MenuAction } from "../input/useMenuController";
import { ControllerButton } from "./ControllerButton";
function PauseDialog() {
const closeOverlay = useGameStore((state) => state.closeOverlay);
const openOverlay = useGameStore((state) => state.openOverlay);
const reset = useGameStore((state) => state.resetAtEntrance);
const gameMode = useGameStore((state) => state.gameMode);
const activeCharacter = useShellStore((state) => state.activeCharacter);
const returnToMainMenu = useShellStore((state) => state.returnToMainMenu);
const abandonManastormRun = useShellStore((state) => state.abandonManastormRun);
const resume = () => {
closeOverlay();
};
const returnToEntrance = () => {
reset();
};
const leaveDungeon = () => {
closeOverlay();
returnToMainMenu();
};
const abandonManastorm = () => {
closeOverlay();
abandonManastormRun();
};
const skillMenuLabel = activeCharacter?.categoryId === "rom" ? "Skills" : "Talents";
const actions = useMemo<MenuAction[]>(() => [
{ id: "pause-resume", run: resume },
{ id: "pause-party", run: () => openOverlay("party") },
{ id: "pause-inventory", run: () => openOverlay("inventory") },
{ id: "pause-map", run: () => openOverlay("map") },
{ id: "pause-spellbook", run: () => openOverlay("spellbook") },
{ id: "pause-bindings", run: () => openOverlay("bindings") },
{ id: "pause-talents", run: () => openOverlay("talents") },
{ id: "pause-options", run: () => openOverlay("options") },
...(gameMode === "manastorm"
? [{ id: "pause-abandon-manastorm", run: abandonManastorm }]
: [{ id: "pause-entrance", run: returnToEntrance }]),
{ id: "pause-main-menu", run: leaveDungeon },
], [abandonManastormRun, closeOverlay, gameMode, openOverlay, reset, returnToMainMenu]);
const controller = useMenuController(actions, { initialId: "pause-resume", onBack: resume });
const menuButton = (id: string, label: string, run: () => void, primary = false) => (
<ControllerButton
controlId={id}
selectedId={controller.selectedId}
select={controller.select}
type="button"
className={`button ${primary ? "button--primary" : ""}`}
onClick={run}
>{label}</ControllerButton>
);
return (
<div className="modal-backdrop" role="presentation">
<section className="pause-menu" role="dialog" aria-modal="true" aria-labelledby="pause-title">
<p className="eyebrow">Healer Man paused</p>
<h2 id="pause-title">The cavern waits.</h2>
<p>Resume play or open any character and system menu from this hub.</p>
<div className="pause-menu__actions">
{menuButton("pause-resume", "Resume expedition", resume, true)}
{menuButton("pause-party", "Party management", () => openOverlay("party"))}
{menuButton("pause-inventory", "Inventory & equipment", () => openOverlay("inventory"))}
{menuButton("pause-map", "Dungeon map", () => openOverlay("map"))}
{menuButton("pause-spellbook", "Spellbook", () => openOverlay("spellbook"))}
{menuButton("pause-bindings", "Ability controls", () => openOverlay("bindings"))}
{menuButton("pause-talents", skillMenuLabel, () => openOverlay("talents"))}
{menuButton("pause-options", "Options", () => openOverlay("options"))}
{gameMode === "manastorm"
? menuButton("pause-abandon-manastorm", "Abandon Manastorm run", abandonManastorm)
: menuButton("pause-entrance", "Return to entrance", returnToEntrance)}
{menuButton("pause-main-menu", "Return to main menu", leaveDungeon)}
</div>
<dl className="controls-list">
<div><dt>Move</dt><dd>WASD / Left stick</dd></div>
<div><dt>Look</dt><dd>Hold right mouse / Arrow keys / Right stick</dd></div>
<div><dt>Abilities</dt><dd>1–8 / Face, R1, R2, D-pad left/right</dd></div>
<div><dt>Ability layers</dt><dd>Shift / Alt / Hold L1 / Hold L2</dd></div>
<div><dt>Targets</dt><dd>Tab / R3 enemy · D-pad up/down party/self · L3 clear</dd></div>
<div><dt>Party orders</dt><dd>F1 Attack / F2 Defend / F3 Stop / F4 Recall</dd></div>
<div><dt>Spellbook / {skillMenuLabel}</dt><dd>P / N</dd></div>
<div><dt>Inventory / Loot</dt><dd>I / E</dd></div>
<div><dt>Pause</dt><dd>Escape / Start</dd></div>
</dl>
</section>
</div>
);
}
export function PauseMenu() {
const open = useGameStore((state) => state.overlay === "pause");
return open ? <PauseDialog /> : null;
}