Перейти к содержанию

Ожидание события

Следующий квест должен открыться не сразу после предыдущего, а когда что-то произойдёт в мире: наступит ночь, игрок дойдёт до места, выполнится ритуал.

Зависимости after выдают следующий квест сразу по завершении предыдущего. Если переход должен быть отложенным — добавь в исходный квест задачу-ждуна.


Зачем нужен этот паттерн

  • Драматическая пауза. «Сделай дело и жди сигнала» — классический сюжетный приём.
  • Синхронизация с миром. Следующий квест зависит от времени суток, погоды, фазы луны, координат игрока.
  • Темп истории. Не вываливать на игрока следующее задание сразу — дать ему отдышаться или поисследовать локацию.

Шаг 1. Добавляем финальный этап-ждун в исходный квест

Берём обычный квест с задачей guide_caravan и добавляем после неё второй этап с одной задачей. Условие этой задачи — нужное событие.

{
  "version": 3,
  "variant": 0,
  "title": "Караван на закате",
  "description": "Караван должен пройти за стену до темноты. Дальше — только ждать.",
  "tasks": {
    "guide_caravan": {
      "title": "Проводить караван за стену"
    },
    "wait_for_signal": {
      "title": "Дождаться ночи",
      "description": "На башне обещали зажечь огонь, когда город уснёт.",
      "condition": {
        "success": { "type": "predicate", "predicate": "ch1:is_night" }
      }
    }
  },
  "stages": [["guide_caravan"], ["wait_for_signal"]]
}

Пока задача wait_for_signal не выполнится — квест не закроется, и зависимые от него квесты не откроются.


Шаг 2. Описываем условие ожидания

В data/ch1/predicates/is_night.json:

{
  "condition": "minecraft:time_check",
  "value": { "min": 13000, "max": 23000 },
  "period": 24000
}

Условие срабатывает, когда время в мире от 13000 до 23000 тиков — то есть ночью.

Любой native Minecraft predicate подойдёт: проверка координат, биома, погоды, инвентаря, прокачки и т.д.


Шаг 3. Зависимый квест — обычная цепочка

{
  "version": 3,
  "variant": 0,
  "title": "Огонь над городом",
  "description": "Башня зажгла сигнал. Пора отвечать.",
  "after": [["ch1:caravan_at_sunset"]],
  "tasks": {
    "answer_signal": { "title": "Подняться на башню" }
  },
  "stages": [["answer_signal"]]
}

Никаких отличий от обычной цепочки. Магия — в том, что предыдущий квест теперь завершается не мгновенно, а только после наступления ночи.


Проверка

  1. Выдай первый квест: /quest give @s ch1:caravan_at_sunset.
  2. Закрой первую задачу: /quest complete @s ch1:caravan_at_sunset task guide_caravan success.
  3. В книге появится второй этап с задачей «Дождаться ночи».
  4. Подожди наступления ночи (или /time set night) — задача завершится сама, квест закроется, второй квест выдастся автоматически.

Когда задача-ждун не подходит

Иногда ожидание не должно быть видимым: между сценами герой «разойдётся по делам», без записи в дневнике. Тогда задача-ждун ломает темп — игрок видит в HUD «Дождаться ночи», и это разрушает иммерсию.

Для таких случаев есть две альтернативы.

Альтернатива А: тиковая функция датапака

Простейший вариант. Ставим игроку тег, тиковая функция проверяет условие и выдаёт следующий квест.

В первом квесте добавляем тег при завершении:

"on": {
  "success": {
    "tags": ["ch1.waiting_for_night"]
  }
}

В файле data/ch1/functions/wait_for_night.mcfunction:

execute as @a[tag=ch1.waiting_for_night] at @s if predicate ch1:is_night run function ch1:advance_to_beacon

В data/ch1/functions/advance_to_beacon.mcfunction:

tag @s remove ch1.waiting_for_night
quest give @s ch1:beacon_over_city

В data/minecraft/tags/functions/tick.json регистрируем:

{
  "values": ["ch1:wait_for_night"]
}

Готово: как только наступит ночь у игрока с тегом — он получит следующий квест, без задачи в HUD.

