Skip to main content

Quests System

1. Summary

Goal: Система заданий для направления активности пользователей. Квесты стимулируют выполнение целевых действий (квизы, кейсы, подписки) и награждают за достижение целей.

User Value: Понятные цели + гарантированные награды. Пользователь видит конкретные задачи с прогрессом и может планировать свой путь к наградам.


2. Business Logic

Quest Types (Временные периоды)

Срок: Бессрочный

Reset: Нет сброса прогресса

Примеры: "Пройди 100 квизов", "Открой 50 кейсов"

Цель: Квесты без дедлайна — подписки на спонсоров, разовые акции

Quest Categories (Типы действий)

Действие: Прохождение квизов

Conditions:

  • categoryId — только квизы из категории
  • subcategoryId — только из подкатегории
  • slug — конкретный квиз (например "mp5a4")
  • entityType — тип сущности (item, monument, mechanic, npc, vehicle)

Пример: "Пройди 5 квизов про оружие" → { categoryId: "weapon" }

Core Mechanics

1. Shared Progress

Одно действие засчитывается во ВСЕ подходящие квесты одновременно.

Игрок прошёл квиз из категории "Оружие"
→ +1 к квесту "Пройди 5 квизов про оружие"
→ +1 к квесту "Пройди 10 любых квизов"
→ +1 к ежедневному "Пройди 3 квиза"
Реализация

QuestProgressService.incrementCategoryProgress() ищет ВСЕ активные квесты нужной категории, фильтрует по conditions, увеличивает прогресс в каждом в рамках одной транзакции.

2. Lazy Reset

Прогресс DAILY/WEEKLY квестов сбрасывается НЕ по cron, а при первом запросе списка квестов после истечения периода.

Пользователь запрашивает /quests

Для каждого userQuest: lastResetAt в том же дне/неделе?

Если нет → сбросить currentProgress = 0, status = IN_PROGRESS
Награда не сгорает

Если квест COMPLETED но награда не забрана — сброс НЕ происходит. Пользователь может забрать награду в следующую сессию.

3. Quest Rotation System

Из большого пула DAILY/WEEKLY/PERMANENT квестов автоматически выбираются фиксированные наборы для показа пользователям.

Основные принципы
  • Детерминированность: Все пользователи видят одинаковые квесты (seeded shuffle)
  • Отдельный пул Rust: Rust квесты ротируются независимо от обычных
  • Запрет повторов: Квесты не повторяются в течение сезона (пока пул не исчерпан)
  • Персональные исключения: Выполненные isUnique квесты исключаются из ротации

Лимиты (хранятся в модели Season):

ТипRegularRustПериод
DAILYdailyQuestLimit (default 3)dailyRustQuestLimit (default 2)Каждый день
WEEKLYweeklyQuestLimit (default 1)weeklyRustQuestLimit (default 1)Каждую неделю
PERMANENTВсеВсеВесь сезон

Алгоритм выбора (stateless, deterministic):

1. Загрузить лимиты из Season model
2. Загрузить активные квесты сезона (через SeasonQuest)
3. Получить персональные исключения пользователя (isUnique)
4. Разделить квесты на regular и rust пулы
5. Применить исключения
6. Для DAILY/WEEKLY:
- Seeded shuffle пула (seed = type + seasonId)
- Pool cycling: startIdx = (offset * limit) % poolSize
- offset = дней/недель с начала сезона
7. PERMANENT: показать все
8. EVENT: фильтр по startAt/endAt

Seed для детерминированности:

ТипФормат seedПример
DAILY regulardaily-{seasonId}daily-season-1
DAILY rustdaily-{seasonId}-rustdaily-season-1-rust
WEEKLY regularweekly-{seasonId}weekly-season-1
WEEKLY rustweekly-{seasonId}-rustweekly-season-1-rust

4. Unique Quests

Квесты с isUnique: true можно получить награду только один раз.

  • Двойная защита: По telegramId И по steamId (если привязан)
  • Запись в ClaimedUniqueQuest при claim
  • Запись в UserQuestExclusion — исключает квест из ротации для пользователя
  • При повторном claim — статус синхронизируется (CLAIMED), но награда не выдается
Multi-account Protection

Защита работает в два уровня:

  1. По telegramId — основная проверка
  2. По steamId — дополнительная (если Steam привязан к нескольким Telegram аккаунтам)

5. RUST Achievements Integration

При claim награды за RUST квест автоматически обновляется прогресс RUST достижений.

