import { useEffect, useState } from "react"; import { useCombatStore } from "../game/combatStore"; import { requireDungeonDefinition } from "../game/dungeonRegistry"; import { MANASTORM_ENDGAME_MODE_ID, manastormCacheChance, } from "../game/manastorm"; import { manastormChaoticLinkState } from "../game/manastormChaoticLink"; import { lootCurrentManastormBoss, openManastormRewardCache, } from "../game/manastormLoot"; import { useManastormStore } from "../game/manastormStore"; import { useGameStore } from "../game/store"; import { ManastormClientOverlay } from "./ManastormClientOverlay"; import { EditableHudElement } from "./EditableHudElement"; export function ManastormStatus() { const gameMode = useGameStore((state) => state.gameMode); const inputMode = useGameStore((state) => state.inputMode); const activeDungeonId = useGameStore((state) => state.activeDungeonId); const level = useManastormStore((state) => state.level); const modeId = useManastormStore((state) => state.modeId); const status = useManastormStore((state) => state.status); const phase = useManastormStore((state) => state.phase); const encounter = useManastormStore((state) => state.currentEncounter); const partySize = useManastormStore((state) => state.partySize); const resurrectionCharges = useManastormStore((state) => state.resurrectionCharges); const checkpointLevel = useManastormStore((state) => state.checkpointLevel); const milestone = useManastormStore((state) => state.milestone); const scaling = useManastormStore((state) => state.scaling); const groupModifier = useManastormStore((state) => state.groupModifier); const affixes = useManastormStore((state) => state.activeAffixes); const cacheMeter = useManastormStore((state) => state.cacheMeter); const cacheThreshold = useManastormStore((state) => state.bonusCacheThreshold); const rewardCache = useManastormStore((state) => state.rewardCache); const [waveElapsedSeconds, setWaveElapsedSeconds] = useState(0); const pendingLootCount = useCombatStore((state) => encounter ? state.mobs[encounter.bossRuntimeId]?.pendingLoot.length ?? 0 : 0); const mobs = useCombatStore((state) => state.mobs); const waveActive = gameMode === "manastorm" && Boolean(encounter) && status !== "idle" && status !== "failed"; useEffect(() => { if (!waveActive) { setWaveElapsedSeconds(0); return undefined; } const startedAt = Date.now(); setWaveElapsedSeconds(0); const interval = window.setInterval(() => { setWaveElapsedSeconds(Math.floor((Date.now() - startedAt) / 1_000)); }, 1_000); return () => window.clearInterval(interval); }, [encounter?.id, level, waveActive]); if (gameMode !== "manastorm" || !encounter || status === "idle" || status === "failed") return <> ; const dungeon = requireDungeonDefinition(activeDungeonId); const stageLocation = encounter.location ?? dungeon.title; const waveElapsed = `${Math.floor(waveElapsedSeconds / 60)}:${String(waveElapsedSeconds % 60).padStart(2, "0")}`; const statBonus = Math.round((scaling.enemyStatMultiplier - 1) * 100); const lootBonus = Math.round(scaling.bonusLootChance * 100); const modeLabel = modeId === MANASTORM_ENDGAME_MODE_ID ? "End-game" : "Leveling"; const cacheChance = modeId === MANASTORM_ENDGAME_MODE_ID ? Math.round(manastormCacheChance(level, cacheMeter) * 100) : 100; const link = manastormChaoticLinkState(encounter, mobs); const chaoticLink = link.activeStacks > 0 ? `${link.activeStacks} stack${link.activeStacks === 1 ? "" : "s"} · +${Math.round((link.bossHealthMultiplier - 1) * 100)}% HP · +${Math.round((link.bossDamageMultiplier - 1) * 100)}% DMG` : "Broken"; const objective = phase === "trash" ? link.activeStacks > 0 ? `Defeat ${link.activeStacks} linked guardian${link.activeStacks === 1 ? "" : "s"}, or challenge the empowered boss` : `Defeat ${encounter.bossName}` : phase === "loot" ? `Loot ${encounter.bossName} · ${pendingLootCount} item${pendingLootCount === 1 ? "" : "s"} · ${inputMode === "gamepad" ? "A" : "E"}` : phase === "portal" ? "Enter the snowglobe portal" : phase === "next" ? "The storm is shifting" : `Defeat ${encounter.bossName}`; return ( <>
{milestone ? "Milestone" : modeLabel} {level} {waveElapsed}

{stageLocation} · {encounter.bossName} {partySize}P · Enemy {statBonus >= 0 ? "+" : ""}{statBonus}% · Loot {lootBonus}% · Checkpoint {checkpointLevel} Resurrections {resurrectionCharges}/5 · Cache chance {cacheChance}% {modeId === MANASTORM_ENDGAME_MODE_ID ? ` · Protection ${cacheMeter}/${cacheThreshold}` : ""} {` · Chaotic Link ${chaoticLink}`} {partySize > 1 ? ` · Party scale ×${groupModifier.enemyStatMultiplier.toFixed(2)}` : ""} {affixes.length ? ( {affixes.map((affix) => ( {affix.iconReference ? ( ) : null} {affix.name} ))} ) : null}

{phase === "loot" ? ( ) : (
{objective}
)}
{rewardCache[0] ? ( ) : null} ); }