From 7629e884639f6b4690fad9817f9747b53d21d210 Mon Sep 17 00:00:00 2001 From: Hikari Date: Thu, 19 Mar 2026 12:06:55 -0700 Subject: [PATCH] feat: communicate exploration zone unlock conditions in-game Locked exploration zones now display the specific boss to defeat and quest to complete required to unlock them. The About panel's Exploration entry also documents the unlock rule explicitly. Closes #59 --- apps/web/src/components/game/aboutPanel.tsx | 6 ++- .../src/components/game/explorationPanel.tsx | 41 ++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/apps/web/src/components/game/aboutPanel.tsx b/apps/web/src/components/game/aboutPanel.tsx index 7c9a184..12785d1 100644 --- a/apps/web/src/components/game/aboutPanel.tsx +++ b/apps/web/src/components/game/aboutPanel.tsx @@ -111,7 +111,11 @@ const howToPlay = [ + " real-time and reward gold, essence, and crafting materials when" + " collected. Each area has a set duration β€” short explorations are" + " faster but longer ones offer rarer finds. A πŸ“– icon marks areas" - + " you've collected from at least once, unlocking a Codex entry.", + + " you've collected from at least once, unlocking a Codex entry." + + " Exploration zones are locked until the corresponding main-game" + + " zone is unlocked β€” which requires defeating that zone's final boss" + + " and completing its final quest. The Exploration tab shows the" + + " specific boss and quest required for each locked zone.", title: "πŸ—ΊοΈ Exploration", }, { diff --git a/apps/web/src/components/game/explorationPanel.tsx b/apps/web/src/components/game/explorationPanel.tsx index defcafb..2ba693e 100644 --- a/apps/web/src/components/game/explorationPanel.tsx +++ b/apps/web/src/components/game/explorationPanel.tsx @@ -6,6 +6,7 @@ */ /* eslint-disable max-lines-per-function -- Complex component with many render paths */ /* eslint-disable complexity -- Complex component with many conditional render paths */ +/* eslint-disable max-lines -- Exploration panel requires many render paths and result display */ import { type JSX, useState } from "react"; import { useGame } from "../../context/gameContext.js"; import { EXPLORATION_AREAS } from "../../data/explorations.js"; @@ -91,7 +92,24 @@ const ExplorationPanel = (): JSX.Element => { ); } - const { zones, exploration: explorationState } = state; + const { zones, exploration: explorationState, bosses, quests } = state; + + const activeZone = zones.find((zone) => { + return zone.id === activeZoneId; + }); + const zoneIsLocked = activeZone?.status === "locked"; + const unlockBoss = activeZone?.unlockBossId === null + || activeZone?.unlockBossId === undefined + ? undefined + : bosses.find((boss) => { + return boss.id === activeZone.unlockBossId; + }); + const unlockQuest = activeZone?.unlockQuestId === null + || activeZone?.unlockQuestId === undefined + ? undefined + : quests.find((quest) => { + return quest.id === activeZone.unlockQuestId; + }); const zoneAreas = EXPLORATION_AREAS.filter((area) => { return area.zoneId === activeZoneId; @@ -220,6 +238,27 @@ const ExplorationPanel = (): JSX.Element => { zones={zones} /> + {zoneIsLocked && (unlockBoss !== undefined || unlockQuest !== undefined) + ?
+

{"πŸ”’ This zone is locked. Unlock exploration by:"}

+ {unlockBoss === undefined + ? null + :

+ {"βš”οΈ Defeat: "} + {unlockBoss.name} +

+ } + {unlockQuest === undefined + ? null + :

+ {"πŸ“œ Complete: "} + {unlockQuest.name} +

+ } +
+ : null + } +
{zoneAreas.map((area) => { const areaState = explorationState?.areas.find((explorationArea) => {