Логика:

  1. Пользователь выполнил Rust квест (например, "Убей 100 медведей", targetProgress=100)
  2. Вызывает /quests/:id/claim → получает награду квеста (Scrap, XP, Item)
  3. Автоматически (через setImmediate) → прогресс RUST достижений +100
  4. Все RUST достижения с подходящими условиями получают прогресс

Пример:

Квест "Убей 100 медведей" (targetProgress=100) выполнен

Подходящие достижения получат +100:
→ "Выполни квесты на 500 убийств медведей" (rustKillAnimalType=BEAR)
→ "Выполни квесты на 1000 убийств животных" (rustEventType=KILL_ANIMAL)
→ "Выполни 100 любых Rust квестов" (conditions=null)
Переменный прогресс

RUST достижения накапливают прогресс по значению quest.targetProgress, а не фиксированный +1 как другие категории.

Это позволяет создавать масштабные долгосрочные достижения: "Выполни квесты на 10000 убийств" выполнится после ~100 квестов "Убей 100 врагов".

Async обновление

Используется setImmediate() — если обновление достижения упадёт с ошибкой, пользователь всё равно получит награду за квест. Ошибки логируются, но не блокируют выдачу награды.

Полная документация: Achievements - RUST Integration

Reward Types

ТипОписаниеПоле
SCRAPОсновная валютаamount
XPОпыт для прокачки уровняamount
STREAK_POINTSВалюта лояльности (SP)amount
ITEMПредмет в инвентарьitemId
CASEКупон на бесплатное открытие кейсаcaseId

Reward API Response

API возвращает расширенную информацию о награде для визуального отображения:

ПолеТипОписание
itemImageUrlstring?URL изображения предмета
itemTypeenum?Тип предмета: SKIN, BLUEPRINT, FRAGMENT, RESOURCE, BUFF
itemTierenum?Тир предмета: TIER_0TIER_5
targetSkinImageUrlstring?URL изображения базового скина (для BLUEPRINT/FRAGMENT)
caseImageUrlstring?URL изображения кейса
Composite Icons

Для типов BLUEPRINT и FRAGMENT фронтенд отображает композитные иконки: базовое изображение скина (targetSkinImageUrl) с оверлеем значка типа (blueprintbase.webp или blueprint_{tier}.webp).

Difficulty Levels (Сложность)

Опциональное поле difficulty (1-3) позволяет указать уровень сложности квеста:

ЗначениеУровеньЦвет badge
1ЛегкийЗелёный
2СреднийЖёлтый
3СложныйКрасный

UI отображение:

  • TMA (QuestCard): DifficultyBadge рядом с заголовком квеста
  • Admin (QuestTable): Колонка "Сложность" с цветным badge
  • Admin (QuestForm): Select "Уровень сложности" в секции "Сложность"
Переиспользуемый компонент

DifficultyBadge используется как в квестах, так и в достижениях. Компонент поддерживает размеры sm и md.

Quest Hints (Подсказки)

Опциональное поле hint (до 300 символов) позволяет добавить подсказку к квесту:

  • В админке: Textarea в форме создания/редактирования квеста
  • В TMA: Иконка ⓘ рядом с описанием (показывается только если hint заполнен)
  • При клике: Модалка в glass morphism стиле с текстом подсказки и кнопкой "Понятно"
Когда использовать hint

Подсказки полезны для квестов со сложными условиями или неочевидными способами выполнения. Например: "Откройте раздел 'Рулетка' в меню" для квеста на spin.

Rust квесты: автозаполнение подсказки

При создании нового Rust квеста в админке поле hint автоматически заполняется текстом: "💡 Напиши /goloot на сервере чтобы начать трекинг прогресса".

Почему: Игрок, который взял Rust квест будучи уже на сервере, не получит прогресс до следующего TIME_UPDATE webhook (0-5 минут). Команда /goloot заставляет плагин синхронизироваться немедленно.

Admin workflow: Подсказка заполняется автоматически при выборе категории RUST, но админ может отредактировать или очистить текст по необходимости.

Admin UI: Rust Item Picker

Модальное окно выбора предметов для RUST квестов (LOOT_ITEM, ITEM_CRAFTED).

