feat: communicate exploration zone unlock conditions in-game (#74)
Security Scan and Upload / Security & DefectDojo Upload (push) Successful in 1m4s
CI / Lint, Build & Test (push) Successful in 1m10s

## 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: #74
Co-authored-by: Hikari <hikari@nhcarrigan.com>
Co-committed-by: Hikari <hikari@nhcarrigan.com>
This commit was merged in pull request #74.
This commit is contained in:
2026-03-19 12:18:45 -07:00
committed by Naomi Carrigan
parent c4b4fba4c9
commit 14de87d765
2 changed files with 45 additions and 2 deletions
+5 -1
View File
@@ -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",
},
{
@@ -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)
? <div className="exploration-zone-locked-hint">
<p>{"πŸ”’ This zone is locked. Unlock exploration by:"}</p>
{unlockBoss === undefined
? null
: <p>
{"βš”οΈ Defeat: "}
{unlockBoss.name}
</p>
}
{unlockQuest === undefined
? null
: <p>
{"πŸ“œ Complete: "}
{unlockQuest.name}
</p>
}
</div>
: null
}
<div className="exploration-list">
{zoneAreas.map((area) => {
const areaState = explorationState?.areas.find((explorationArea) => {