Как сделать дроп вещей

Динамический лут в играх: что стоит учитывать

Люди всех возрастов любят азарт, будь то Kinder Surprise, блэкджек или компьютерные игры. Представьте, у вас в игре есть две коробки: на одной написано «Вы получите 100 монет«, а на второй — “Вы получите 50-1000 монет”. Сразу понятно, вокруг какой из коробок будет больше ажиотажа. А если при этом коробки покупаются за реальные деньги — мы получим политику и головную боль для разработчиков.

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

Почему об этом мало пишут?

Где это сделано хорошо: Diablo III Если во время игры вы были особо неудачливы и вам никак не падают легендарные вещи — с течением времени их шанс выпадения будет постоянно увеличиваться.

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

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

В отдельных случаях даже приходится вмешиваться на уровне государственных указов, как, например, поступили с лутбоксами в Китае.

  • Требуется выводить точный шанс выпадения вещей, включенных в состав лутбокса.
  • Нельзя открыть платный лутбокс более 30 раз в сутки.
  • Шанс получения желаемой вещи должен увеличиваться с числом открытий лутбокса.
  • Должна быть возможность гарантированного получения вещи из лутбокса за N открытий, вне зависимости от указанного шанса.

Какие бывают механики?

В большинстве игр, где имеется система динамического лута, можно вычленить основные приемы, которыми могут пользоваться гейм-дизайнеры. Давайте попробуем разобрать по порядку основные из них:

Слоты дропа

Например: Открывая сундуки в Overwatch, вы всегда
получаете по 4 предмета, будь то:
стикер на стену, скин для персонажа, анимация или эмоция.

Слот может обладать индивидуальным содержимым, отличным от других слотов, например, выдавать только валюту.

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

Попытки подбора

Фактически, попытка — это одна итерация подбора лута. Например, у нас есть таблица дропа ресурсов и счетчик попыток, равный 3-м. Это означает, что мы три раза пойдем в одну и ту же таблицу и попытаемся извлечь награду, добавив ее в итоговый дроп. Так, например, работает алгоритм подбора лута в Diablo II.

  • Плюсы: можно сэкономить на объеме заводимых данных.
  • Минусы: необходимо понимать, что новая попытка может выбрать предмет, ранее выбранный в предыдущей итерации. Иногда такое поведение может быть нежелательным.
Читайте также:  Как iphone сделать тише

Шанс выпадения

Буквально. Указывается число от 0 до N, где 0 означает, что предмет не выпадет никогда, а N — что выпадет в 100% случаев. Для экономии размерности часто используются целочисленные значения от 0 до 100.

  • Плюсы: наглядно для дизайнера, удобно для описания случаев, когда “ничего не выпало”.
  • Минусы: неудобен, если среди нескольких вещей с разным шансом необходимо выбрать одну, сумма шансов может превысить 100% и тогда будет непонятно, что именно должно упасть.

Вес

Вес — это некая абстрактная мера частоты, с которой должен встречаться предмет. Если вес предмета высокий — он будет выпадать чаще остальных. Итоговый процент шанса выпадения здесь напрямую зависит от веса всех предметов из выборки. Например, у вас есть три вещи, с весами 10, 15 и 25. Шанс выпадения каждой из них считается по формуле и составляет 20%, 30% и 50% соответственно.

Для удобства: Иногда удобнее для обозначения веса указывать его, как , где value — это ценность предмета. Таким образом, более “дорогая” вещь будет автоматически иметь меньший шанс выпадения.

Диапазон количества

Когда мы хотим, чтобы игрок получал произвольное количество предметов, но в допустимом диапазоне, — обычно указываются пограничные минимальные и максимальные значения, например от 3 до 9 включительно

  • Плюсы: можно указывать точный диапазон количества предметов (вместо медианного значения и дельты, например)
  • Минусы: Параметр сильно влияет на итоговую ценность выпадающих вещей, но при этом может быть не связан с вероятностью/весом самого предмета

Условия выпадения

Нюанс: У подобного условия может быть два режима работы, в случае, если игрок не удовлетворяет условиям:

  • Первый: проверка условия идет после того, как вещь выбрана в дроп (и тогда игрок не получает ничего).
  • Второй: проверка идет перед выбором вещи, и тогда игрок взамен получит что-то другое, из оставшихся вещей в списке дропа.

Фильтры

Иногда для заведения дропа может потребоваться указать множество предметов с одинаковыми или похожими характеристиками. Чтобы не указывать каждую вещь по отдельности — можно группировать их по фильтрам. Например, за убийство босса игрок может получить любое оружие с требованиями по уровням с 10 по 15.

  • Плюсы: меньше работ по обновлению дропов, если что-то добавили или удалили из игры
  • Минусы: как и в случае с диапазоном количества — предметам из результатов работы фильтра может требоваться индивидуальное указание веса или вероятности.

Какая стояла задача?

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

  1. В луте должны присутствовать ярко выраженные слоты.
  2. У слота может быть вероятность выпадения, отличная от 1.
  3. У слота, а также у каждой вещи, могут быть условия для выпадения.
  4. В каждом слоте может быть перечислен свой список вещей, которые могут падать.
  5. У каждой вещи из списка должен быть свой вес.
  6. Каждой вещи надо указывать точный диапазон количества min/max.
  7. Вещь в списке может быть описана набором фильтров, а не конкретным идентификатором.
  8. У вещи в списке могут быть аргументы, модифицирующие ее состояние (например — более редкое качество).
  9. Должна быть настройка, чтобы одна и та же вещь не могла быть сгенерирована в двух разных слотах.
  10. Должна быть возможность объединять вещи в группы, чтобы при наличии в сгенерированном дропе одной вещи из группы, — не падали все остальные.