Возможности:

  • 933 предмета из rustclash.com вместо ранних 258
  • 14 категорий в виде горизонтальных табов: Weapons, Construction, Items, Resources, Attire, Tools, Medical, Food, Ammo, Traps, Misc, Components, Electrical, Fun
  • Hybrid filtering: Глобальный поиск по всем предметам или фильтрация по активной категории
  • English names: Все названия на английском (из официальной документации Rust)
  • Lazy loading: Изображения загружаются по мере прокрутки
  • Custom shortname: Возможность ввести shortname вручную (для редких предметов)

UI Flow:

  1. Админ открывает форму создания RUST квеста (LOOT_ITEM или CRAFT)
  2. Клик на поле "Item Shortname" → открывается ItemSelectModal
  3. Выбор категории из табов или использование глобального поиска
  4. Клик на предмет → превью с названием и shortname
  5. Подтверждение → shortname заполняется в форму квеста

Технические детали:

  • Каталог: admin/src/constants/rust-item-catalog.ts
  • Компонент: admin/src/components/quests/ItemSelectModal.tsx
  • CDN изображений: https://wiki.rustclash.com/img/items40/{shortname}.png
  • Fallback: Placeholder "?" при ошибке загрузки изображения
Backward Compatibility

Старый каталог (258 items) полностью заменён новым (933 items). Legacy функции в rust-loot.ts обеспечивают совместимость с существующим кодом через @deprecated обёртки.

Smart Quest Generation (Blueprints)

Сезонные квесты генерируются автоматически из code-defined блюпринтов. Каждый блюпринт описывает шаблон генерации с creative русскоязычными названиями, Russian pluralization и условиями.

Блюпринты: quest-blueprints.ts (29 шт.)

Генератор: season-quest-generator.service.ts

Blueprint Matrix

CASES (3 блюпринта) — действия открытия:

IDTypeModeTargetDiff
cases-open-any-dailyDAILYgeneric5–15 (×5)Easy
cases-open-specific-dailyDAILYper-case1–3 (×1)Medium
cases-open-specific-weeklyWEEKLYper-case3–10 (×1)Medium

QUIZ (3 блюпринта):

IDTypeModeTargetDiff
quiz-any-dailyDAILYgeneric1 (fixed)Easy
quiz-any-weeklyWEEKLYgeneric5 (fixed)Easy
quiz-any-permanentPERMANENTgeneric15 (fixed)Medium
Quiz Quests = Generic Only

Quiz-квесты используют только generic режим ("ответь на любой квиз"). Специфичные задания по категориям/предметам/подкатегориям будут реализованы как Achievement templates — долгосрочные цели, для которых не нужна координация с публикацией квизов.

RECYCLE (8 блюпринтов):

IDTypeModeTargetDiff
recycle-any-dailyDAILYgeneric1–5 (×1)Easy
recycle-blueprint-dailyDAILYgeneric1–3 (×1)Easy
recycle-fragment-dailyDAILYgeneric1–3 (×1)Easy
recycle-tier-dailyDAILYgeneric1–2 (×1)Medium
recycle-tier-weeklyWEEKLYgeneric1–5 (×1)Medium
recycle-blueprint-tier-weeklyWEEKLYgeneric2–5 (×1)Medium
recycle-fragment-tier-weeklyWEEKLYgeneric2–5 (×1)Medium
recycle-item-weeklyWEEKLYper-item1 (fixed)Hard

COLLECTION (12 блюпринтов) — content-aware результаты из кейсов + рулеток:

IDTypeModeTargetDiffУсловия
collection-resource-dailyDAILYgeneric3–10 (×1)EasyitemType: RESOURCE
collection-fragment-dailyDAILYgeneric1–3 (×1)MediumitemType: FRAGMENT
collection-scrap-dailyDAILYgeneric50–300 (×50)EasyrewardType: SCRAP
collection-item-dailyDAILYper-item1 (fixed)EasyitemId: {id}
collection-tier-weeklyWEEKLYgeneric1–5 (×1)MediumitemTier: 2
collection-blueprint-weeklyWEEKLYgeneric1–3 (×1)MediumitemType: BLUEPRINT
collection-scrap-weeklyWEEKLYgeneric300–1500 (×150)EasyrewardType: SCRAP
collection-item-weeklyWEEKLYper-item1 (fixed)MediumitemId: {id}
collection-resource-weeklyWEEKLYgeneric15–50 (×5)EasyitemType: RESOURCE
collection-tier-permanentPERMANENTgeneric1–5 (×1)1→3itemTier: 3
collection-item-permanentPERMANENTper-item1 (fixed)HarditemId: {id}, isUnique
collection-scrap-permanentPERMANENTgeneric2000–10000 (×1000)HardrewardType: SCRAP
Content-Aware генерация

