fix: remove early prestige gates and improve quest unlock hints

- Remove prestigeRequirement from all original zone bosses (Shattered Ruins through Astral Void) — prestige gates now only apply to new endgame zones (Celestial Reaches onward)
- Show zone unlock hint on locked quests when the quest's zone is still locked, so players know what to do
- Switch quest reward numbers to use formatNumber instead of toLocaleString, fixing raw integer display for endgame values
This commit is contained in:
2026-03-06 16:41:50 -08:00
committed by Naomi Carrigan
parent fa1c46f17f
commit 18ff4ce547
2 changed files with 27 additions and 18 deletions
+11 -11
View File
@@ -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 ─────────────────────────────────────────────────────
+16 -7
View File
@@ -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
<span key={index} className="reward-tag">
{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"}
</span>
@@ -46,7 +48,8 @@ const QuestCard = ({ quest, unlockHint }: QuestCardProps): React.JSX.Element =>
{quest.status === "locked" && (
<>
<span className="quest-badge locked">🔒 Locked</span>
{unlockHint && <p className="unlock-hint">📜 Complete: {unlockHint}</p>}
{zoneHint && <p className="unlock-hint">🗺 Unlock zone: {zoneHint}</p>}
{!zoneHint && unlockHint && <p className="unlock-hint">📜 Complete: {unlockHint}</p>}
</>
)}
{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<string, string>();
const questZoneHints = new Map<string, string>();
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 => {
<div className="quest-list">
{visibleQuests.map((quest) => (
<QuestCard key={quest.id} quest={quest} unlockHint={questUnlockHints.get(quest.id)} />
<QuestCard key={quest.id} quest={quest} unlockHint={questUnlockHints.get(quest.id)} zoneHint={questZoneHints.get(quest.id)} />
))}
{visibleQuests.length === 0 && (
<p className="empty-zone">No quests to show in this zone.</p>