Перейти к основному содержимому

Создание квестов

webapp_banner.jpg

Пример квеста​

Этот упрощённый пример использует формат поставляемого с плагином test_quest.yml.

Создавайте файлы .yml с уникальными именами в plugins/EliteMobs/customquests/ относительно папки сервера. Загрузите квест и указанный в нём контент командой /em reload, затем назначьте квест NPC, как показано ниже.

test_quest.yml

isEnabled: true
customObjectives:
Objective1:
amount: '1'
filename: test_boss.yml
objectiveType: KILL_CUSTOM
customRewards:
- filename=magmaguys_toothpick.yml:amount=1:chance=1
name: "&aKill the Test Boss"
questLore:
- "&cEnd the test boss' reign of terror!"

create_quest_quest.jpg

На снимке показан старый интерфейс книги. /em alt меняет предпочтение меню: игроки Java с этой настройкой получают книги до Minecraft 1.21.6 и диалоги Minecraft в более новых версиях. Игроки Bedrock и выбравшие меню инвентаря используют интерфейс инвентаря.

Этот пример квеста даст игрокам задание убить 1 test_boss.yml. (Фактическое имя босса, отображаемое в трекере квестов, будет взято из поля name:, заданного в test_boss.yml.) А в награду за выполнение квеста они получат 1 Magmaguy's Toothpick.

Все цели активируются одновременно при принятии квеста; ключи Objective1, Objective2 и подобные не задают порядок. Для награды нужно выполнить все цели. По умолчанию после этого квест сдают NPC. При requireQuestTurnIn: false в Quests.yml выполнение целей сразу запускает попытку завершения, включая проверку и расход собираемых предметов. maximumActiveQuests по умолчанию ограничивает число принятых квестов десятью.

Создание пользовательских квестов​

isEnabled​

Задаёт, включён ли квест.

КлючЗначенияПо умолчанию
isEnabledЛогическое значениеtrue
Пример
isEnabled: true

customObjectives​

Задаёт цели квеста.

КлючЗначенияПо умолчанию
customObjectivesОсобый формат [1]нет

Для многофазового босса указывайте файл первой фазы. Прогресс засчитывается при смерти босса, а не при каждой смене фазы. KILL_CUSTOM проверяет имя файла и не использует questLevel как минимальный уровень убитого босса.

Примеры

KILL_CUSTOM:

customObjectives:
Objective1:
amount: '1'
filename: my_cool_boss.yml
objectiveType: KILL_CUSTOM

DIALOG:

customObjectives:
Objective1:
dialog:
- "&a[Dialog NPC] &fCome here often?"
- "&7&oI should eat more apples."
filename: dialog_npc.yml
npcName: Dialog NPC
location: at dialog location.
objectiveType: DIALOG

FETCH_ITEM:

Цели сбора считают соответствующие метки пользовательских предметов EliteMobs в инвентаре. При сдаче все такие цели проверяются по одному снимку инвентаря до удаления предметов и выдачи наград. Если две цели требуют один предмет, нужно суммарное количество: одна стопка не может удовлетворить обе цели одновременно. Выбрасывание предмета может снова сделать выполненную цель незавершённой.

customObjectives:
Objective1:
amount: '99'
itemName: Red Apples
filename: my_quest_item_red_apples.yml
objectiveType: FETCH_ITEM

ARENA:

customObjectives:
Objective1:
objectiveType: ARENA
filename: my_arena.yml
name: "Complete the Arena"

create_quest_objective.jpg

Особый формат [1]

Развернуть таблицу

Пользовательские цели создаются с использованием следующих значений:

