generated from nhcarrigan/template
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:
+11
-11
@@ -102,7 +102,7 @@ export const DEFAULT_BOSSES: Boss[] = [
|
|||||||
crystalReward: 100,
|
crystalReward: 100,
|
||||||
upgradeRewards: ["click_3"],
|
upgradeRewards: ["click_3"],
|
||||||
equipmentRewards: ["vorpal_sword", "dragon_scale"],
|
equipmentRewards: ["vorpal_sword", "dragon_scale"],
|
||||||
prestigeRequirement: 1,
|
prestigeRequirement: 0,
|
||||||
zoneId: "shattered_ruins",
|
zoneId: "shattered_ruins",
|
||||||
},
|
},
|
||||||
// ── Shadow Marshes ────────────────────────────────────────────────────────
|
// ── Shadow Marshes ────────────────────────────────────────────────────────
|
||||||
@@ -154,7 +154,7 @@ export const DEFAULT_BOSSES: Boss[] = [
|
|||||||
crystalReward: 150,
|
crystalReward: 150,
|
||||||
upgradeRewards: ["arcane_scholar_1"],
|
upgradeRewards: ["arcane_scholar_1"],
|
||||||
equipmentRewards: ["crystal_shard"],
|
equipmentRewards: ["crystal_shard"],
|
||||||
prestigeRequirement: 1,
|
prestigeRequirement: 0,
|
||||||
zoneId: "shadow_marshes",
|
zoneId: "shadow_marshes",
|
||||||
},
|
},
|
||||||
// ── Frozen Peaks ──────────────────────────────────────────────────────────
|
// ── Frozen Peaks ──────────────────────────────────────────────────────────
|
||||||
@@ -172,7 +172,7 @@ export const DEFAULT_BOSSES: Boss[] = [
|
|||||||
crystalReward: 100,
|
crystalReward: 100,
|
||||||
upgradeRewards: ["dragon_rider_1"],
|
upgradeRewards: ["dragon_rider_1"],
|
||||||
equipmentRewards: [],
|
equipmentRewards: [],
|
||||||
prestigeRequirement: 1,
|
prestigeRequirement: 0,
|
||||||
zoneId: "frozen_peaks",
|
zoneId: "frozen_peaks",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -189,7 +189,7 @@ export const DEFAULT_BOSSES: Boss[] = [
|
|||||||
crystalReward: 250,
|
crystalReward: 250,
|
||||||
upgradeRewards: ["void_walker_1"],
|
upgradeRewards: ["void_walker_1"],
|
||||||
equipmentRewards: ["frost_crystal"],
|
equipmentRewards: ["frost_crystal"],
|
||||||
prestigeRequirement: 2,
|
prestigeRequirement: 0,
|
||||||
zoneId: "frozen_peaks",
|
zoneId: "frozen_peaks",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -206,7 +206,7 @@ export const DEFAULT_BOSSES: Boss[] = [
|
|||||||
crystalReward: 500,
|
crystalReward: 500,
|
||||||
upgradeRewards: [],
|
upgradeRewards: [],
|
||||||
equipmentRewards: ["philosophers_stone"],
|
equipmentRewards: ["philosophers_stone"],
|
||||||
prestigeRequirement: 3,
|
prestigeRequirement: 0,
|
||||||
zoneId: "frozen_peaks",
|
zoneId: "frozen_peaks",
|
||||||
},
|
},
|
||||||
// ── Volcanic Depths ───────────────────────────────────────────────────────
|
// ── Volcanic Depths ───────────────────────────────────────────────────────
|
||||||
@@ -224,7 +224,7 @@ export const DEFAULT_BOSSES: Boss[] = [
|
|||||||
crystalReward: 150,
|
crystalReward: 150,
|
||||||
upgradeRewards: ["celestial_guard_1"],
|
upgradeRewards: ["celestial_guard_1"],
|
||||||
equipmentRewards: ["flame_lance"],
|
equipmentRewards: ["flame_lance"],
|
||||||
prestigeRequirement: 2,
|
prestigeRequirement: 0,
|
||||||
zoneId: "volcanic_depths",
|
zoneId: "volcanic_depths",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -241,7 +241,7 @@ export const DEFAULT_BOSSES: Boss[] = [
|
|||||||
crystalReward: 400,
|
crystalReward: 400,
|
||||||
upgradeRewards: ["crystal_resonance"],
|
upgradeRewards: ["crystal_resonance"],
|
||||||
equipmentRewards: ["volcanic_plate"],
|
equipmentRewards: ["volcanic_plate"],
|
||||||
prestigeRequirement: 3,
|
prestigeRequirement: 0,
|
||||||
zoneId: "volcanic_depths",
|
zoneId: "volcanic_depths",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -258,7 +258,7 @@ export const DEFAULT_BOSSES: Boss[] = [
|
|||||||
crystalReward: 800,
|
crystalReward: 800,
|
||||||
upgradeRewards: ["crystal_mastery"],
|
upgradeRewards: ["crystal_mastery"],
|
||||||
equipmentRewards: ["eternal_flame"],
|
equipmentRewards: ["eternal_flame"],
|
||||||
prestigeRequirement: 4,
|
prestigeRequirement: 0,
|
||||||
zoneId: "volcanic_depths",
|
zoneId: "volcanic_depths",
|
||||||
},
|
},
|
||||||
// ── Astral Void (original) ────────────────────────────────────────────────
|
// ── Astral Void (original) ────────────────────────────────────────────────
|
||||||
@@ -276,7 +276,7 @@ export const DEFAULT_BOSSES: Boss[] = [
|
|||||||
crystalReward: 1_000,
|
crystalReward: 1_000,
|
||||||
upgradeRewards: ["divine_champion_1"],
|
upgradeRewards: ["divine_champion_1"],
|
||||||
equipmentRewards: ["astral_robe"],
|
equipmentRewards: ["astral_robe"],
|
||||||
prestigeRequirement: 4,
|
prestigeRequirement: 0,
|
||||||
zoneId: "astral_void",
|
zoneId: "astral_void",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -293,7 +293,7 @@ export const DEFAULT_BOSSES: Boss[] = [
|
|||||||
crystalReward: 2_500,
|
crystalReward: 2_500,
|
||||||
upgradeRewards: ["crystal_focus"],
|
upgradeRewards: ["crystal_focus"],
|
||||||
equipmentRewards: ["celestial_blade"],
|
equipmentRewards: ["celestial_blade"],
|
||||||
prestigeRequirement: 5,
|
prestigeRequirement: 0,
|
||||||
zoneId: "astral_void",
|
zoneId: "astral_void",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -310,7 +310,7 @@ export const DEFAULT_BOSSES: Boss[] = [
|
|||||||
crystalReward: 10_000,
|
crystalReward: 10_000,
|
||||||
upgradeRewards: [],
|
upgradeRewards: [],
|
||||||
equipmentRewards: ["infinity_gem"],
|
equipmentRewards: ["infinity_gem"],
|
||||||
prestigeRequirement: 6,
|
prestigeRequirement: 0,
|
||||||
zoneId: "astral_void",
|
zoneId: "astral_void",
|
||||||
},
|
},
|
||||||
// ── Celestial Reaches ─────────────────────────────────────────────────────
|
// ── Celestial Reaches ─────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { Quest } from "@elysium/types";
|
import type { Quest } from "@elysium/types";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useGame } from "../../context/GameContext.js";
|
import { useGame } from "../../context/GameContext.js";
|
||||||
|
import { formatNumber } from "../../utils/format.js";
|
||||||
import { LockToggle } from "../ui/LockToggle.js";
|
import { LockToggle } from "../ui/LockToggle.js";
|
||||||
import { ZoneSelector } from "./ZoneSelector.js";
|
import { ZoneSelector } from "./ZoneSelector.js";
|
||||||
|
|
||||||
@@ -19,9 +20,10 @@ const questTimeRemaining = (quest: Quest): number => {
|
|||||||
interface QuestCardProps {
|
interface QuestCardProps {
|
||||||
quest: Quest;
|
quest: Quest;
|
||||||
unlockHint?: string | undefined;
|
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();
|
const { startQuest } = useGame();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -33,9 +35,9 @@ const QuestCard = ({ quest, unlockHint }: QuestCardProps): React.JSX.Element =>
|
|||||||
{quest.rewards.map((reward, index) => (
|
{quest.rewards.map((reward, index) => (
|
||||||
// eslint-disable-next-line react/no-array-index-key -- rewards have no unique id
|
// eslint-disable-next-line react/no-array-index-key -- rewards have no unique id
|
||||||
<span key={index} className="reward-tag">
|
<span key={index} className="reward-tag">
|
||||||
{reward.type === "gold" && `🪙 ${reward.amount?.toLocaleString()}`}
|
{reward.type === "gold" && `🪙 ${formatNumber(reward.amount ?? 0)}`}
|
||||||
{reward.type === "essence" && `✨ ${reward.amount?.toLocaleString()}`}
|
{reward.type === "essence" && `✨ ${formatNumber(reward.amount ?? 0)}`}
|
||||||
{reward.type === "crystals" && `💎 ${reward.amount?.toLocaleString()}`}
|
{reward.type === "crystals" && `💎 ${formatNumber(reward.amount ?? 0)}`}
|
||||||
{reward.type === "upgrade" && "🔓 Upgrade"}
|
{reward.type === "upgrade" && "🔓 Upgrade"}
|
||||||
{reward.type === "adventurer" && "👥 New Adventurer"}
|
{reward.type === "adventurer" && "👥 New Adventurer"}
|
||||||
</span>
|
</span>
|
||||||
@@ -46,7 +48,8 @@ const QuestCard = ({ quest, unlockHint }: QuestCardProps): React.JSX.Element =>
|
|||||||
{quest.status === "locked" && (
|
{quest.status === "locked" && (
|
||||||
<>
|
<>
|
||||||
<span className="quest-badge locked">🔒 Locked</span>
|
<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" && (
|
{quest.status === "available" && (
|
||||||
@@ -84,9 +87,15 @@ export const QuestPanel = (): React.JSX.Element => {
|
|||||||
: zoneQuests.filter((q) => q.status !== "locked");
|
: zoneQuests.filter((q) => q.status !== "locked");
|
||||||
|
|
||||||
const questNameById = new Map(state.quests.map((q) => [q.id, q.name]));
|
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 questUnlockHints = new Map<string, string>();
|
||||||
|
const questZoneHints = new Map<string, string>();
|
||||||
for (const quest of state.quests) {
|
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];
|
const prereqId = quest.prerequisiteIds[0];
|
||||||
if (prereqId) {
|
if (prereqId) {
|
||||||
const prereqName = questNameById.get(prereqId);
|
const prereqName = questNameById.get(prereqId);
|
||||||
@@ -116,7 +125,7 @@ export const QuestPanel = (): React.JSX.Element => {
|
|||||||
|
|
||||||
<div className="quest-list">
|
<div className="quest-list">
|
||||||
{visibleQuests.map((quest) => (
|
{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 && (
|
{visibleQuests.length === 0 && (
|
||||||
<p className="empty-zone">No quests to show in this zone.</p>
|
<p className="empty-zone">No quests to show in this zone.</p>
|
||||||
|
|||||||
Reference in New Issue
Block a user