Создание контента (Дата-паки)
Для создания квестов и груп есть инструмент созданый на Googl ai studio QuestForge
Как сделать моба квестодателем
Контент в данном моде добавляется по средством дата паков, потому надо создать новый дата пак или редактировать новый. Рассмотрим пример добавления моба на примере "guardvillagers:guard"
data_pack_name -> data -> guardvillagers -> quest_givers -> guard.jsonСодержимое guard.json
{
"pool": ["name_pool_1", "name_pool_2", "name_pool_1"]
}
При генерации квеста пул выбирается случайно.
И всё готово!
Как создать группу
Квест не может существовать без группы, в ней хранится информация про задания и награды награды.
Рассмотрим готовый пример example_group.json которой должен находится по пути
data_pack_name -> data -> guardvillagers* -> groups -> example_group.json* - Тут может быть любой namespace но для наглядности используемguardvillagers.example_group.json:
{
"tasks": [
{
"task_type": "thequestforge:collect",
"value": 40,
"target": "minecraft:iron_pickaxe",
"multiplier": false,
"weight": 20,
"count": {
"min": 1,
"max": 1
},
"enchantment_count": {
"min": 1,
"max": 3
},
"enchantment": [
{
"id": "minecraft:sharpness",
"level": {
"min": 1,
"max": 1
},
"weight": 10
},
{
"id": "minecraft:unbreaking",
"level": {
"min": 1,
"max": 3
},
"weight": 10
},
{
"id": "minecraft:fortune",
"level": {
"min": 1,
"max": 14
},
"weight": 10
}
]
},
{
"task_type": "thequestforge:kill",
"value": 5,
"target": "minecraft:zombie",
"multiplier": true,
"weight": 17,
"count": {
"min": 15,
"max": 23
}
},
{
"task_type": "thequestforge:collect",
"value": 1,
"target": "minecraft:potion",
"multiplier": false,
"weight": 10,
"count": {
"min": 1,
"max": 2
},
"tag": "{Potion:\"minecraft:healing\"}"
}
],
"rewards": [
{
"target": "minecraft:diamond",
"multiplier": true,
"price": 12,
"weight": 20,
"count": {
"min": 1,
"max": 1
}
},
{
"target": "minecraft:diamond_pickaxe",
"multiplier": false,
"price": 20,
"weight": 10,
"count": {
"min": 1,
"max": 1
},
"tag": "{display:{Name:'{\"text\":\"Exemplae pickaxe\",\"italic\":false}'}}",
"enchantment": [
{
"id": "minecraft:efficiency",
"level": {
"min": 1,
"max": 2
},
"weight": 10
},
{
"id": "minecraft:fortune",
"level": {
"min": 1,
"max": 3
},
"weight": 10
}
],
"enchantment_count": {
"min": 1,
"max": 2
}
}
],
"xp_reward": {
"min": 1,
"max": 20
},
"currency_reward": {
"min": 1,
"max": 20
}
}
Поля
В массиве tasks хранятся данные о задании.
"task_type": "thequestforge:kill"
- Это ID типа задания, оно говорит что надо сделать что бы прогресс поднялся, собрать предметы, убить сущность и т.д.
"value": 40
- Это ценность задания за единицу задания, то есть если поставить 4, и выпадет собрать 13 камня, то (4 * 13 = 52) ценность данного задания 52. Нужна она для того чтобы награда за квест была справедливая (Поле только для задания!!).
"price": 12
- Это стоимость награды за единицу (Поле только для награды!!).
"target": "minecraft:iron_pickaxe"
- Это цель задания что нужно Найти/Убить.
"multiplier": false
- Это флаг множителя который указывает нужно ли увеличивать награду или задание исходя из редкости? Пример квест на сбор дерева выпал эпической редкости, нужно собрать 30 шт. множитель по умолчанию 1.4 (30 * 1.4 = 42) Как итог нужно будет собрать 42 дерева. (Если у вас появился вопрос, ценность задания будет просчитана по 30 или 42? То ответ 42) .
"weight": 20
- Это вес Задания/Награды то есть шанс на выпадения данного задания.
"count":
{
"min": 1,
"max": 30
}
- Это диапазон количества предметов для сбора, или существ для убийства чтобы выполнить задание.
"enchantment_count": {
"min": 1,
"max": 3
}
- Это диапазон количества зачаров на предмет, в данном примере может выпасти от 1 до 3 зачаров (если данного свойства нету то количество будет 1).
"enchantment": [
{
"id": "minecraft:sharpness",
"level": {
"min": 1,
"max": 5
},
"weight": 10
}
]
- Это массив самих зачаров где :
"id": "minecraft:sharpness"- id зачара."level"- Уровень."weight"- Вес (шанс выпадения).
"tag"
Тут можно задать тег для Предмета/Сущности, (Если хотите выдать зелье, книгу зачара, стрелу с эффектом, то это поле вам поможет).
Как создать квест
После того как группа для квеста была создана, можно перейти к созданию квеста.
Рассмотрим готовый пример example_quest.json которой должен находится по пути
data_pack_name -> data -> guardvillagers* -> quest_template -> example_quest.json* - Тут может быть любой namespace но для наглядности используемguardvillagers.example_quest.json(Тут вариант маленько и сжатого для того чтобы не сильно нагружать вас) :
{
"pool": "farmer",
"type": "LOCAL",
"weight": 100,
"requirement": [],
"requirement_target": [
"minecraft:zombie"
],
"guaranteed_reward": [
"minecraft:iron_ingot"
],
"name": {
"en_us": [
"Lost Harvest",
"Empty Barn"
],
"ru_ru": [
"Потерянный урожай",
"Пустой амбар"
]
},
"description": {
"en_us": [
"%npc_name% needs your help to gather crops."
],
"ru_ru": [
"%npc_name% просит вашей помощи в сборе урожая."
]
},
"group": "thequestforge:example_group",
"task_count": {
"min": 1,
"max": 2
},
"max_reward": 2,
"time_limit": {
"min": 6,
"max": 12
},
"next_quest": "thequestforge:chain_2",
"dialogs": {
"start": {
"text": {
"en_us": ["I need you to get %target-1%. Reward will be %reward-1%."],
"ru_ru": ["Мне нужно, чтобы ты достал %target-1%. Наградой будет %reward-1%."]
},
"buttons": [
{
"text": {
"en_us": ["Accept"],
"ru_ru": ["Принять"]
},
"to_go": "complete",
"actions": ["thequestforge:accept", "thequestforge:save"]
},
{
"text": {
"en_us": ["Decline"],
"ru_ru": ["Отказаться"]
},
"to_go": "exit",
"actions": ["thequestforge:close"]
}
]
},
"complete": {
"text": {
"en_us": ["Thank you! Here is your reward."],
"ru_ru": ["Спасибо! Вот твоя награда."]
},
"buttons": [
{
"text": {
"en_us": ["Collect reward"],
"ru_ru": ["Забрать награду"]
},
"to_go": "exit",
"actions": ["thequestforge:complete", "thequestforge:next_quest"]
}
]
}
}
}
Поля файла Квеста
"pool": "farmer"
- Указывает, к какому пулу (например, профессии жителя) привязан квест.
"type": "LOCAL"
- Тип квеста. Определяет его поведение :
LOCAL- локальный квест для НПС.STORY- тоже локальный квест для НПС но, при сбросе квестов, эти остаются не тронутыми и они остаются существовать дальше.GUILD- Пока не реализовано
"weight": 100
- Шанс (вес) появления этого квеста среди остальных в пуле. Чем выше, тем чаще он будет выпадать.
"requirement": []
- Массив условий для того чтобы квест выбрался. Сами условия смотреть тут
"requirement_target": [
"minecraft:zombie"
]
- Если вы хотите чтобы вашем квесту 100% было нужное вам задание (Например убить зомби), то в данном поле вам нужно написать ID зомби.
Важно чтобы то что вы пропишите (Пример "minecraft:zombie"), то такое задание было в выбранной вами группе для квеста! Если вы хотите чтобы у вас было гарантированное задание, но при этом вы не хотите чтобы оно выпадало просто так (при генерации других квестов), то установите поле
"weight"на 0 для данного задания, тем самым вы 100% исключите данное задание из генерации.
"guaranteed_reward": [
"minecraft:iron_ingot"
]
- Если вы хотите чтобы в данном квесту была 100% нежная вам наград, то в данном поле вы пишете ID нужной награды.
Важно чтобы то что вы пропишите (Пример "minecraft:iron_ingot"), то такая награда была в выбранной вами группе для квеста! Если вы хотите чтобы у вас было гарантированная награда, но при этом вы не хотите чтобы она выпадало просто так (при генерации других квестов), то установите поле
"weight"на 0 для данной награды, тем самым вы 100% исключите данную награду из генерации.
"name": {
"en_us": ["Name1", "Name2", ...],
"ru_ru": ["Имя1", "Имя2", ...]
},
"description": {
"en_us": ["Description1", "Description2", ...],
"ru_ru": ["Описание1", "Описание2", ...]
}
ВАЖНО ЧТОБЫ КОЛИЧЕСТВО ЛОКАЛИЗАЦИЙ ВЕЗДЕ БЫЛО ОДИНАКОВО (если "en_us" 5 названий, значит в "ru_ru" тоже должно быть 5 названий) , А ТАК ЖЕ КЛЮЧ "en_us" ОБЯЗАТЕЛЬНО ДОЛЖЕН СУЩЕСТВОВАТЬ!!
- Объекты локализации (поддерживают
en_us,ru_ruи т.д.). Внутри языкового ключа находится массив строк. Движок выберет случайную строку из массива при генерации, что позволяет делать квесты более разнообразными.
В тексте можно использовать переменные, например
%npc_name%, которые автоматически заменятся на имя персонажа. Детально тут
"group": "guardvillagers:example_group"
- Это ID группы (о которой мы говорили ранее), из которой квест будет брать список заданий и наград.
"task_count": {
"min": 1,
"max": 2
}
- Диапазон. Указывает, сколько именно заданий из привязанной
groupбудет выдано игроку (например, от 1 до 2).
"max_reward": 2
- Максимальное количество наград, которые игрок получит из пула наград группы. Если данного параметра нету, то умолчанию будет стоять 1.
"time_limit": {
"min": 6,
"max": 12
}
- (Опционально) Диапазон времени в игровых днях на выполнение квеста. Если квест ограничен по времени, здесь указываются минимальные и максимальные значения таймера. Если данного параметра не будет, то квест будет неограничен по времени.
"next_quest": "thequestforge:chain_2"
- (Опционально) Поле для создания цепочек квестов. Указывает ID следующего квеста, который станет доступен после завершения текущего (например,
"thequestforge:chain_2").
Блок dialogs (Диалоги)
В этом объекте прописывается вся ветка общения с NPC. Состоит из "узлов" (например, start, complete, exit или кастомных, вроде dialog_1).
Самый первый узел диалога должен называться "start"
Структура узла диалога:
"text": {
"en_us": [
"Greeting text..."
],
"ru_ru": [
"Текст приветствия..."
]
}
- Текст, который говорит NPC. Здесь работают специальные переменные.
ВАЖНО ЧТОБЫ КОЛИЧЕСТВО ЛОКАЛИЗАЦИЙ ВЕЗДЕ БЫЛО ОДИНАКОВО (если "en_us" 5 названий, значит в "ru_ru" тоже должно быть 5 названий) , А ТАК ЖЕ КЛЮЧ "en_us" ОБЯЗАТЕЛЬНО ДОЛЖЕН СУЩЕСТВОВАТЬ!!
"buttons": []
- Массив кнопок для ответа игрока.
Кнопки в диалоге
"text": {
"en_us": [
"Greeting text..."
],
"ru_ru": [
"Текст приветствия..."
]
}
- Текст на кнопке.
ВАЖНО ЧТОБЫ КОЛИЧЕСТВО ЛОКАЛИЗАЦИЙ ВЕЗДЕ БЫЛО ОДИНАКОВО (если "en_us" 5 названий, значит в "ru_ru" тоже должно быть 5 названий) , А ТАК ЖЕ КЛЮЧ "en_us" ОБЯЗАТЕЛЬНО ДОЛЖЕН СУЩЕСТВОВАТЬ!!
"give": [
{
"id": "minecraft:oak_log",
"count": 15,
"tag": "{display:{Name:'{\"text\":\"Some name\",\"italic\":false}'}}"
}
]
- Данное поле массив с простой формой хранения предметов, если надо выдать игроку некие предметы то можно использовать это поле в кнопке.
"remove": [
{
"id": "minecraft:oak_log",
"count": 15,
"tag": "{display:{Name:'{\"text\":\"Some name\",\"italic\":false}'}}"
}
]
- попытается забрать у игрока предметы, и даже сравнит теги, при отсутствии предметов перейдёт на "alt_to_go", если он есть.
"functions": []
- Массив функций, которые выполнятся при нажатии на кнопку, функции это ванильная механика игры (сборник команд которые выполняются одновременно).
"to_go": "dialog_2"
- Имя узла диалога, на который перекинет игрока при нажатии (например,
"dialog_2").
"alt_to_go": "dialog_3"
- Альтернативный узел для перехода (например, если игрок принёс не все предметы).
"actions": ["thequestforge:complete", "thequestforge:next_quest"]
- Массив системных действий, которые происходят при нажатии.