КлючОписание
objectiveTypeТип цели: KILL_CUSTOM — убийство пользовательского босса, FETCH_ITEM — сбор пользовательского предмета, DIALOG — разговор с NPC, ARENA — прохождение арены, CLASS_UNLOCK — проверка открытия класса.
filenameОбязательное имя файла .yml босса, предмета, NPC для разговора, арены или наставника класса. Указывайте загруженное определение, а не отображаемое имя. Цель без filename либо с отсутствующим или неизвестным objectiveType отключает весь квест с предупреждением в консоли. Неверный CLASS_UNLOCK остаётся в квесте, но выполнить его нельзя. Исправьте все предупреждения до выдачи квеста.
amountПоложительное целое число боссов или предметов; по умолчанию 1. Значение меньше 1 отключает квест. Для DIALOG, ARENA и CLASS_UNLOCK цель равна единице, это поле игнорируется.
dialogТолько для DIALOG — реплики, которые NPC произносит, когда игрок с ним разговаривает.
locationТолько для DIALOG — произвольная текстовая подсказка о том, где находится NPC; показывается как $location в строке-сводке меню квестов.
name / npcName / itemNameНеобязательные псевдонимы подписи для FETCH_ITEM, DIALOG, ARENA и CLASS_UNLOCK. Задавайте только один. Все переводятся и позволяют использовать особую формулировку или скрыть информацию. Без замены FETCH_ITEM использует переведённое имя предмета, а DIALOG — имя NPC. KILL_CUSTOM использует имя из конфигурации босса.
classТолько CLASS_UNLOCK: ID формы класса, например adventurer.

Задавайте непустую таблицу customObjectives с уникальным ключом для каждой цели (Objective1, Objective2, ...). Имена полей чувствительны к регистру, типы целей используют значения в верхнем регистре из таблицы. Старые строки вида KILL_CUSTOM:filename=X.yml:amount=Y автоматически преобразуются в новый формат при первой загрузке и сохраняются на диск.

У подписей целей отдельные записи перевода: имя файла квеста и путь вроде customObjectives.Objective1.itemName. Переведите эту запись в языковом CSV, даже если сам предмет уже переведён. Если перевода нет, остаётся исходная подпись, чтобы не раскрывать скрытое имя предмета. Исходный текст остаётся в YAML квеста, существующие переводы сохраняются.

Поведение FETCH_ITEM

FETCH_ITEM распознаёт метку имени файла предмета, а не материал, видимое имя или описание. Учитываются предметы, полученные до принятия, в том числе в слотах брони и второй руки. Принятие, подбор или выбрасывание подходящих предметов и награды квестов запускают пересчёт на следующем тике. Другие изменения инвентаря могут отразиться не сразу, но при сдаче он всегда проверяется заново. При успехе нужные предметы расходуются; нехватка суммарного количества отменяет сдачу без частичного изъятия.

DIALOG продвигается при взаимодействии с подходящим NPC, до открытия его обычного меню. Дочитывать диалог не требуется. location — только текстовая подсказка, не координаты компаса. ARENA засчитывает прохождение указанной арены при активном квесте; предыдущие прохождения не учитываются.


Цели открытия класса​

CLASS_UNLOCK проверяет класс, открытый через расширенную боевую систему. Сам класс не выдаётся. Например:

customObjectives:
Objective1:
objectiveType: CLASS_UNLOCK
class: adventurer
filename: class_trainer_adventurer.yml

class должен обозначать существующую форму класса. filename направляет отслеживание к наставнику NPC; name необязательно заменяет подпись. Цель равна единице и распознаёт ранее открытый класс, даже если он не выбран сейчас. Развитие классов должно быть доступно; открытие проверяется повторно при завершении. Неверный класс или отсутствующее имя файла наставника оставляет невыполнимую цель, а не пропускается.

Отслеживание и отказ​

Игрок может отслеживать только один квест. При autoTrackNextQuestOnCompletion: true в Quests.yml завершение отслеживаемого квеста выбирает другой активный квест с разрешённым отслеживанием на следующем тике. questAutoTrackNextMessage поддерживает $questName. autoTrackQuestsOnAccept тоже включён по умолчанию, но сейчас использует переключатель: принятие квеста при уже включённом отслеживании может остановить его вместо смены цели. При необходимости включите отслеживание снова в меню.