Читайте также:  Аква мозаика как сделать

Что в итоге получилось?

По итогам, вышло две структуры: список слотов динамического лута и листинг предметов.

Пример динамического дропа

Пример листинга предметов

Алгоритм подбора лута при этом работает следующим образом:

  1. Берем элемент из массива reward_slots.
  2. Если игрок прошел условия из drop_requirements — переходим дальше, иначе — берем следующий элемент из reward_slots.
  3. Роллим дроп по drop_probability. Если успешно, то переходим дальше, иначе — берем следующий элемент из reward_slots.
  4. Перебираем все элементы связанного с слотом списка drop_list:
    • Исключаем все предметы, не прошедшие проверку по item_requirements.
    • Исключаем все предметы, которые уже есть в сгенерированном дропе в случае, если drop_mode выставлен как unrepeatable.
    • Исключаем предметы, у которых в tags проставлен такой же тег, как в предметах, уже добавленных в текущий сгенерированный экземпляр дропа.
  5. Из оставшегося списка предметов выбираем один, воспользовавшись роллом по их весам из weight.
  6. Вносим финальные уточнения в выбранный предмет:
    • Отбираем список предметов, подходящих нам по item_type и item_requirements, выбираем из них случайный.
    • Модифицируем выбранный предмет через аргументы в args.
    • Выбираем количество падающих предметов, взяв случайное число в интервале из amount.
  7. Готово. Добавляем предмет в итоговый дроп и переходим к следующему слоту из reward_slots.

Какие нюансы у решения?

Бюджет

В текущем формате записи дропа бюджет вообще не предусмотрен. Как следствие — дизайнер не может просто указать “выдай таких-то вещей, общей стоимостью N монет” и должен считать такой баланс вручную, отдельно. Учитывая, что в большинстве случаев так и делается, — это не проблема.

Переиспользование данных

В первой редакции системы дропа вообще не было отдельно вынесенных листингов предметов и фактически каждый дроп заводился отдельно. Используя листинги, можно добиться хоть какого-то переиспользования.

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

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

Количество выпадающих предметов и аргументы

Самое узкое место решения и источник компромиссов:

  • Количество выпадающих предметов указывается в диапазоне [min, max] и его модификация извне пока остается не реализованной. В случае, если диапазон не устраивает, — придется в листинге предметов создавать еще одну запись предмета, но уже с другим количеством.
  • Аргументы задают свойства предметов (например, что выпавший меч должен быть редкого качества) и также не могут быть изменены извне.

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

Как можно персонализировать лут?

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

Читайте также:  Как сделать англ ник

Глобальный модификатор веса

Фактически, мы знаем, что ценные вещи имеют малый вес, а дешевые — большой. То есть, чтобы наградить игрока, — нам нужно увеличить вес ценных вещей и/или уменьшить вес дешевых вещей. Для этого можно ввести в игру коэффициент, привязанный к конкретному игроку и меняющийся по игровым триггерам. Проще всего его воздействие выразить через формулу , где:

  • Если мы хотим дать игроку более ценные вещи — понижаем значение X в диапазоне 0 1
  • Если же хотим выдавать честно, то X = 1

Посмотрите, как в таких случаях меняется итоговый шанс выпадения вещи:

Исходный вес x=0.5 x=1 x=1.5
1 15.63% 6.25% 2.28%
5 34.95% 31.25% 25.52%
10 49.42% 62.5% 72.19%

Точечный модификатор веса

Могут быть ситуации, когда требуется модификация отдельной группы предметов. В таком случае, в настройках заводится описание группы вещей (списком или фильтрами) и отдельный модификатор, равный 1 по умолчанию.

Далее, в зависимости от игровых событий, мы или увеличиваем, или уменьшаем этот модификатор.

В момент же, когда игроку будет требоваться выдать дроп, перед выбором предмета из листинга, — мы смотрим какие из вещей включены в нашу группу предметов и домножаем их вес на текущее значение модификатора:

Шаговое изменение шанса выпадения

Так как у слота дропа есть и шанс выпадения, и условия выпадения, — можно создать несколько слотов с одинаковым содержимым и разными вероятностями выпадения (и не пересекающимися условиями). Таким образом, в один момент времени, игрок может соответствовать условиям только одного из слотов, из чего и будет складываться его шанс получения награды.

Гарантированное выпадение

Иногда нам будет требоваться гарантированно выдавать какой-то предмет (или предмет из группы) на N-ное получение дропа в случае, если в интервале от 0 до N такой предмет еще не падал. Например для лутбоксов в Китае.

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

Как следствие, если личный счетчик меньше максимума и предмет не выпал, — увеличиваем личный счетчик на 1. Если личный счетчик стал равен числу из глобальной таблицы — добавляем предмет в дроп, игнорируя обычные правила учета веса или вероятности. При этом, после выдачи вещи в дроп (в т.ч. обычным способом), — обнуляем счетчик у игрока.

Примечание: Таким образом можно, например, создать лутбокс, где каждое 50-е открытие будет гарантированно выдавать легендарное оружие, если предыдущие 49 открытий такого не выдали.

Заключение

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

Источник

Поделиться с друзьями
Ответ и точка