diff --git a/apps/api/src/data/bosses.ts b/apps/api/src/data/bosses.ts index dde3398..f8b089a 100644 --- a/apps/api/src/data/bosses.ts +++ b/apps/api/src/data/bosses.ts @@ -102,7 +102,7 @@ export const DEFAULT_BOSSES: Boss[] = [ crystalReward: 100, upgradeRewards: ["click_3"], equipmentRewards: ["vorpal_sword", "dragon_scale"], - prestigeRequirement: 1, + prestigeRequirement: 0, zoneId: "shattered_ruins", }, // ── Shadow Marshes ──────────────────────────────────────────────────────── @@ -154,7 +154,7 @@ export const DEFAULT_BOSSES: Boss[] = [ crystalReward: 150, upgradeRewards: ["arcane_scholar_1"], equipmentRewards: ["crystal_shard"], - prestigeRequirement: 1, + prestigeRequirement: 0, zoneId: "shadow_marshes", }, // ── Frozen Peaks ────────────────────────────────────────────────────────── @@ -172,7 +172,7 @@ export const DEFAULT_BOSSES: Boss[] = [ crystalReward: 100, upgradeRewards: ["dragon_rider_1"], equipmentRewards: [], - prestigeRequirement: 1, + prestigeRequirement: 0, zoneId: "frozen_peaks", }, { @@ -189,7 +189,7 @@ export const DEFAULT_BOSSES: Boss[] = [ crystalReward: 250, upgradeRewards: ["void_walker_1"], equipmentRewards: ["frost_crystal"], - prestigeRequirement: 2, + prestigeRequirement: 0, zoneId: "frozen_peaks", }, { @@ -206,7 +206,7 @@ export const DEFAULT_BOSSES: Boss[] = [ crystalReward: 500, upgradeRewards: [], equipmentRewards: ["philosophers_stone"], - prestigeRequirement: 3, + prestigeRequirement: 0, zoneId: "frozen_peaks", }, // ── Volcanic Depths ─────────────────────────────────────────────────────── @@ -224,7 +224,7 @@ export const DEFAULT_BOSSES: Boss[] = [ crystalReward: 150, upgradeRewards: ["celestial_guard_1"], equipmentRewards: ["flame_lance"], - prestigeRequirement: 2, + prestigeRequirement: 0, zoneId: "volcanic_depths", }, { @@ -241,7 +241,7 @@ export const DEFAULT_BOSSES: Boss[] = [ crystalReward: 400, upgradeRewards: ["crystal_resonance"], equipmentRewards: ["volcanic_plate"], - prestigeRequirement: 3, + prestigeRequirement: 0, zoneId: "volcanic_depths", }, { @@ -258,7 +258,7 @@ export const DEFAULT_BOSSES: Boss[] = [ crystalReward: 800, upgradeRewards: ["crystal_mastery"], equipmentRewards: ["eternal_flame"], - prestigeRequirement: 4, + prestigeRequirement: 0, zoneId: "volcanic_depths", }, // ── Astral Void (original) ──────────────────────────────────────────────── @@ -276,7 +276,7 @@ export const DEFAULT_BOSSES: Boss[] = [ crystalReward: 1_000, upgradeRewards: ["divine_champion_1"], equipmentRewards: ["astral_robe"], - prestigeRequirement: 4, + prestigeRequirement: 0, zoneId: "astral_void", }, { @@ -293,7 +293,7 @@ export const DEFAULT_BOSSES: Boss[] = [ crystalReward: 2_500, upgradeRewards: ["crystal_focus"], equipmentRewards: ["celestial_blade"], - prestigeRequirement: 5, + prestigeRequirement: 0, zoneId: "astral_void", }, { @@ -310,7 +310,7 @@ export const DEFAULT_BOSSES: Boss[] = [ crystalReward: 10_000, upgradeRewards: [], equipmentRewards: ["infinity_gem"], - prestigeRequirement: 6, + prestigeRequirement: 0, zoneId: "astral_void", }, // ── Celestial Reaches ───────────────────────────────────────────────────── diff --git a/apps/web/src/components/game/QuestPanel.tsx b/apps/web/src/components/game/QuestPanel.tsx index 71460a7..247e602 100644 --- a/apps/web/src/components/game/QuestPanel.tsx +++ b/apps/web/src/components/game/QuestPanel.tsx @@ -1,6 +1,7 @@ import type { Quest } from "@elysium/types"; import { useState } from "react"; import { useGame } from "../../context/GameContext.js"; +import { formatNumber } from "../../utils/format.js"; import { LockToggle } from "../ui/LockToggle.js"; import { ZoneSelector } from "./ZoneSelector.js"; @@ -19,9 +20,10 @@ const questTimeRemaining = (quest: Quest): number => { interface QuestCardProps { quest: Quest; unlockHint?: string | undefined; + zoneHint?: string | undefined; } -const QuestCard = ({ quest, unlockHint }: QuestCardProps): React.JSX.Element => { +const QuestCard = ({ quest, unlockHint, zoneHint }: QuestCardProps): React.JSX.Element => { const { startQuest } = useGame(); return ( @@ -33,9 +35,9 @@ const QuestCard = ({ quest, unlockHint }: QuestCardProps): React.JSX.Element => {quest.rewards.map((reward, index) => ( // eslint-disable-next-line react/no-array-index-key -- rewards have no unique id - {reward.type === "gold" && `🪙 ${reward.amount?.toLocaleString()}`} - {reward.type === "essence" && `✨ ${reward.amount?.toLocaleString()}`} - {reward.type === "crystals" && `💎 ${reward.amount?.toLocaleString()}`} + {reward.type === "gold" && `🪙 ${formatNumber(reward.amount ?? 0)}`} + {reward.type === "essence" && `✨ ${formatNumber(reward.amount ?? 0)}`} + {reward.type === "crystals" && `💎 ${formatNumber(reward.amount ?? 0)}`} {reward.type === "upgrade" && "🔓 Upgrade"} {reward.type === "adventurer" && "👥 New Adventurer"} @@ -46,7 +48,8 @@ const QuestCard = ({ quest, unlockHint }: QuestCardProps): React.JSX.Element => {quest.status === "locked" && ( <> 🔒 Locked - {unlockHint &&

📜 Complete: {unlockHint}

} + {zoneHint &&

🗺️ Unlock zone: {zoneHint}

} + {!zoneHint && unlockHint &&

📜 Complete: {unlockHint}

} )} {quest.status === "available" && ( @@ -84,9 +87,15 @@ export const QuestPanel = (): React.JSX.Element => { : zoneQuests.filter((q) => q.status !== "locked"); const questNameById = new Map(state.quests.map((q) => [q.id, q.name])); + const zoneById = new Map(zones.map((z) => [z.id, z])); const questUnlockHints = new Map(); + const questZoneHints = new Map(); for (const quest of state.quests) { - if (quest.status === "locked" && quest.prerequisiteIds.length > 0) { + if (quest.status !== "locked") continue; + const zone = zoneById.get(quest.zoneId); + if (zone?.status === "locked") { + questZoneHints.set(quest.id, zone.name); + } else if (quest.prerequisiteIds.length > 0) { const prereqId = quest.prerequisiteIds[0]; if (prereqId) { const prereqName = questNameById.get(prereqId); @@ -116,7 +125,7 @@ export const QuestPanel = (): React.JSX.Element => {
{visibleQuests.map((quest) => ( - + ))} {visibleQuests.length === 0 && (

No quests to show in this zone.