Компас ищет поддерживаемые места: пользовательских боссов, NPC для разговора или наставников, а также боссов и сундуки, в таблицах лута которых есть нужный предмет. Он не находит все возможные источники предметов; у целей арены и динамического убийства нет отдельного поиска места. Для другого мира он может показать подходящий прямой портал или название мира, но не гарантирует проходимый маршрут. Отсутствие места назначения не мешает прогрессу целей.

Обычный отказ требует второго подтверждения. Текст и подсказка задаются через questAbandonConfirmationText и questAbandonConfirmationHover. Отказ удаляет активный квест и его отслеживание, но не запускает блокировку завершения questLockoutMinutes и не выдаёт маркер завершения. Квест можно принять снова при выполнении обычных условий.

Маркеры квестов NPC индивидуальны для каждого игрока и видны в пределах 30 блоков. Компас показывает направление по высоте. Во время диалога через боссбары область занята исключительно им: другие управляемые полосы скрываются, а старая опция hideKeyedBossBarsDuringQuestDialogue удаляется. hideQuestScoreboardDuringQuestDialogue отдельно управляет боковой панелью.

В Java приседание сначала показывает текущую страницу целиком, затем переключает дальше. Диалог накладывает Замедление III не более чем на 30 секунд, а не обездвиживает игрока. Неотменённый урон больше нуля закрывает экраны и диалог квеста. Bedrock получает этот диалог в чате. Для оформления нужны соответствующие ресурсы ресурс-пака.

customRewards​

Задаёт награды за квест.

КлючЗначенияПо умолчанию
customRewardsУниверсальный формат лута EliteMobsнет
Пример
customRewards:
- currencyAmount=50:amount=1:chance=0.05
- material=COOKED_COD:amount=3:chance=1.0
- filename=magmaguys_toothpick.yml:amount=1:chance=1.0

create_quest_rewards.jpg

Пользовательские квесты не создают записи наград автоматически. Если customRewards пуст, эта таблица не выдаёт предметов или валюты; отдельно заданные команды завершения всё равно выполняются. Автоматические записи наград относятся к динамическим квестам.

Масштабируемые предметы наград используют выбранный уровень динамического подземелья или текущий боевой уровень, с вероятностью 10% получить ещё один уровень. Фиксированные и ограниченные предметы сохраняют обычные правила масштабирования. questLevel не задаёт фактический уровень предмета.

Награды за квест выдаются напрямую: предметы попадают сразу в инвентарь игрока (всё, что не помещается, выбрасывается ему под ноги), а валюта добавляется к его балансу. Чтобы выполнять команды при завершении, используйте questCompleteCommands, а не запись лута command=.

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


questAcceptPermission​

Требует один маркер завершения квеста EliteMobs для принятия. Обычное право с тем же именем не удовлетворяет проверке.

КлючЗначенияПо умолчанию
questAcceptPermissionСтроканет
Пример
questAcceptPermission: elitequest.my_permission

questAcceptPermissions​

Требует все перечисленные маркеры завершения EliteMobs. Если также задан questAcceptPermission, его маркер тоже обязателен.

КлючЗначенияПо умолчанию
questAcceptPermissionsСписок строкнет
Пример
questAcceptPermissions: 
- elitequest.my_previous_quest_one.yml
- elitequest.my_previous_quest_two.yml

questLockoutPermission​

Задаёт маркер, выдаваемый после успешного завершения. Он может открывать следующие квесты и при нулевом или отрицательном questLockoutMinutes запрещает повтор этого квеста. Отсутствие маркера не отключает положительную блокировку по времени.

КлючЗначенияПо умолчанию
questLockoutPermissionСтроканет
Пример
questLockoutPermission: elitequest.my_quest.yml