COLLECTION блюпринты анализируют реальный контент сезона (предметы в кейсах и рулетках). Если в сезоне нет ресурсов — collection-resource-* блюпринты не генерируются. Скрап-квесты динамически капируются: avgScrapPerDrop × 3 drops/day × periodMultiplier.

SOCIAL (1), SPECIAL (2):

IDCategoryTypeModeTargetDiff
social-referral-permanentSOCIALPERMANENTgeneric1–5 (×1)Medium
special-level-permanentSPECIALPERMANENTgeneric5–20 (×5)Medium
special-streak-weeklySPECIALWEEKLYgeneric3–7 (×1)Medium

Generation Modes

РежимОписаниеВарианты
genericБез привязки к контентуДо 3 (DAILY/WEEKLY), 1 (PERMANENT)
per-caseПо 1 квесту на каждый кейс сезона{caseName} в названии
per-itemПо 1 квесту на предмет из пула (по difficulty){itemName} в названии
Roman Numerals

Когда блюпринт генерирует >1 варианта (generic mode), к названию добавляются римские цифры: "Эрудит I", "Эрудит II", "Эрудит III".

Content-Aware Generation

Генератор анализирует реальный контент сезона через analyzeSeasonContent():

  1. Cases + Spins — все предметы и награды из привязанных кейсов и рулеток
  2. Item deduplication — один предмет может быть в нескольких кейсах; берётся лучший dropChance
  3. Difficulty mapping — dropChance → difficulty: ≥5% = Easy(1), 1-5% = Medium(2), <1% = Hard(3)
  4. Items by type — группировка по itemType (SKIN, BLUEPRINT, FRAGMENT, RESOURCE, BUFF)
  5. Scrap analysis — минимальный/средний/максимальный скрап из наград

COLLECTION per-item блюпринты получают пул предметов по difficulty (DAILY → Easy, WEEKLY → Medium, PERMANENT → Hard).

Скрап-квесты динамически капируются на основе avgScrapPerDrop × ESTIMATED_DROPS_PER_DAY (3) × periodMultiplier.

Placeholder Rewards

Генерируемые квесты получают SCRAP награды по difficulty:

DifficultyReward
Easy (1)50 Scrap
Medium (2)100 Scrap
Hard (3)150 Scrap

Админ настраивает финальные награды в Step 6 Setup Wizard после генерации.

Protection

ДействиеRate LimitAuthValidation
Get questsgeneral (100/min)TelegramGetUserQuestsSchema
Get quest by IDgeneral (100/min)TelegramGetUserQuestByIdSchema
Claim rewardachievementClaim (15/min)Telegram + Active SeasonClaimQuestRewardSchema
Check questgeneral (100/min)Telegram + Active SeasonCheckQuestSchema
Start Rust questgeneral (100/min)Telegram + Active SeasonStartRustQuestSchema
Детали реализации

См. Security Matrix для полного обзора защит.

Edge Cases

Что видит пользователь (UI):

СитуацияUI поведение
RUST квест без стартаКнопка "Начать квест", статус AVAILABLE
Внутренний квест без прогресса"Ожидает прогресса", статус PENDING
Квест с прогрессом"Выполняется...", показан прогресс X/Y
Квест выполненКнопка "Забрать" активна, анимация готовности
Награда полученаСтатус CLAIMED, карточка скрыта
Claim награды (UI)Fade-out анимация 300ms → карточка исчезает из списка
После claimКвесты остаются на месте (не "прыгают" вниз)
Claim последнего квеста на страницеАвтоматический переход на предыдущую страницу
Daily reset прошёлПрогресс сброшен, квест снова IN_PROGRESS
Уникальный уже полученПри claim — статус синхронизируется без ошибки
Квест с подсказкойИконка ⓘ рядом с описанием → модалка с hint при клике
Квест без подсказкиИконка ⓘ не отображается
Квест с difficultyDifficultyBadge рядом с заголовком (1=зелёный, 2=жёлтый, 3=красный)
Квест без difficultyDifficultyBadge не отображается

Отображение наград (RewardIcon):