Минус: проверка каждый тик у всех помеченных игроков. Для редких переходов overkill, но для коротких ожиданий (минуты) — норм.

Альтернатива Б: цепочка advancement'ов

Более экзотично, но дешевле по нагрузке. Vanilla advancement сам отслеживает условие у конкретного игрока и запускает функцию датапака как награду.

Шаг 1. Advancement-маркер «игрок ждёт». Без trigger'а, без награды — нужен только как «ключ», который выдаётся вручную.

data/ch1/advancements/wait_for_night_armed.json:

{
  "criteria": {
    "impossible": {
      "trigger": "minecraft:impossible"
    }
  }
}

Шаг 2. Advancement-«стрелочник» с trigger'ом minecraft:tick и player-predicate'ом на нужное событие. Выдаётся автоматически, как только у игрока есть parent-маркер и сработал predicate.

data/ch1/advancements/wait_for_night_complete.json:

{
  "parent": "ch1:wait_for_night_armed",
  "criteria": {
    "tick": {
      "trigger": "minecraft:tick",
      "conditions": {
        "player": [
          {
            "condition": "minecraft:time_check",
            "value": { "min": 13000, "max": 23000 },
            "period": 24000
          }
        ]
      }
    }
  },
  "rewards": {
    "function": "ch1:advance_to_beacon"
  }
}

Шаг 3. Функция, выдающая следующий квест и снимающая маркер:

data/ch1/functions/advance_to_beacon.mcfunction:

quest give @s ch1:beacon_over_city
advancement revoke @s only ch1:wait_for_night_armed

Шаг 4. В on.success финальной задачи предыдущего квеста ставится маркер:

"on": {
  "success": {
    "functions": ["ch1:arm_night_wait"]
  }
}

data/ch1/functions/arm_night_wait.mcfunction:

advancement grant @s only ch1:wait_for_night_armed

Vanilla сам отслеживает условие у игроков с выданным parent'ом. Никаких тиковых функций, никаких записей в дневнике.

Минус: больше файлов, выше порог входа.


Какой способ когда

Сценарий Способ
Хочется, чтобы игрок видел и понимал, чего ждёт Задача-ждун (шаги 1-3)
Ожидание короткое, нужно «незаметно перевести сцену» Тиковая функция (Альтернатива А)
Ожидание долгое или редкое, важна производительность Advancement-цепочка (Альтернатива Б)

Подводные камни

  • Невидимое ожидание — это gap для игрока. Если переход происходит «само» и игрок не понимает, чего от него ждут — он застрянет. Скрытое ожидание оправдано только для коротких или сюжетно подразумеваемых задержек («приди завтра»).
  • Статус квеста InkQuest нельзя проверить из predicate. Vanilla player predicate не знает про активные/завершённые квесты — поэтому в advancement-цепочке маркер ожидания приходится создавать самим (через advancement-«ключ» или scoreboard-тег). Это не баг, а граница между ванильной системой и InkQuest.
  • Игрок офлайн → задача-ждун замёрла. condition проверяется только для игроков на сервере. Это норма: если у тебя «дождаться полнолуния», игрок просто увидит, что условие сработало, когда вернётся.

Расширения

Таймер «реального времени»

Если нужно ждать N секунд игрового времени (не суток) — комбинируй задачу-ждун с условием score. Заведи objective dummy, в on.load запиши туда 0, в on.tick прибавляй 1. Условие score >= 1200 сработает через минуту (1200 тиков). Похожая механика, но в обратную сторону, описана в Задача с двумя исходами, раздел «Шаблон A.1 — миссия на время».

Цепочка ожиданий

Если переходов несколько — каждый со своим условием — оформи их отдельными этапами в одном квесте: [["guide"], ["wait_night"], ["wait_signal"], ["wait_dawn"]]. Каждый этап откроется по своему условию.

Ожидание группы игроков

Если нужно дождаться, пока все активные участники события дойдут до точки — комбинируй с глобальным счётчиком: каждый игрок инкрементит счётчик при входе в зону, условие проверяет score >= N.


См. также