questLockoutMinutes​

Задаёт, сколько минут игроку придётся ждать, прежде чем он сможет выполнить квест снова.

КлючЗначенияПо умолчанию
questLockoutMinutesЦелое число-1 (правило маркера ниже)

Существуют две системы блокировки, и этот ключ решает, какая из них используется:

  • Любое значение выше 0 использует трекер блокировки по времени. Игрок заблокирован для этого квеста на указанное число минут после его сдачи, ему сообщается, сколько осталось, когда он пытается взять квест снова, а questLockoutPermission игнорируется при проверке доступности.
  • 0 или меньше откатывается на устаревший маркер questLockoutPermission, который выдаётся навсегда при завершении. Если questLockoutPermission тоже не задан, квест остаётся повторяемым.

Если заданы оба поля и время положительно, маркер всё равно выдаётся, но исчезает по истечении этого времени. Следующий квест, которому нужен этот маркер, следует принять до его истечения. Временная блокировка хранится по имени файла квеста отдельно от маркера предварительных условий.

Пример
questLockoutMinutes: 60

name​

Задаёт имя квеста. Принимает цветовые коды.

КлючЗначенияПо умолчанию
nameСтрокапусто
Пример
name: "&aMy Great Quest Name"

questLore​

Задаёт описание (lore) квеста, которое будет отображаться во внутриигровом меню квестов.

КлючЗначенияПо умолчанию
questLoreСписок строкнет
Пример
questLore:
- "Interesting lore sentence."
- "Yet another interesting lore sentence."

create_quest_lore.jpg


temporaryPermissions​

Выдаёт настоящие права Bukkit при принятии квеста и повторно применяет их при восстановлении активного квеста после входа. Завершение квеста или отказ от него снимает эти права, а выход с сервера освобождает их до следующего входа. Каждый квест выдаёт свои узлы отдельно, поэтому два активных квеста могут использовать один узел: завершение одного из них оставляет узел, выданный другим.

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

КлючЗначенияПо умолчанию
temporaryPermissionsСписок строкнет
Пример
temporaryPermissions:
- elitequest.item_that_should_drop_only_during_quest.yml

questAcceptDialog​

Задаёт реплики, которые появляются в чате при принятии квеста.

Когда включены боссбары диалогов квестов, этот список одновременно служит диалогом, который квестодатель произносит в диалоговом окне до принятия квеста. Если он пуст, для этого диалога вместо него используется questLore.

КлючЗначенияПо умолчанию
questAcceptDialogСписок строкнет
Пример
questAcceptDialog:
- "My hero! You are so helpful!"
- "I wish you the best of luck!"

create_quest_accept.jpg


questCompleteMessage​

Задаёт диалог сдачи. При useQuestDialogueBossBars в Quests.yml он может появиться до открытия меню сдачи; иначе показывается при успешном завершении. Недавно показанный диалог сдачи не повторяется при завершении. Bedrock получает текст в чате. Само появление диалога не доказывает выдачу награды.

КлючЗначенияПо умолчанию
questCompleteMessageСписок строкнет
Пример
questCompleteMessage:
- "My hero! You have completed my difficult quest!"
- "As a reward you can have this loaf of bread!"

create_quest_complete.jpg


questCompleteCommands​

Задаёт команды, которые будут выполнены при завершении квеста. Команды отправляются из консоли, поэтому не включайте ведущий слеш и не рассчитывайте на наличие у игрока прав на них.

Поддерживаемые плейсхолдеры: $player для имени игрока, $getWorld для имени мира, в котором он находится, и $getX, $getY, $getZ для координат его местоположения.

КлючЗначенияПо умолчанию
questCompleteCommandsСписок строкнет
Пример
questCompleteCommands:
- say $player has finished a quest at $getX, $getY, $getZ!
- give $player diamond 1

create_quest_commands.jpg


turnInNPC​