Тип наградыОтображение
SCRAP / XP / SPКомпонент Currency с иконкой и суммой
ITEM (SKIN/RESOURCE)Изображение предмета 48×48px
ITEM (BLUEPRINT)Изображение targetSkin + оверлей blueprintbase.webp
ITEM (FRAGMENT)Изображение targetSkin + оверлей blueprint_{tier}.webp
ITEM (BUFF)Изображение или иконка Zap (fallback)
CASEИзображение кейса 48×48px
Количество > 1Badge "×N" в правом нижнем углу
Нет изображенияИконка Package (fallback)
Backend Error Codes (для API/тестов)
КодHTTPСообщение пользователю
QUEST_NOT_FOUND404"Квест не найден"
NOT_COMPLETED400"Квест еще не выполнен"
ALREADY_CLAIMED400"Награда уже получена"
UNIQUE_ALREADY_CLAIMED400"Эта награда уже была получена ранее"
REWARD_NOT_FOUND500"Награда не найдена"
ITEM_NOT_FOUND500"Предмет награды не найден"
CASE_NOT_FOUND500"Кейс награды не найден"

3. ADR (Architectural Decisions)

Почему Shared Progress, а не отдельный трекинг?

Проблема: При каждом действии нужно засчитывать прогресс в нескольких квестах одновременно.

Решение: Паттерн Shared Progress — incrementCategoryProgress() находит ВСЕ подходящие квесты и увеличивает прогресс в рамках одной транзакции.

Альтернативы (отклонены):

  • Event sourcing с отложенной обработкой — сложно, задержки в UI
  • Отдельные счетчики на каждый квест — дублирование логики, race conditions

Последствия: Простота интеграции (один вызов из любого домена), атомарность, но нужна транзакция на запись.

Почему Lazy Reset, а не cron?

Проблема: Нужно сбрасывать прогресс DAILY/WEEKLY квестов без блокировки на всю базу.

Решение: Lazy Reset — сброс при первом обращении пользователя. Проверка lastResetAt vs текущего периода.

Альтернативы (отклонены):

  • Cron job с массовым UPDATE — блокировка таблицы, пиковая нагрузка в полночь
  • TTL в Redis — сложность консистентности с PostgreSQL

Последствия: Равномерная нагрузка, но первый запрос дня чуть медленнее.

Почему детерминированная ротация?

Проблема: При случайном выборе квестов разные пользователи видят разные задания — нельзя обсуждать в сообществе.

Решение: Seeded shuffle на основе даты — все видят одинаковые квесты в один день.

Последствия: Единый игровой опыт, возможность обсуждения "квеста дня", но меньше персонализации.

Quiz-Quest Coordination: почему quiz-квесты только generic?

Проблема: Две независимые системы не координированы:

  1. Публикация квизов — случайный выбор 3 квизов/день из неопубликованного пула, отправка в Telegram
  2. Ротация квестов — детерминированный выбор дневных/недельных квестов из пула

Специфичные quiz-квесты (по категории, подкатегории, slug, entityType) были бы часто невыполнимы: если дневной квест требует квиз про оружие, а сегодня опубликованы квизы про еду — квест невыполним.

Решение: Quiz-квесты используют только generic режим ("ответь на любой квиз") с фиксированными таргетами: daily=1, weekly=5, permanent=15. Специфичные quiz-задания (по категории/подкатегории/slug/entityType) будут реализованы как Achievement templates — долгосрочные цели на весь сезон, для которых проблема координации не критична.

Альтернативы (отклонены):

  • Специфичные quiz-квесты как PERMANENT — по-прежнему создают неудобства (ждать нужный квиз) и загромождают пул квестов
  • Координация публикации с ротацией квестов — сложная связность, breaking existing architecture
  • Quiz Catalog в TMA (все квизы доступны без публикации) — меняет бизнес-модель, снижает ценность Telegram-канала

Последствия:

  • Чистое разделение: квесты = широкие задания, достижения = точечные цели
  • Нет проблемы с координацией — любой опубликованный квиз засчитывается
  • PERMANENT_POOL_MAX остаётся 10 (quiz permanent не раздувает пул)

4. Architecture

Flow: Прохождение квиза → Прогресс квеста

Flow: Claim награды

Key Components

