38 lines
1.4 KiB
TypeScript
38 lines
1.4 KiB
TypeScript
import { useMemo } from "react";
|
|
import { encounterTimeline } from "../game/encounterTimeline";
|
|
import { useCombatStore } from "../game/combatStore";
|
|
|
|
function mechanicGlyph(shape: "circle" | "cone" | "line" | undefined): string {
|
|
if (shape === "cone") return "◢";
|
|
if (shape === "line") return "▰";
|
|
if (shape === "circle") return "●";
|
|
return "◆";
|
|
}
|
|
|
|
export function EncounterTimeline({ now }: { readonly now: number }) {
|
|
const mobs = useCombatStore((state) => state.mobs);
|
|
const model = useMemo(() => encounterTimeline(mobs, now), [mobs, now]);
|
|
if (!model) return null;
|
|
return (
|
|
<section className="encounter-timeline" aria-label={`${model.bossName} mechanic timeline`}>
|
|
<header><span>Mechanics</span><strong>{model.bossName}</strong></header>
|
|
<div className="encounter-timeline__rows">
|
|
{model.rows.map((row) => (
|
|
<div
|
|
key={row.id}
|
|
className={`encounter-timeline__row encounter-timeline__row--${row.kind}`}
|
|
data-school={row.school}
|
|
>
|
|
<span className="encounter-timeline__glyph" aria-hidden="true">
|
|
{mechanicGlyph(row.telegraphShape)}
|
|
</span>
|
|
<span className="encounter-timeline__name">{row.name}</span>
|
|
<strong>{row.value}</strong>
|
|
<i aria-hidden="true"><b style={{ transform: `scaleX(${row.progress})` }} /></i>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|