Задаёт файл NPC для сдачи. Он может отличаться от квестодателя; если поле пропущено, используется первоначальный NPC. Отдельный принимающий NPC должен использовать interactionType: CUSTOM_QUEST_GIVER, а список его предложений может быть пустым.

КлючЗначенияПо умолчанию
turnInNPCИмя файланет
Пример
turnInNPC: my_cool_quest_npc.yml

Выдача квестов​

Чтобы назначить квест NPC, который будет выдавать его игрокам, нужно настроить файл NPC, а не файл квеста.

В файле NPC (plugins/EliteMobs/npcs/) добавьте:

interactionType: CUSTOM_QUEST_GIVER
questFileName:
- my_quest.yml

Для NPC, которые выдают несколько квестов:

interactionType: CUSTOM_QUEST_GIVER
questFileName:
- quest_one.yml
- quest_two.yml

Используйте список YAML даже для одного квеста: скаляр questFileName: my_quest.yml не загружается как список предложений. Для открытия списка требуется interactionType: CUSTOM_QUEST_GIVER.

Подробнее о настройке NPC см. документацию по созданию NPC.


trackable​

Разрешает ручное и автоматическое отслеживание компасом. false не останавливает прогресс целей, выдачу наград или временные панели прогресса.

КлючЗначенияПо умолчанию
trackableЛогическое значениеtrue
Пример
trackable: true

questLevel​

Задаёт уровень квеста. Это всего лишь визуальный ориентир, чтобы игроки могли понять, насколько сложным будет квест. Это никак не изменяет уровни босса, предметов или другие уровни.

КлючЗначенияПо умолчанию
questLevelЦелое число0
Пример
questLevel: 10

create_quest_level.jpg


questAcceptSound​

Задаёт звук, который воспроизводится при принятии квеста. Можно воспроизводить как звуки Minecraft, так и звуки из ресурс-пака. Когда он не задан, EliteMobs вместо него проигрывает глобальный звук принятия квеста из SoundsConfig.

КлючЗначенияПо умолчанию
questAcceptSoundСтроканет
Пример
questAcceptSound: entity.experience_orb.pickup

create_quest_level.jpg


questCompleteSound​

Задаёт звук, который воспроизводится при завершении квеста (его сдаче). Можно воспроизводить как звуки Minecraft, так и звуки из ресурс-пака. Когда он не задан, EliteMobs вместо него проигрывает глобальный звук завершения квеста из SoundsConfig.

КлючЗначенияПо умолчанию
questCompleteSoundСтроканет
Пример
questCompleteSound: entity.player.levelup

create_quest_level.jpg


Поддержка локализации​

Следующие поля поддерживают локализацию для многоязычных серверов:

  • name
  • questLore
  • questAcceptDialog
  • questCompleteMessage
  • Внутри каждой записи customObjectives: dialog, name, npcName, itemName и location

Это позволяет вам предоставлять переводы для разных языков на вашем сервере.


Разрешения​

Как упоминалось в таблицах выше, права обычно представляют собой Strings или String Lists. Но давайте рассмотрим подробнее, как вы будете использовать их для блокировки и разблокировки квестов.

Важно: questAcceptPermission и questAcceptPermissions проверяют внутренние маркеры EliteMobs, а не обычные права. Завершение квеста с подходящим questLockoutPermission создаёт маркер. Выдача одноимённого права через LuckPerms не открывает квест. temporaryPermissions, напротив, выдаёт настоящие права, пока квест активен.

Допустим, вы создаёте quest_3 в запланированной серии квестов и не хотите, чтобы игроки могли взять quest_3 до того, как они завершат quest_2. Мы настроили бы файл квеста так:

questAcceptPermission: elitequest.quest_2.yml
questLockoutPermission: elitequest.quest_3.yml

