From 14de87d765787c57b5569c41ce831ff6a0cb9d37 Mon Sep 17 00:00:00 2001 From: Hikari Date: Thu, 19 Mar 2026 12:18:45 -0700 Subject: [PATCH] feat: communicate exploration zone unlock conditions in-game (#74) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Locked exploration zones now show a `πŸ”’ This zone is locked. Unlock exploration by:` hint above the area list, with the specific `βš”οΈ Defeat: {boss}` and `πŸ“œ Complete: {quest}` required - Updated the About panel's Exploration how-to-play entry to document the zone unlock rule explicitly - No new data required β€” unlock conditions are read directly from `zone.unlockBossId` and `zone.unlockQuestId` already in state ## Test plan - [ ] Verify locked exploration zones display the correct boss and quest unlock hints - [ ] Verify already-unlocked zones show no hint - [ ] Verify starter zone (no unlock conditions) shows no hint - [ ] Verify the About panel Exploration entry reflects the updated description - [ ] Confirm lint, build, and tests all pass Closes #59 Reviewed-on: https://git.nhcarrigan.com/nhcarrigan/elysium/pulls/74 Co-authored-by: Hikari Co-committed-by: Hikari --- 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) => {