Повторяемый квест¶
Квест, который можно проходить много раз: ежедневное задание, фарм-миссия, испытание на время. Один и тот же квестовый файл, новый прогресс каждый раз.
В InkQuest для этого есть одно поле — repeatable: true. Завершённый квест можно выдать повторно, и его прогресс автоматически сбросится.
Зачем нужен этот паттерн¶
- Ежедневки и фарм. «Принеси 10 кожи», «убей босса в шахте» — повторяемый источник опыта и наград.
- Тренировка/обучение. Туториальный квест, который игрок может перепройти, если что-то забыл.
- Серверные ивенты с многоразовым участием. «Победи дракона выходного дня» — каждые выходные новая попытка.
- Ачивменты с прогрессом. «Пройди 100 раз» — каждое прохождение засчитывается отдельной попыткой.
Шаг 1. Создаём квест с флагом repeatable¶
data/daily/quests/courier.json:
{
"version": 3,
"variant": 0,
"title": "Доставка из таверны",
"description": "Каждый день нужен курьер. Награда — серебро.",
"repeatable": true,
"tasks": {
"deliver": {
"title": "Доставить посылку",
"condition": {
"success": { "type": "predicate", "predicate": "daily:package_delivered" }
},
"on": {
"success": { "functions": ["daily:pay_silver"] }
}
}
},
"stages": [["deliver"]]
}
Один флаг — и квест становится перевыдаваемым.
Шаг 2. Описываем предикат завершения¶
data/daily/predicates/package_delivered.json — проверяет scoreboard-флаг игрока, который ставит командный блок в сундуке-цели:
{
"condition": "minecraft:entity_scores",
"entity": "this",
"scores": {
"daily.courier_delivered": { "min": 1 }
}
}
data/daily/functions/init.mcfunction (вызови один раз через #minecraft:load):
В сундуке-цели поставь командный блок: scoreboard players set @p daily.courier_delivered 1.
Шаг 3. Описываем функцию награды¶
data/daily/functions/pay_silver.mcfunction:
give @s minecraft:iron_ingot 8
tellraw @s {"text":"Заказ выполнен. Серебро в кармане.","color":"gold"}
scoreboard players set @s daily.courier_delivered 0
Последняя строка важна: при следующем заходе на квест scoreboard-флаг должен начинаться с нуля, иначе квест завершится моментально на старте.
Шаг 4. Выдаём первый раз и проверяем повтор¶
Игрок проходит, квест уходит в «Завершённые → success». Награда выдана.
Чтобы выдать тому же игроку повторно:
InkQuest видит, что квест уже завершён + repeatable: true → сам сбрасывает старый прогресс, потом создаёт новую запись. Игрок получает чистый квест: задача deliver снова active, награды можно получить заново.
Если попробуешь перевыдать активный (незавершённый) повторяемый квест — система откажет. Это защита от случайного стирания текущего прогресса. Сначала пусть игрок завершит или явно дропнет.
Проверка¶
- Выдай повторяемый квест:
/quest give @s daily:courier. - Заверши вручную:
/scoreboard players set @s daily.courier_delivered 1. - На следующем тике квест уходит в «Завершённые».
- Выдай ещё раз:
/quest give @s daily:courier— квест снова появляется в «Активных» с чистым прогрессом. ✅ - Попробуй выдать ещё раз, не завершая — должен прийти отказ (
already_tracked).
Чем repeatable отличается от обычной выдачи¶
Без repeatable команда /quest give для завершённого квеста выдаёт ошибку «квест уже завершён». С repeatable: true — эта ошибка не появляется, InkQuest сначала сбрасывает старый прогресс, потом создаёт новый.
| Состояние квеста | Без repeatable |
С repeatable: true |
|---|---|---|
| не выдан | выдаст | выдаст |
| активен | ошибка «уже отслеживается» | ошибка «уже отслеживается» |
завершён success/failure/skipped |
ошибка «уже завершён» | сбросит и выдаст заново |
Команды, Quest Scroll и любые внешние вызовы работают одинаково — логика одна.
Расширения¶
Ежедневный квест¶
Если квест должен выдаваться раз в сутки автоматически — повесь раздачу на циклическую функцию датапака.
data/daily/functions/distribute.mcfunction:
Триггерь её, когда время в мире переходит на утро. Самый простой способ — через тиковую функцию + проверку времени:
data/daily/functions/tick.mcfunction:
execute if score #day_phase daily.state matches 0 if predicate daily:is_morning run function daily:distribute
execute if score #day_phase daily.state matches 0 if predicate daily:is_morning run scoreboard players set #day_phase daily.state 1
execute if predicate daily:is_night run scoreboard players set #day_phase daily.state 0
Предикат data/daily/predicates/is_morning.json:
Предикат data/daily/predicates/is_night.json:
Регистрируем тиковую функцию в data/minecraft/tags/functions/tick.json:
Заведи scoreboard для фазы дня (раз в #minecraft:load):
Каждое утро всем онлайн-игрокам автоматически выдастся (или перевыдастся) daily:courier. Логика «фазы дня» гарантирует, что раздача случится один раз за сутки, а не каждый тик утра.
Кулдаун между прохождениями¶
Если квест повторяемый, но не «раз в сутки», а «не чаще раза в час» — заведи scoreboard с временем последнего прохождения. В on.success:
В тиковой функции — декрементируй:
execute as @a[scores={daily_courier_cooldown=1..}] run scoreboard players remove @s daily_courier_cooldown 1
Раздачу повторной попытки сделай отдельной командой или предметом, который проверяет cooldown:
Перевыдача через свиток (бесконечный источник заданий)¶
Свитки квестов и повторяемые квесты — идеальная пара. Игрок копит/покупает свитки daily:courier, и каждый свиток даёт ему новую попытку. Логика проверки «выдан/завершён» уже встроена в свиток.
Цепочка повторяемых квестов¶
Можно сделать целую серию ежедневок, связанных через after: пройди A → откроется B → пройди B → откроется C. И всё это — повторяемое, чтобы цикл можно было прокрутить заново.
⚠️ Тут важно: after смотрит на статус success зависимости. Если первый квест в цепочке — repeatable, и игрок прошёл его дважды, у него всё равно один статус: success. Зависимый квест откроется один раз. Если хочешь, чтобы цикл перезапускался полностью — дропни все квесты цепочки скриптом перед новым запуском.
Тротлинг через require.tags¶
Если хочешь, чтобы повторная выдача требовала специальный тег (например, «купил билет на сегодня»):
Тег ставится покупкой/действием, при выдаче квеста снимается функцией. Игрок не сможет «спамить» повторами без билета.
Подводные камни¶
- Сброс при повторной выдаче — атомарный. Снаружи это выглядит как мгновенное «обнулил и выдал заново»; визуальных артефактов нет.
repeatable— серверное поле. Клиенту не передаётся, в UI квестовой книги никак не отображается. Если хочешь «значок повторяемости» — добавь его вtitleчерез стилизацию ("§b[Ежедневка] Доставка").- Все данные предыдущего прохождения теряются. Статус задач, прогресс scoreboard-условий, флаги
on.load— всё обнуляется. Если тебе нужна «история прохождений» — храни её отдельно: счётчик в scoreboard, добавляемый вon.success(scoreboard players add @s courier_completed 1). on.unloadсработает при сбросе. Перевыдача = drop + give, поэтомуon.unloadстарой задачи сработает передon.loadновой. Если вon.unloadесть побочные эффекты — учитывай это.- Predicate'ы продолжают «срабатывать» при перевыдаче. Если scoreboard-флаг успеха не сбрасывается в
on.success(или другим способом), новая итерация квеста завершится сразу на первом же тике. Сбрось флаг — либо в функцииon.success, либо в функции, которая раздаёт квест.
См. также¶
- Справочник команд — команда
/quest giveи её аргументы - Предметы — Quest Scroll, отлично сочетается с repeatable
- Хуки жизненного цикла задачи — про
on.loadиon.unload