Квест 2 должен выдавать elitequest.quest_2.yml через свой questLockoutPermission. Квест 3 требует этот маркер через questAcceptPermission. При неположительной длительности по умолчанию завершение квеста 3 выдаёт постоянный маркер и запрещает повтор. Предложение уже активного квеста другим NPC не создаёт вторую независимую копию.

Если вы хотите сделать квест, который становится доступен только после того, как игроки завершат серию квестов, то вы настроили бы файл квеста так:

questAcceptPermissions: 
- elitequest.quest_2.yml
- elitequest.quest_3.yml
- elitequest.quest_4.yml

Чтобы принятие разрешало обычную генерацию предмета, добавьте узел в temporaryPermissions и укажите его же в поле permission предмета.

Например, мы откроем наш файл квеста и добавим следующее:

temporaryPermissions: 
- elitequest.my_cool_item.yml

Затем мы откроем файл предмета, в нашем случае my_cool_item.yml, и добавим следующее:

permission: elitequest.my_cool_item.yml

Теперь, пока квест активен, он выдаёт узел, проверяемый при обычной генерации предметов, и снимает его при завершении квеста или отказе от него.

Группы и общий зачёт убийств​

Квесты остаются личными: вступление в группу не принимает, не сдаёт и не награждает квесты за других. Когда участнику засчитывается убийство, другие участники онлайн в том же мире и в пределах sharedProgressRange (по умолчанию 128 блоков в Party.yml) также продвигают свои подходящие активные цели убийства, включая конкретных пользовательских боссов.

Предметы сбора, диалоги NPC и цели арен не разделяются. Получателям нужны собственный подходящий активный квест и загруженные данные игрока. Если их матч прошёл этап ожидания или запуска, они должны входить в его первоначальный состав участников. Отдельного сравнения их инстанса с инстансом источника убийства нет; близость в одном мире всё равно обязательна.

Динамические квесты​

Динамические квесты — это процедурно генерируемые квесты, которые автоматически создаются и обновляются EliteMobs. В отличие от пользовательских квестов, заданных в конфигурационных файлах, динамические квесты не требуют ручной настройки и адаптируются к прогрессу каждого игрока.

Как они работают​

  • Квестодатель: используйте NPC с interactionType: QUEST_GIVER. Его предложения берутся из динамического пула, а не questFileName.
  • Тир: ограничьте боевой уровень диапазоном 1–100, разделите на пять целочисленно, затем ограничьте тир диапазоном 1–20. Уровень 45 даёт тир 9. Тир задаёт шаблоны и число убийств, а минимальный уровень врагов берётся из ограниченного боевого уровня игрока.
  • Три шаблона на тир: каждый выбирает тип сущности из questEntityTypes в Quests.yml. Неизвестные типы сущностей и типы без свойств мобов EliteMobs пропускаются с предупреждением, а список без пригодных записей отключает предложения динамических квестов. Каждый шаблон также выбирает число убийств от tier + 1 до tier * 10 включительно. Подходящий Elite Mob должен быть не ниже минимального уровня; обычный моб Minecraft не считается.
  • Обновление: все шаблоны обновляются каждые 1200 тиков, примерно 60 секунд при 20 TPS. Существующие квесты и прогресс сохраняются. Меню объединяет их с тремя текущими шаблонами, исключая повторные ID шаблонов, поэтому записей может быть больше трёх.
  • Динамические подземелья: вход меняет минимальный уровень врагов, показанный уровень и имя существующих динамических квестов на выбранный уровень в пределах 1–100. Число целей и прогресс сохраняются. Валютная награда не пересчитывается.
  • Награды: валюта фиксируется при создании предложения как floor(questLevel / 2 * targetKillCount). Предмет создаётся обычной системой лута при сдаче, по выбранному уровню динамического подземелья или текущему боевому уровню, с вероятностью 10% прибавить один и итоговым ограничением 1–100. Доступность предметов и правила масштабирования сохраняются; предпросмотр делает отдельный случайный выбор.