Tier System
1. Summary
Goal: Система визуального различения предметов по редкости. Определяет цвета, градиенты и glow эффекты для каждого tier.
User Value: Мгновенное понимание ценности предмета по цвету. Редкие предметы выделяются — создаёт желание их получить.
Вопреки изначальному плану, tier-константы продублированы в трёх файлах с разными значениями (см. Architecture). Shared содержит core-функции и базовые константы, но frontend и admin определяют собственные расширенные наборы стилей.
2. Business Logic
Tier Levels
| Tier | Название | HEX | Tailwind |
|---|---|---|---|
TIER_0 | Обычный | #9CA3AF | gray-400 |
TIER_1 | Необычный | #22C55E | green-500 |
TIER_2 | Редкий | #3B82F6 | blue-500 |
TIER_3 | Эпический | #A855F7 | purple-500 |
TIER_4 | Мифический | #EF4444 | red-500 |
TIER_5 | Легендарный | #EAB308 | yellow-500 |
Все tier получают визуальное оформление: цветная рамка + градиент снизу. Цвет определяется по таблице выше.
Resolution Logic
- SKIN
- FRAGMENT / BLUEPRINT
- BUFF
- SCRAP / XP
- RESOURCE
Источник tier: Собственный item.tier из БД
Пример: Dragon Rocket Launcher → TIER_4 (Мифический, красный)
Источник tier: Наследует от targetSkin.tier
Fallback: Если нет targetSkin → собственный item.tier
Фрагмент скина TIER_5 должен выглядеть так же ценно, как сам скин. Иначе пользователь не понимает что собирает.
Источник tier: item.tier напрямую из БД
Пример: XP Catalyst +100% → TIER_3 (задаётся в админке)
Tier: Всегда null → интерпретируется как TIER_0
Цвет рамки/glow: Серый (#9CA3AF)
Для узнаваемости в тексте: SCRAP = green-400, XP = yellow-400. Это не tier система, а Currency Display.
Tier: Всегда null → TIER_0
Пример: Ключи, расходники
Dark Colors (для рулетки)
Затемнённые версии для тёмных фонов (секторы колеса):
| Tier | HEX | Tailwind |
|---|---|---|
TIER_0 | #3d4654 | — |
TIER_1 | #166534 | green-800 |
TIER_2 | #1e40af | blue-800 |
TIER_3 | #581c87 | purple-800 |
TIER_4 | #991b1b | red-800 |
TIER_5 | #854d0e | yellow-800 |
3. ADR (Architectural Decisions)
Почему SCRAP/XP не имеют собственного tier?
Проблема: Предлагалось создать TIER_SCRAP, TIER_XP, TIER_SP для унификации.
Решение: Отклонено. Валюты получают tier = null → TIER_0.
Альтернативы (отклонены):
TIER_SCRAP/TIER_XP— смешивает концепции (редкость ≠ валюта)- Отдельные HEX для каждой валюты в tier системе — усложняет shouldGlow(), getTierColor()
Tier = редкость ПРЕДМЕТА (рамки, glow) Currency Display = узнаваемость валют в тексте (green/yellow/orange)
Не смешивать!
Последствия: Чистая архитектура, но нужно понимать разницу между системами.
Почему планировался единый источник истины?
Проблема: Было 3 файла с константами tier (shared, frontend, admin). HEX цвета расходились.
Решение (частичное): Core-функции и базовые HEX-константы вынесены в shared/item-display-system/core/tier.system.ts. Однако frontend и admin по-прежнему содержат собственные определения tier-констант с отличающимися значениями.
Что было удалено
| Файл | Удалённый код |
|---|---|
shared/tier.system.ts | CURRENCY_COLORS, getCurrencyColor() |
frontend/tiers.ts | RESOURCE_TEXT_COLORS, getResourceColor(), getTierFromMultiplier() |
TIER_GRADIENTS определён в двух файлах с разными значениями:
| Tier | shared/.../tier.system.ts | frontend/.../tiers.ts |
|---|---|---|
| TIER_0 | from-neutral-700/90 via-neutral-800/60 | from-gray-900/80 via-gray-950/50 |
| TIER_1 | from-green-900/60 via-green-950/30 | from-green-900/80 via-green-950/50 |
| TIER_2 | from-blue-900/60 via-blue-950/30 | from-blue-900/80 via-blue-950/50 |
| TIER_3 | from-purple-900/60 via-purple-950/30 | from-purple-900/80 via-purple-950/50 |
| TIER_4 | from-red-900/60 via-red-950/30 | from-red-900/80 via-red-950/50 |
| TIER_5 | from-yellow-900/60 via-yellow-950/30 | from-yellow-900/80 via-yellow-950/50 |
Ключевые отличия:
- Shared использует
neutralдля TIER_0, frontend используетgray(gray имеет синий подтон) - Прозрачность: shared
90/60, frontend80/50(frontend более прозрачный) - Остальные tiers: shared
60/30, frontend80/50(frontend интенсивнее)
Аналогично TIER_NAMES, TIER_BG_COLORS дублированы между shared и frontend с одинаковыми значениями. TIER_TEXT_COLORS определена только в frontend и admin (не в shared).
Последствия: Shared определяет градиенты для ItemCell (используется через resolveItemProps), а frontend определяет свою версию для FlippableItemCard и других компонентов. Оба варианта используются в разных контекстах.
4. Architecture
Resolution Flow
Key Components
| Компонент | Путь | Описание |
|---|---|---|
| tier.system.ts | shared/src/item-display-system/core/tier.system.ts | Core-константы (HEX, gradients, borders) и функции (resolveTier, getTierColor и т.д.) |
| item.resolver.ts | shared/src/item-display-system/core/item.resolver.ts | resolveItemProps() — единый резолвер всех визуальных свойств для UI |
| tiers.ts (frontend) | frontend/src/constants/tiers.ts | Расширенный набор frontend-стилей: константы (TIER_GRADIENTS, TIER_CARD_STYLES, TIER_GLOW_COLORS, TIER_HSL_COLORS, TIER_HISTORY_CARD_STYLES, TIER_ACTION_BUTTON_STYLES, TIER_THIN_BORDER_STYLES, TIER_HEX_COLORS, TIER_CONFETTI_CONFIG, REWARD_CONFETTI_CONFIG), типы (ItemTier, TierNumber), конвертеры (TIER_TO_NUMBER, NUMBER_TO_TIER, tierFromNumber, tierToNumber), утилиты (getTierTextColor, getTierCardStyle, getTierHistoryCardStyle, getTierActionButtonStyle, getTierGlowColor, getTierThinBorderStyle, interpolateTierColor, getConfettiConfig и др.). Реэкспортирует только getDarkTierColor и TIER_DARK_COLORS из shared |
| tiers.ts (admin) | admin/src/constants/tiers.ts | Набор для админки: константы (TIER_NAMES, TIER_TEXT_COLORS, TIER_HEX_COLORS, TIER_BADGE_COLORS, TIER_BORDER_COLORS, TIER_SHORT_LABELS, TIER_BADGE_TEXT_HEX), утилиты (getTierName, getTierTextColor, getTierHexColor, getTierBadgeColor, getTierBorderColor, getTierNameOrNull, getTierBadgeConfig), тип ItemTier. Полностью независим от shared |
| Currency | frontend/src/components/ui/Currency/ | Display цвета для валют |
5. API
Core Functions (shared/tier.system.ts)
// Получить tier с учётом наследования
resolveTier(item: UnifiedItem): ItemTier | null
// Получить эффективный tier (null → TIER_0, всегда возвращает tier)
getEffectiveTier(item: UnifiedItem): ItemTier
// HEX цвет (null → TIER_0)
getTierColor(tier: ItemTier | null): string
// Затемнённый цвет для рулетки
getDarkTierColor(tier: ItemTier | null): string
// Tailwind класс градиента
getTierGradient(tier: ItemTier | null): string
// Tailwind класс border
getTierBorder(tier: ItemTier | null): string
// HEX цвет border (для inline styles)
getTierBorderColor(tier: ItemTier | null): string
// Tailwind класс bg
getTierBgColor(tier: ItemTier | null): string
// Название на русском
getTierName(tier: ItemTier | null): string
// Нужен ли glow по tier (TIER_2+)
shouldGlowByTier(tier: ItemTier | null): boolean
// Нужен ли glow для предмета (использует resolveTier)
shouldGlow(item: UnifiedItem): boolean
Usage
- Frontend
- Admin
import {
resolveTier,
getTierColor,
getDarkTierColor,
shouldGlow,
} from '@goloot/shared/item-display-system';
// Для карточки предмета
const tier = resolveTier(item);
const color = getTierColor(tier);
const hasGlow = shouldGlow(item);
// Для рулетки (тёмный фон)
const sectorColor = getDarkTierColor(tier);
import { resolveTier, getTierColor } from '@goloot/shared/item-display-system';
// Цвет слота награды
const tier = resolveTier(item);
const slotColor = getTierColor(tier);
6. Contexts
Где что используется
| Контекст | Система | Результат для SCRAP/XP |
|---|---|---|
| 🎰 Рулетка (сектор) | Tier | Серый #3d4654 |
| 📦 Кейс (рамка/glow) | Tier | Серый, без glow |
| 📋 История | Tier | Серый текст |
| 📰 LiveFeed | Currency Display | Зелёный/Жёлтый текст |
| 🎁 TopFloating | Currency Display | Зелёный/Жёлтый текст |
Отдельная валюта лояльности. Цвет: orange-400. Не часть tier системы.
Валюта Boost Pass. Цвет: text-blue-400. Определена в currency.constants.ts. Не часть tier системы.
7. Related
- Buffs — баффы используют tier из БД
- Cases — награды кейсов с tier
- Daily Spins — секторы рулетки с tier цветами
- Inventory — отображение предметов с tier стилями