feat: unify guardian system — merge static GUARDIANS with extended procedural guardians in Pacts tab
- guardian-encounters.ts: add getGuardianForFloor() and getAllGuardianFloors() unified lookup functions that merge static GUARDIANS (floors 10-100) with extended system (compound 110, exotic 120-140, combo 150+) - GuardianPactsTab.tsx: use unified system, update tiers to cover all floors (Early 10-40, Mid 50-80, Late 90-100, Compound 110, Exotic 120-140, Transcendent 150+) - guardian-pacts-components.tsx: handle combo guardians with dual-element display (symbols + names + '✦ Combo' badge) - docs/circular-deps.txt, docs/dependency-graph.json: auto-generated updates - craftingStore.ts: extract initial equipment instances to crafting-initial-state.ts
This commit is contained in:
@@ -12,11 +12,32 @@ import clsx from 'clsx';
|
||||
|
||||
export type GuardianStatus = 'undefeated' | 'defeated' | 'signed';
|
||||
|
||||
interface FloorTier {
|
||||
export interface FloorTier {
|
||||
label: string;
|
||||
floors: number[];
|
||||
}
|
||||
|
||||
// ─── Element Display Helper ──────────────────────────────────────────────────
|
||||
|
||||
interface ElementDisplay {
|
||||
sym: string;
|
||||
name: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
function getElementDisplays(element: string): ElementDisplay[] {
|
||||
// Combo guardians have elements like "fire+water"
|
||||
const parts = element.split('+');
|
||||
return parts.map((el) => {
|
||||
const def = ELEMENTS[el];
|
||||
return {
|
||||
sym: def?.sym ?? '?',
|
||||
name: def?.name ?? el,
|
||||
color: def?.color ?? '#888',
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Guardian Card ───────────────────────────────────────────────────────────
|
||||
|
||||
interface GuardianCardProps {
|
||||
@@ -40,9 +61,9 @@ export const GuardianCard: React.FC<GuardianCardProps> = React.memo(({
|
||||
ritualProgress,
|
||||
onStartRitual,
|
||||
}) => {
|
||||
const elemDef = ELEMENTS[guardian.element];
|
||||
const elemColor = elemDef?.color ?? '#888';
|
||||
const elemSym = elemDef?.sym ?? '';
|
||||
const elemDisplays = getElementDisplays(guardian.element);
|
||||
const primaryColor = elemDisplays[0]?.color ?? '#888';
|
||||
const isCombo = elemDisplays.length > 1;
|
||||
|
||||
const statusConfig: Record<GuardianStatus, { label: string; color: string; bg: string }> = {
|
||||
undefeated: { label: 'Undefeated', color: 'text-gray-400', bg: 'bg-gray-800/50' },
|
||||
@@ -54,6 +75,11 @@ export const GuardianCard: React.FC<GuardianCardProps> = React.memo(({
|
||||
const ritualTime = guardian.pactTime;
|
||||
const ritualComplete = ritualProgress >= ritualTime;
|
||||
|
||||
// Build element label: single element name, or "Fire + Water" for combos
|
||||
const elementLabel = isCombo
|
||||
? elemDisplays.map(e => e.name).join(' + ')
|
||||
: elemDisplays[0]?.name ?? guardian.element;
|
||||
|
||||
return (
|
||||
<Card
|
||||
className={clsx(
|
||||
@@ -66,11 +92,18 @@ export const GuardianCard: React.FC<GuardianCardProps> = React.memo(({
|
||||
<CardHeader className="pb-2">
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<div className="min-w-0">
|
||||
<CardTitle className="text-sm flex items-center gap-2" style={{ color: elemColor }}>
|
||||
<span>{elemSym}</span>
|
||||
<CardTitle className="text-sm flex items-center gap-2" style={{ color: primaryColor }}>
|
||||
<span className="flex items-center gap-0.5">
|
||||
{elemDisplays.map((e, i) => (
|
||||
<span key={i}>{e.sym}</span>
|
||||
))}
|
||||
</span>
|
||||
<span className="truncate">{guardian.name}</span>
|
||||
</CardTitle>
|
||||
<div className="text-xs text-gray-500 mt-0.5">Floor {floor} · {elemDef?.name ?? guardian.element}</div>
|
||||
<div className="text-xs text-gray-500 mt-0.5">
|
||||
Floor {floor} · {elementLabel}
|
||||
{isCombo && <span className="ml-1 text-purple-400">✦ Combo</span>}
|
||||
</div>
|
||||
</div>
|
||||
<Badge className={clsx('text-[10px] px-1.5 py-0 shrink-0', sc.bg, sc.color)}>
|
||||
{sc.label}
|
||||
|
||||
Reference in New Issue
Block a user