КомпонентПутьОписание
QuestServicebackend/src/domains/quests/services/quest.service.tsПолучение квестов с прогрессом, ротация
QuestProgressServicebackend/src/domains/quests/services/quest-progress.service.tsShared Progress — увеличение прогресса
QuestRewardServicebackend/src/domains/quests/services/quest-reward.service.tsВыдача наград
QuestResetServicebackend/src/domains/quests/services/quest-reset.service.tsLazy Reset для DAILY/WEEKLY
QuestRotationServicebackend/src/domains/quests/services/quest-rotation.service.tsStateless deterministic ротация квестов
TelegramSubscriptionServicebackend/src/domains/quests/services/telegram-subscription.service.tsПроверка подписки через Telegram API
QuestControllerbackend/src/domains/quests/controllers/quest.controller.tsUser API контроллер
QuestAdminControllerbackend/src/domains/quests/controllers/quest-admin.controller.tsAdmin API контроллер
Routesbackend/src/domains/quests/routes/quests.routes.tsUser API роуты
Admin Routesbackend/src/domains/quests/routes/admin-quests.routes.tsAdmin API роуты
Schemasbackend/src/domains/quests/schemas/quest.schemas.tsВалидация запросов

5. Database Schema

Models

МодельОписаниеКлючевые поля
QuestКонфигурация квестаtitle, description, hint, type, category, targetProgress, difficulty, rewardId, conditions, isUnique, isPriority
UserQuestПрогресс пользователяuserId, questId, currentProgress, status, lastResetAt, rewardSnapshot
ClaimedUniqueQuestУникальные награды по telegramId/steamIdtelegramId, steamId, questId
RewardНаграда (общая модель)type, amount, amountMax, itemId, caseId
UserQuestExclusionПерсональные исключения (isUnique)telegramId, steamId, questId, seasonId, reason

Reward Audit (rewardSnapshot)

При claim награды в UserQuest.rewardSnapshot сохраняется JSON снимок:

{
"type": "ITEM",
"amount": 1,
"itemId": "item-123",
"itemName": "AK-47 Blueprint",
"itemTier": "TIER_3"
}
Для чего нужен rewardSnapshot

Snapshot фиксирует выданную награду на момент claim. Если квест или награда изменится — аудит сохранит оригинальные значения для истории операций пользователя.

Quest Statuses (Backend)

СтатусОписание
IN_PROGRESSАктивен, прогресс засчитывается
COMPLETEDВыполнен, ожидает claim
CLAIMEDНаграда получена

Quest UI Statuses (Frontend)

Frontend расширяет backend статусы дополнительными состояниями для UX:

UI СтатусУсловиеКнопка / Отображение
AVAILABLERUST квест без startedAt"Начать квест"
PENDINGНе-RUST квест с currentProgress = 0"Ожидает прогресса"
IN_PROGRESScurrentProgress > 0 и < targetProgress"Выполняется..."
COMPLETEDcurrentProgress >= targetProgress, не claimed"Забрать" (активна)
CLAIMEDНаграда полученаНе отображается
Shared Progress vs Explicit Start

RUST квесты требуют явного старта через "Начать квест" — это создаёт Steam сессию и проверяет привязку.

Внутренние квесты (QUIZ, CASES, SOCIAL, etc.) используют Shared Progress — прогресс засчитывается автоматически при первом действии. Статус PENDING показывает, что квест ждёт первого действия пользователя.

Сортировка UI статусов

Квесты сортируются по UI статусу: AVAILABLECOMPLETEDIN_PROGRESSPENDINGCLAIMED.

Это гарантирует, что:

  • RUST квесты готовые к старту — первыми
  • Квесты готовые к claim — вторыми
  • Квесты с прогрессом — перед "ожидающими"

Relationships

Key Indexes

@@index([type])        -- Фильтрация по типу (DAILY, WEEKLY, etc.)
@@index([category]) -- Фильтрация по категории (QUIZ, CASES, etc.)
@@index([isActive]) -- Только активные квесты
@@index([isPriority]) -- Сортировка приоритетных первыми
@@index([startAt, endAt]) -- EVENT квесты в диапазоне дат

6. API Endpoints

МетодЭндпоинтОписаниеDocs
GET/api/questsСписок квестов с прогрессом
GET/api/quests/:idДетали квеста
POST/api/quests/:id/claimПолучение награды
POST/api/quests/:id/checkПроверка выполнения (SOCIAL)
POST/api/quests/:id/startНачать Rust квест

  • Seasons — квесты привязаны к сезону через SeasonQuest, лимиты ротации в Season model
  • Cases — квесты категории CASES отслеживают открытия кейсов
  • Quizzes — квесты категории QUIZ отслеживают прохождение квизов
  • Achievements — похожая механика с условиями и наградами
  • Streaks — SPECIAL квесты с условием streakDays
  • Referrals — SOCIAL квесты на приглашение друзей
  • Rust Integration — квесты категории RUST
  • Inventory — куда попадают ITEM награды